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 com.google.crypto.tink.util.Bytes; 20 import java.security.GeneralSecurityException; 21 import java.security.KeyPair; 22 import java.security.interfaces.ECPrivateKey; 23 import java.security.interfaces.ECPublicKey; 24 25 /** 26 * HKDF-based ECIES-KEM (key encapsulation mechanism) for ECIES sender. 27 * 28 * @since 1.0.0 29 */ 30 public final class EciesHkdfSenderKem { 31 private final ECPublicKey recipientPublicKey; 32 33 /** A container for key parts generated by the KEM. */ 34 public static final class KemKey { 35 private final Bytes kemBytes; 36 private final Bytes symmetricKey; 37 KemKey(final byte[] kemBytes, final byte[] symmetricKey)38 public KemKey(final byte[] kemBytes, final byte[] symmetricKey) { 39 if (kemBytes == null) { 40 throw new NullPointerException("KemBytes must be non-null"); 41 } 42 if (symmetricKey == null) { 43 throw new NullPointerException("symmetricKey must be non-null"); 44 } 45 this.kemBytes = Bytes.copyFrom(kemBytes); 46 this.symmetricKey = Bytes.copyFrom(symmetricKey); 47 } 48 getKemBytes()49 public byte[] getKemBytes() { 50 return kemBytes.toByteArray(); 51 } 52 getSymmetricKey()53 public byte[] getSymmetricKey() { 54 return symmetricKey.toByteArray(); 55 } 56 } 57 EciesHkdfSenderKem(final ECPublicKey recipientPublicKey)58 public EciesHkdfSenderKem(final ECPublicKey recipientPublicKey) { 59 this.recipientPublicKey = recipientPublicKey; 60 } 61 generateKey( String hmacAlgo, final byte[] hkdfSalt, final byte[] hkdfInfo, int keySizeInBytes, EllipticCurves.PointFormatType pointFormat)62 public KemKey generateKey( 63 String hmacAlgo, 64 final byte[] hkdfSalt, 65 final byte[] hkdfInfo, 66 int keySizeInBytes, 67 EllipticCurves.PointFormatType pointFormat) 68 throws GeneralSecurityException { 69 KeyPair ephemeralKeyPair = EllipticCurves.generateKeyPair(recipientPublicKey.getParams()); 70 ECPublicKey ephemeralPublicKey = (ECPublicKey) ephemeralKeyPair.getPublic(); 71 ECPrivateKey ephemeralPrivateKey = (ECPrivateKey) ephemeralKeyPair.getPrivate(); 72 byte[] sharedSecret = EllipticCurves.computeSharedSecret( 73 ephemeralPrivateKey, recipientPublicKey); 74 byte[] kemBytes = 75 EllipticCurves.pointEncode( 76 ephemeralPublicKey.getParams().getCurve(), pointFormat, ephemeralPublicKey.getW()); 77 byte[] symmetricKey = 78 Hkdf.computeEciesHkdfSymmetricKey( 79 kemBytes, sharedSecret, hmacAlgo, hkdfSalt, hkdfInfo, keySizeInBytes); 80 return new KemKey(kemBytes, symmetricKey); 81 } 82 } 83