diff options
Diffstat (limited to 'security-utils/src')
-rw-r--r-- | security-utils/src/main/java/com/yahoo/security/SharedKeyGenerator.java | 16 | ||||
-rw-r--r-- | security-utils/src/test/java/com/yahoo/security/SharedKeyTest.java | 16 |
2 files changed, 28 insertions, 4 deletions
diff --git a/security-utils/src/main/java/com/yahoo/security/SharedKeyGenerator.java b/security-utils/src/main/java/com/yahoo/security/SharedKeyGenerator.java index 8a1a7dd3688..66a87a94707 100644 --- a/security-utils/src/main/java/com/yahoo/security/SharedKeyGenerator.java +++ b/security-utils/src/main/java/com/yahoo/security/SharedKeyGenerator.java @@ -62,10 +62,7 @@ public class SharedKeyGenerator { public static SecretSharedKey generateForReceiverPublicKey(PublicKey receiverPublicKey, KeyId keyId) { var secretKey = generateRandomSecretAesKey(); - // We protect the integrity of the key ID by passing it as AAD. - var sealed = HPKE.sealBase((XECPublicKey) receiverPublicKey, EMPTY_BYTES, keyId.asBytes(), secretKey.getEncoded()); - var sealedSharedKey = new SealedSharedKey(keyId, sealed.enc(), sealed.ciphertext()); - return new SecretSharedKey(secretKey, sealedSharedKey); + return internalSealSecretKeyForReceiver(secretKey, receiverPublicKey, keyId); } public static SecretSharedKey fromSealedKey(SealedSharedKey sealedKey, PrivateKey receiverPrivateKey) { @@ -74,6 +71,17 @@ public class SharedKeyGenerator { return new SecretSharedKey(new SecretKeySpec(secretKeyBytes, "AES"), sealedKey); } + public static SecretSharedKey reseal(SecretSharedKey secret, PublicKey receiverPublicKey, KeyId keyId) { + return internalSealSecretKeyForReceiver(secret.secretKey(), receiverPublicKey, keyId); + } + + private static SecretSharedKey internalSealSecretKeyForReceiver(SecretKey secretKey, PublicKey receiverPublicKey, KeyId keyId) { + // We protect the integrity of the key ID by passing it as AAD. + var sealed = HPKE.sealBase((XECPublicKey) receiverPublicKey, EMPTY_BYTES, keyId.asBytes(), secretKey.getEncoded()); + var sealedSharedKey = new SealedSharedKey(keyId, sealed.enc(), sealed.ciphertext()); + return new SecretSharedKey(secretKey, sealedSharedKey); + } + // A given key+IV pair can only be used for one single encryption session, ever. // Since our keys are intended to be inherently single-use, we can satisfy that // requirement even with a fixed IV. This avoids the need for explicitly including diff --git a/security-utils/src/test/java/com/yahoo/security/SharedKeyTest.java b/security-utils/src/test/java/com/yahoo/security/SharedKeyTest.java index 4e64bc3e9aa..23e22345cc6 100644 --- a/security-utils/src/test/java/com/yahoo/security/SharedKeyTest.java +++ b/security-utils/src/test/java/com/yahoo/security/SharedKeyTest.java @@ -21,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; public class SharedKeyTest { private static final KeyId KEY_ID_1 = KeyId.ofString("1"); + private static final KeyId KEY_ID_2 = KeyId.ofString("2"); @Test void generated_secret_key_is_128_bit_aes() { @@ -45,6 +46,21 @@ public class SharedKeyTest { } @Test + void secret_key_can_be_resealed_for_another_receiver() { + var originalReceiverKp = KeyUtils.generateX25519KeyPair(); + var secondaryReceiverKp = KeyUtils.generateX25519KeyPair(); + var myShared = SharedKeyGenerator.generateForReceiverPublicKey(originalReceiverKp.getPublic(), KEY_ID_1); + var theirShared = SharedKeyGenerator.reseal(myShared, secondaryReceiverKp.getPublic(), KEY_ID_2); + + var publicToken = theirShared.sealedSharedKey().toTokenString(); + var theirSealed = SealedSharedKey.fromTokenString(publicToken); + assertEquals(KEY_ID_2, theirSealed.keyId()); + theirShared = SharedKeyGenerator.fromSealedKey(theirSealed, secondaryReceiverKp.getPrivate()); + // Should be same internal secret key + assertArrayEquals(myShared.secretKey().getEncoded(), theirShared.secretKey().getEncoded()); + } + + @Test void token_v1_representation_is_stable() { var receiverPrivate = KeyUtils.fromBase58EncodedX25519PrivateKey("GFg54SaGNCmcSGufZCx68SKLGuAFrASoDeMk3t5AjU6L"); var receiverPublic = KeyUtils.fromBase58EncodedX25519PublicKey( "5drrkakYLjYSBpr5Haknh13EiCYL36ndMzK4gTJo6pwh"); |