• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 package com.google.crypto.tink.subtle;
18 
19 import java.security.GeneralSecurityException;
20 import javax.crypto.Mac;
21 import javax.crypto.spec.SecretKeySpec;
22 
23 /**
24  * This class implements HMAC-based Extract-and-Expand Key Derivation Function (HKDF), as described
25  * in <a href="https://tools.ietf.org/html/rfc5869">RFC 5869</a>.
26  *
27  * @since 1.0.0
28  */
29 public final class Hkdf {
30 
31   /**
32    * Computes an HKDF.
33    *
34    * @param macAlgorithm the MAC algorithm used for computing the Hkdf. I.e., "HMACSHA1" or
35    *     "HMACSHA256".
36    * @param ikm the input keying material.
37    * @param salt optional salt. A possibly non-secret random value. If no salt is provided (i.e. if
38    *     salt has length 0) then an array of 0s of the same size as the hash digest is used as salt.
39    * @param info optional context and application specific information.
40    * @param size The length of the generated pseudorandom string in bytes. The maximal size is
41    *     255.DigestSize, where DigestSize is the size of the underlying HMAC.
42    * @return size pseudorandom bytes.
43    * @throws GeneralSecurityException if the {@code macAlgorithm} is not supported or if {@code
44    *     size} is too large or if {@code salt} is not a valid key for macAlgorithm (which should not
45    *     happen since HMAC allows key sizes up to 2^64).
46    */
computeHkdf( String macAlgorithm, final byte[] ikm, final byte[] salt, final byte[] info, int size)47   public static byte[] computeHkdf(
48       String macAlgorithm, final byte[] ikm, final byte[] salt, final byte[] info, int size)
49       throws GeneralSecurityException {
50     Mac mac = EngineFactory.MAC.getInstance(macAlgorithm);
51     if (size > 255 * mac.getMacLength()) {
52       throw new GeneralSecurityException("size too large");
53     }
54     if (salt == null || salt.length == 0) {
55       // According to RFC 5869, Section 2.2 the salt is optional. If no salt is provided
56       // then HKDF uses a salt that is an array of zeros of the same length as the hash digest.
57       mac.init(new SecretKeySpec(new byte[mac.getMacLength()], macAlgorithm));
58     } else {
59       mac.init(new SecretKeySpec(salt, macAlgorithm));
60     }
61     byte[] prk = mac.doFinal(ikm);
62     byte[] result = new byte[size];
63     int ctr = 1;
64     int pos = 0;
65     mac.init(new SecretKeySpec(prk, macAlgorithm));
66     byte[] digest = new byte[0];
67     while (true) {
68       mac.update(digest);
69       mac.update(info);
70       mac.update((byte) ctr);
71       digest = mac.doFinal();
72       if (pos + digest.length < size) {
73         System.arraycopy(digest, 0, result, pos, digest.length);
74         pos += digest.length;
75         ctr++;
76       } else {
77         System.arraycopy(digest, 0, result, pos, size - pos);
78         break;
79       }
80     }
81     return result;
82   }
83 
84   /**
85    * Computes symmetric key for ECIES with HKDF from the provided parameters.
86    *
87    * @param ephemeralPublicKeyBytes the encoded ephemeral public key, i.e. the KEM part of the
88    *     hybrid encryption. In some versions of ECIES (e.g. IEEE P1363a) this argument is optional.
89    *     Shoup strongly prefers the inclusion of this argument in
90    *     http://eprint.iacr.org/2001/112.pdf (see discussion of the value C0 in Section 15.6, and
91    *     15.6.1)
92    * @param sharedSecret the shared DH secret. This typically is the x-coordinate of the secret
93    *     point.
94    * @param hmacAlgo the HMAC used (e.g. "HmacSha256")
95    * @param hkdfInfo TODO(bleichen): determine what are good values for Info and salt and what are
96    *     not good values. The ISO standard proposal http://eprint.iacr.org/2001/112.pdf does not
97    *     allow additional values for the key derivation (see Section 15.6.2)
98    * @param hkdfSalt
99    * @param keySizeInBytes the size of the key material for the DEM key.
100    * @throws GeneralSecurityException if hmacAlgo is not supported
101    */
computeEciesHkdfSymmetricKey( final byte[] ephemeralPublicKeyBytes, final byte[] sharedSecret, String hmacAlgo, final byte[] hkdfSalt, final byte[] hkdfInfo, int keySizeInBytes)102   public static byte[] computeEciesHkdfSymmetricKey(
103       final byte[] ephemeralPublicKeyBytes,
104       final byte[] sharedSecret,
105       String hmacAlgo,
106       final byte[] hkdfSalt,
107       final byte[] hkdfInfo,
108       int keySizeInBytes)
109       throws GeneralSecurityException {
110     byte[] hkdfInput = Bytes.concat(ephemeralPublicKeyBytes, sharedSecret);
111     return Hkdf.computeHkdf(hmacAlgo, hkdfInput, hkdfSalt, hkdfInfo, keySizeInBytes);
112   }
113 
Hkdf()114   private Hkdf() {}
115 }
116