2121import com .google .crypto .tink .hybrid .HpkePublicKey ;
2222import com .google .crypto .tink .subtle .Bytes ;
2323import com .google .crypto .tink .subtle .EllipticCurves ;
24+ import com .google .crypto .tink .subtle .EllipticCurves .PointFormatType ;
2425import com .google .errorprone .annotations .Immutable ;
2526import java .security .GeneralSecurityException ;
27+ import java .security .spec .ECPoint ;
2628
2729/**
2830 * A class with functions helping for HPKE implementations based on Android Keystore.
@@ -115,7 +117,7 @@ private static void validateParameters(HpkeParameters parameters)
115117 * <p>The ciphertext must have been encrypted with the public key used to create this helper
116118 * object. The encapsulated key must be in encapsulatedKey. dhSharedSecret1 must be the
117119 * Diffie-Hellman shared secrets computed between the receiver and encapsulated key,
118- * dhSharedSecret2 must be the Diffie-Hellman secret between the reciever and the sender key.
120+ * dhSharedSecret2 must be the Diffie-Hellman secret between the receiver and the sender key.
119121 */
120122 public byte [] decryptAuthenticatedWithEncapsulatedKeyAndP256SharedSecret (
121123 byte [] encapsulatedKey ,
@@ -135,4 +137,44 @@ public byte[] decryptAuthenticatedWithEncapsulatedKeyAndP256SharedSecret(
135137 HpkeUtil .AUTH_MODE , encapsulatedKey , derivedSharedSecret , kem , kdf , aead , info );
136138 return context .open (ciphertext , ciphertextOffset , EMPTY_ASSOCIATED_DATA );
137139 }
140+
141+ /**
142+ * Encrypts a message.
143+ *
144+ * <p>The message will be encrypted for `theirPublicKeyByteArray` and authenticated with
145+ * `ourPublicKey`. The value in emphemeralPublicKey must contain the public key piont of an
146+ * ephemerally generated key. dhSharedSecret1 must be the Diffie-Hellman shared secrets computed
147+ * between the receiver and emphemeralKey. dhSharedSecret2 must be the Diffie-Hellman secret
148+ * between the receiver and the sender key.
149+ */
150+ public byte [] encryptAuthenticatedWithEncapsulatedKeyAndP256SharedSecret (
151+ ECPoint emphemeralPublicKey ,
152+ byte [] dhSharedSecret1 ,
153+ byte [] dhSharedSecret2 ,
154+ byte [] plaintext ,
155+ byte [] contextInfo )
156+ throws GeneralSecurityException {
157+ byte [] emphemeralPublicKeyByteArray =
158+ EllipticCurves .pointEncode (
159+ EllipticCurves .CurveType .NIST_P256 , PointFormatType .UNCOMPRESSED , emphemeralPublicKey );
160+ byte [] dhSharedSecret = Bytes .concat (dhSharedSecret1 , dhSharedSecret2 );
161+ byte [] derivedSharedSecret =
162+ NistCurvesHpkeKem .fromCurve (EllipticCurves .CurveType .NIST_P256 )
163+ .deriveKemSharedSecret (
164+ dhSharedSecret ,
165+ emphemeralPublicKeyByteArray ,
166+ theirPublicKeyByteArray ,
167+ ourPublicKeyByteArray );
168+ HpkeContext context =
169+ HpkeContext .createContext (
170+ HpkeUtil .AUTH_MODE ,
171+ emphemeralPublicKeyByteArray ,
172+ derivedSharedSecret ,
173+ kem ,
174+ kdf ,
175+ aead ,
176+ contextInfo );
177+ return Bytes .concat (
178+ emphemeralPublicKeyByteArray , context .seal (plaintext , EMPTY_ASSOCIATED_DATA ));
179+ }
138180}
0 commit comments