From 64732e3f04bf9d01d5885cd0afdff9f2fc8e8c5c Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Fri, 25 Oct 2024 12:24:13 +0200 Subject: [PATCH 1/3] Add test for reencryption using AEAD --- .../test/AEADProtectedPGPSecretKeyTest.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/AEADProtectedPGPSecretKeyTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/AEADProtectedPGPSecretKeyTest.java index da3f4cc11c..0185364ce5 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/AEADProtectedPGPSecretKeyTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/AEADProtectedPGPSecretKeyTest.java @@ -32,9 +32,12 @@ import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.bc.BcPGPObjectFactory; +import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; +import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor; import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider; import org.bouncycastle.openpgp.operator.bc.BcAEADSecretKeyEncryptorBuilder; import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder; +import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyEncryptorBuilder; import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider; import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair; import org.bouncycastle.openpgp.operator.jcajce.JcaAEADSecretKeyEncryptorBuilder; @@ -65,6 +68,8 @@ public void performTest() testUnlockKeyWithWrongPassphraseBc(); testUnlockKeyWithWrongPassphraseJca(); + + reencryptKey(); } private void unlockTestVector() @@ -358,6 +363,58 @@ private void lockUnlockKeyJca( keyPair.getPrivateKey().getPrivateKeyDataPacket().getEncoded(), dec.getPrivateKeyDataPacket().getEncoded()); } + private void reencryptKey() throws PGPException { + reencryptKeyBc(); + reencryptKeyJca(); + } + + private void reencryptKeyJca() + { + + } + + private void reencryptKeyBc() + throws PGPException + { + Ed25519KeyPairGenerator gen = new Ed25519KeyPairGenerator(); + gen.init(new Ed25519KeyGenerationParameters(new SecureRandom())); + AsymmetricCipherKeyPair kp = gen.generateKeyPair(); + Date creationTime = currentTimeRounded(); + String passphrase = "recycle"; + PGPKeyPair keyPair = new BcPGPKeyPair(PublicKeyPacket.VERSION_6, PublicKeyAlgorithmTags.Ed25519, kp, creationTime); + + PBESecretKeyEncryptor cfbEncBuilder = new BcPBESecretKeyEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_128) + .build(passphrase.toCharArray()); + PGPDigestCalculatorProvider digestProv = new BcPGPDigestCalculatorProvider(); + + // Encrypt key using CFB mode + PGPSecretKey cfbEncKey = new PGPSecretKey( + keyPair.getPrivateKey(), + keyPair.getPublicKey(), + digestProv.get(HashAlgorithmTags.SHA1), + true, + cfbEncBuilder); + + PBESecretKeyDecryptor cfbDecryptor = new BcPBESecretKeyDecryptorBuilder(digestProv) + .build(passphrase.toCharArray()); + + BcAEADSecretKeyEncryptorBuilder aeadEncBuilder = new BcAEADSecretKeyEncryptorBuilder( + AEADAlgorithmTags.OCB, SymmetricKeyAlgorithmTags.AES_128, + S2K.Argon2Params.memoryConstrainedParameters()); + + // Reencrypt key using AEAD + PGPSecretKey aeadEncKey = PGPSecretKey.copyWithNewPassword( + cfbEncKey, + cfbDecryptor, + aeadEncBuilder.build( + passphrase.toCharArray(), + cfbEncKey.getPublicKey().getPublicKeyPacket())); + + PBESecretKeyDecryptor aeadDecryptor = new BcPBESecretKeyDecryptorBuilder(digestProv) + .build(passphrase.toCharArray()); + isNotNull(aeadEncKey.extractPrivateKey(aeadDecryptor)); + } + public static void main(String[] args) { runTest(new AEADProtectedPGPSecretKeyTest()); From fe12757b9f96f9ae814e535cf04cd15097b6e1d3 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Fri, 25 Oct 2024 12:59:50 +0200 Subject: [PATCH 2/3] PGPSecretKey.copyWithNewPassword: Fix S2KUsage if newKeyEncryptor is using AEAD --- .../java/org/bouncycastle/openpgp/PGPSecretKey.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java index e53ab7714e..434bea210f 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java @@ -991,7 +991,15 @@ public static PGPSecretKey copyWithNewPassword( SecretKeyPacket secret; - secret = generateSecretKeyPacket(!(key.secret instanceof SecretSubkeyPacket), key.secret.getPublicKeyPacket(), newEncAlgorithm, s2kUsage, s2k, iv, keyData); + if (newKeyEncryptor.getAeadAlgorithm() > 0) + { + s2kUsage = SecretKeyPacket.USAGE_AEAD; + secret = generateSecretKeyPacket(!(key.secret instanceof SecretSubkeyPacket), key.secret.getPublicKeyPacket(), newEncAlgorithm, newKeyEncryptor.getAeadAlgorithm(), s2kUsage, s2k, iv, keyData); + } + else + { + secret = generateSecretKeyPacket(!(key.secret instanceof SecretSubkeyPacket), key.secret.getPublicKeyPacket(), newEncAlgorithm, s2kUsage, s2k, iv, keyData); + } return new PGPSecretKey(secret, key.pub); } From efaa203e0b7e83712013258a2e344d6a93860029 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 31 Oct 2024 15:11:28 +0100 Subject: [PATCH 3/3] Fix NPE in copyWithNewPassword --- pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java index 434bea210f..1e8288716c 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKey.java @@ -991,7 +991,7 @@ public static PGPSecretKey copyWithNewPassword( SecretKeyPacket secret; - if (newKeyEncryptor.getAeadAlgorithm() > 0) + if (newKeyEncryptor != null && newKeyEncryptor.getAeadAlgorithm() > 0) { s2kUsage = SecretKeyPacket.USAGE_AEAD; secret = generateSecretKeyPacket(!(key.secret instanceof SecretSubkeyPacket), key.secret.getPublicKeyPacket(), newEncAlgorithm, newKeyEncryptor.getAeadAlgorithm(), s2kUsage, s2k, iv, keyData);