diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/Curve25519PrivateKeyEncodingTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/Curve25519PrivateKeyEncodingTest.java index 96ecc77a44..9e8942ed7a 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/Curve25519PrivateKeyEncodingTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/Curve25519PrivateKeyEncodingTest.java @@ -2,14 +2,15 @@ import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; -import org.bouncycastle.bcpg.*; +import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.generators.X25519KeyPairGenerator; import org.bouncycastle.crypto.params.X25519KeyGenerationParameters; import org.bouncycastle.crypto.params.X25519PrivateKeyParameters; import org.bouncycastle.jcajce.spec.XDHParameterSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openpgp.*; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyPair; import org.bouncycastle.openpgp.operator.bc.BcPGPKeyConverter; import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyConverter; @@ -17,7 +18,12 @@ import org.bouncycastle.util.Arrays; import java.io.IOException; -import java.security.*; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.SecureRandom; import java.util.Date; /** @@ -169,7 +175,8 @@ public boolean containsSubsequence(byte[] sequence, byte[] subsequence) /** * Test proper functionality of the {@link #containsSubsequence(byte[], byte[])} method. */ - private void containsTest() { + private void containsTest() + { // Make sure our containsSubsequence method functions correctly byte[] s = new byte[] {0x00, 0x01, 0x02, 0x03}; isTrue(containsSubsequence(s, new byte[] {0x00, 0x01})); diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedEd25519KeyPairTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedEd25519KeyPairTest.java index 7a2cf69b25..7ff616c852 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedEd25519KeyPairTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedEd25519KeyPairTest.java @@ -1,6 +1,10 @@ package org.bouncycastle.openpgp.test; -import org.bouncycastle.bcpg.*; +import org.bouncycastle.bcpg.Ed25519PublicBCPGKey; +import org.bouncycastle.bcpg.Ed25519SecretBCPGKey; +import org.bouncycastle.bcpg.HashAlgorithmTags; +import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; +import org.bouncycastle.bcpg.PublicKeyPacket; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; @@ -8,17 +12,32 @@ import org.bouncycastle.jcajce.spec.EdDSAParameterSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyPair; import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.PGPSignatureGenerator; +import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider; import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator; +import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider; import org.bouncycastle.openpgp.operator.bc.BcPGPKeyConverter; import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyConverter; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; import org.bouncycastle.util.Pack; import org.bouncycastle.util.encoders.Hex; import java.io.IOException; -import java.security.*; +import java.nio.charset.StandardCharsets; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.SecureRandom; import java.util.Date; public class DedicatedEd25519KeyPairTest @@ -36,10 +55,64 @@ public void performTest() { testConversionOfJcaKeyPair(); testConversionOfBcKeyPair(); + testV4SigningVerificationWithJcaKey(); + testV4SigningVerificationWithBcKey(); testConversionOfTestVectorKey(); } + private void testV4SigningVerificationWithJcaKey() + throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, PGPException + { + Date date = currentTimeRounded(); + KeyPairGenerator gen = KeyPairGenerator.getInstance("EDDSA", new BouncyCastleProvider()); + gen.initialize(new EdDSAParameterSpec("Ed25519")); + KeyPair kp = gen.generateKeyPair(); + PGPKeyPair keyPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.Ed25519, kp, date); + + byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + PGPContentSignerBuilder contSigBuilder = new JcaPGPContentSignerBuilder( + keyPair.getPublicKey().getAlgorithm(), + HashAlgorithmTags.SHA512) + .setProvider(new BouncyCastleProvider()); + PGPSignatureGenerator sigGen = new PGPSignatureGenerator(contSigBuilder); + sigGen.init(PGPSignature.BINARY_DOCUMENT, keyPair.getPrivateKey()); + sigGen.update(data); + PGPSignature signature = sigGen.generate(); + + PGPContentVerifierBuilderProvider contVerBuilder = new JcaPGPContentVerifierBuilderProvider() + .setProvider(new BouncyCastleProvider()); + signature.init(contVerBuilder, keyPair.getPublicKey()); + signature.update(data); + isTrue(signature.verify()); + } + + private void testV4SigningVerificationWithBcKey() + throws PGPException + { + Date date = currentTimeRounded(); + Ed25519KeyPairGenerator gen = new Ed25519KeyPairGenerator(); + gen.init(new Ed25519KeyGenerationParameters(new SecureRandom())); + AsymmetricCipherKeyPair kp = gen.generateKeyPair(); + BcPGPKeyPair keyPair = new BcPGPKeyPair(PublicKeyAlgorithmTags.Ed25519, kp, date); + + byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + PGPContentSignerBuilder contSigBuilder = new BcPGPContentSignerBuilder( + keyPair.getPublicKey().getAlgorithm(), + HashAlgorithmTags.SHA512); + PGPSignatureGenerator sigGen = new PGPSignatureGenerator(contSigBuilder); + sigGen.init(PGPSignature.BINARY_DOCUMENT, keyPair.getPrivateKey()); + sigGen.update(data); + PGPSignature signature = sigGen.generate(); + + PGPContentVerifierBuilderProvider contVerBuilder = new BcPGPContentVerifierBuilderProvider(); + signature.init(contVerBuilder, keyPair.getPublicKey()); + signature.update(data); + isTrue(signature.verify()); + } + private void testConversionOfJcaKeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, PGPException, IOException { @@ -128,7 +201,9 @@ private void testConversionOfBcKeyPair() date.getTime(), j2.getPublicKey().getCreationTime().getTime()); } - private void testConversionOfTestVectorKey() throws PGPException, IOException { + private void testConversionOfTestVectorKey() + throws PGPException, IOException + { JcaPGPKeyConverter jc = new JcaPGPKeyConverter().setProvider(new BouncyCastleProvider()); BcPGPKeyConverter bc = new BcPGPKeyConverter(); // ed25519 public key from https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-13.html#name-hashed-data-stream-for-sign diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedEd448KeyPairTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedEd448KeyPairTest.java index e353bc9922..baa3560cf9 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedEd448KeyPairTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedEd448KeyPairTest.java @@ -2,6 +2,7 @@ import org.bouncycastle.bcpg.Ed448PublicBCPGKey; import org.bouncycastle.bcpg.Ed448SecretBCPGKey; +import org.bouncycastle.bcpg.HashAlgorithmTags; import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.generators.Ed448KeyPairGenerator; @@ -9,11 +10,25 @@ import org.bouncycastle.jcajce.spec.EdDSAParameterSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.PGPSignatureGenerator; +import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider; +import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider; import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; import java.io.IOException; -import java.security.*; +import java.nio.charset.StandardCharsets; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.Date; public class DedicatedEd448KeyPairTest @@ -31,6 +46,60 @@ public void performTest() { testConversionOfJcaKeyPair(); testConversionOfBcKeyPair(); + testV4SigningVerificationWithJcaKey(); + testV4SigningVerificationWithBcKey(); + } + + private void testV4SigningVerificationWithJcaKey() + throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, PGPException + { + Date date = currentTimeRounded(); + KeyPairGenerator gen = KeyPairGenerator.getInstance("EDDSA", new BouncyCastleProvider()); + gen.initialize(new EdDSAParameterSpec("Ed448")); + KeyPair kp = gen.generateKeyPair(); + PGPKeyPair keyPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.Ed448, kp, date); + + byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + PGPContentSignerBuilder contSigBuilder = new JcaPGPContentSignerBuilder( + keyPair.getPublicKey().getAlgorithm(), + HashAlgorithmTags.SHA512) + .setProvider(new BouncyCastleProvider()); + PGPSignatureGenerator sigGen = new PGPSignatureGenerator(contSigBuilder); + sigGen.init(PGPSignature.BINARY_DOCUMENT, keyPair.getPrivateKey()); + sigGen.update(data); + PGPSignature signature = sigGen.generate(); + + PGPContentVerifierBuilderProvider contVerBuilder = new JcaPGPContentVerifierBuilderProvider() + .setProvider(new BouncyCastleProvider()); + signature.init(contVerBuilder, keyPair.getPublicKey()); + signature.update(data); + isTrue(signature.verify()); + } + + private void testV4SigningVerificationWithBcKey() + throws PGPException + { + Date date = currentTimeRounded(); + Ed448KeyPairGenerator gen = new Ed448KeyPairGenerator(); + gen.init(new Ed448KeyGenerationParameters(new SecureRandom())); + AsymmetricCipherKeyPair kp = gen.generateKeyPair(); + BcPGPKeyPair keyPair = new BcPGPKeyPair(PublicKeyAlgorithmTags.Ed448, kp, date); + + byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + PGPContentSignerBuilder contSigBuilder = new BcPGPContentSignerBuilder( + keyPair.getPublicKey().getAlgorithm(), + HashAlgorithmTags.SHA512); + PGPSignatureGenerator sigGen = new PGPSignatureGenerator(contSigBuilder); + sigGen.init(PGPSignature.BINARY_DOCUMENT, keyPair.getPrivateKey()); + sigGen.update(data); + PGPSignature signature = sigGen.generate(); + + PGPContentVerifierBuilderProvider contVerBuilder = new BcPGPContentVerifierBuilderProvider(); + signature.init(contVerBuilder, keyPair.getPublicKey()); + signature.update(data); + isTrue(signature.verify()); } private void testConversionOfJcaKeyPair() diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedX25519KeyPairTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedX25519KeyPairTest.java index 6de196eb47..0b2fcc99fa 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedX25519KeyPairTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedX25519KeyPairTest.java @@ -1,6 +1,7 @@ package org.bouncycastle.openpgp.test; import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.bcpg.X25519PublicBCPGKey; import org.bouncycastle.bcpg.X25519SecretBCPGKey; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; @@ -8,12 +9,41 @@ import org.bouncycastle.crypto.params.X25519KeyGenerationParameters; import org.bouncycastle.jcajce.spec.XDHParameterSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openpgp.PGPEncryptedDataGenerator; +import org.bouncycastle.openpgp.PGPEncryptedDataList; import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPLiteralData; +import org.bouncycastle.openpgp.PGPLiteralDataGenerator; +import org.bouncycastle.openpgp.PGPObjectFactory; +import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData; +import org.bouncycastle.openpgp.bc.BcPGPObjectFactory; +import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory; +import org.bouncycastle.openpgp.operator.PGPDataEncryptorBuilder; +import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory; +import org.bouncycastle.openpgp.operator.PublicKeyKeyEncryptionMethodGenerator; +import org.bouncycastle.openpgp.operator.bc.BcPGPDataEncryptorBuilder; import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair; +import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory; +import org.bouncycastle.openpgp.operator.bc.BcPublicKeyKeyEncryptionMethodGenerator; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; - +import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.io.Streams; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.security.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.Date; public class DedicatedX25519KeyPairTest @@ -31,6 +61,99 @@ public void performTest() { testConversionOfJcaKeyPair(); testConversionOfBcKeyPair(); + + testV4MessageEncryptionDecryptionWithJcaKey(); + testV4MessageEncryptionDecryptionWithBcKey(); + } + + private void testV4MessageEncryptionDecryptionWithJcaKey() + throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException + { + BouncyCastleProvider provider = new BouncyCastleProvider(); + + Date date = currentTimeRounded(); + KeyPairGenerator gen = KeyPairGenerator.getInstance("XDH", provider); + gen.initialize(new XDHParameterSpec("X25519")); + KeyPair kp = gen.generateKeyPair(); + PGPKeyPair keyPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.X25519, kp, date); + + byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + PGPDataEncryptorBuilder encBuilder = new JcePGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256) + .setProvider(provider); + PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(encBuilder); + PublicKeyKeyEncryptionMethodGenerator metGen = new JcePublicKeyKeyEncryptionMethodGenerator(keyPair.getPublicKey()) + .setProvider(provider); + encGen.addMethod(metGen); + PGPLiteralDataGenerator litGen = new PGPLiteralDataGenerator(); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + OutputStream encOut = encGen.open(bOut, new byte[4096]); + OutputStream litOut = litGen.open(encOut, PGPLiteralData.BINARY, "", PGPLiteralData.NOW, new byte[4096]); + litOut.write(data); + litGen.close(); + encGen.close(); + + byte[] encrypted = bOut.toByteArray(); + + ByteArrayInputStream bIn = new ByteArrayInputStream(encrypted); + PGPObjectFactory objectFactory = new JcaPGPObjectFactory(bIn); + PGPEncryptedDataList encDataList = (PGPEncryptedDataList) objectFactory.nextObject(); + PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) encDataList.get(0); + PublicKeyDataDecryptorFactory decFactory = new JcePublicKeyDataDecryptorFactoryBuilder() + .setProvider(provider) + .build(keyPair.getPrivateKey()); + InputStream decIn = encData.getDataStream(decFactory); + objectFactory = new JcaPGPObjectFactory(decIn); + PGPLiteralData lit = (PGPLiteralData) objectFactory.nextObject(); + InputStream litIn = lit.getDataStream(); + byte[] plaintext = Streams.readAll(litIn); + litIn.close(); + decIn.close(); + + isTrue(Arrays.areEqual(data, plaintext)); + } + + private void testV4MessageEncryptionDecryptionWithBcKey() + throws PGPException, IOException + { + Date date = currentTimeRounded(); + X25519KeyPairGenerator gen = new X25519KeyPairGenerator(); + gen.init(new X25519KeyGenerationParameters(new SecureRandom())); + AsymmetricCipherKeyPair kp = gen.generateKeyPair(); + BcPGPKeyPair keyPair = new BcPGPKeyPair(PublicKeyAlgorithmTags.X25519, kp, date); + + byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + PGPDataEncryptorBuilder encBuilder = new BcPGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256); + PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(encBuilder); + PublicKeyKeyEncryptionMethodGenerator metGen = new BcPublicKeyKeyEncryptionMethodGenerator(keyPair.getPublicKey()); + encGen.addMethod(metGen); + PGPLiteralDataGenerator litGen = new PGPLiteralDataGenerator(); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + OutputStream encOut = encGen.open(bOut, new byte[4096]); + OutputStream litOut = litGen.open(encOut, PGPLiteralData.BINARY, "", PGPLiteralData.NOW, new byte[4096]); + litOut.write(data); + litGen.close(); + encGen.close(); + + byte[] encrypted = bOut.toByteArray(); + + ByteArrayInputStream bIn = new ByteArrayInputStream(encrypted); + PGPObjectFactory objectFactory = new BcPGPObjectFactory(bIn); + PGPEncryptedDataList encDataList = (PGPEncryptedDataList) objectFactory.nextObject(); + PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) encDataList.get(0); + PublicKeyDataDecryptorFactory decFactory = new BcPublicKeyDataDecryptorFactory(keyPair.getPrivateKey()); + InputStream decIn = encData.getDataStream(decFactory); + objectFactory = new BcPGPObjectFactory(decIn); + PGPLiteralData lit = (PGPLiteralData) objectFactory.nextObject(); + InputStream litIn = lit.getDataStream(); + byte[] plaintext = Streams.readAll(litIn); + litIn.close(); + decIn.close(); + + isTrue(Arrays.areEqual(data, plaintext)); } private void testConversionOfJcaKeyPair() diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedX448KeyPairTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedX448KeyPairTest.java index 42e19a3170..758a069c08 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedX448KeyPairTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/DedicatedX448KeyPairTest.java @@ -1,5 +1,6 @@ package org.bouncycastle.openpgp.test; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.bcpg.X448PublicBCPGKey; import org.bouncycastle.bcpg.X448SecretBCPGKey; import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; @@ -8,12 +9,41 @@ import org.bouncycastle.crypto.params.X448KeyGenerationParameters; import org.bouncycastle.jcajce.spec.XDHParameterSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openpgp.PGPEncryptedDataGenerator; +import org.bouncycastle.openpgp.PGPEncryptedDataList; import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPLiteralData; +import org.bouncycastle.openpgp.PGPLiteralDataGenerator; +import org.bouncycastle.openpgp.PGPObjectFactory; +import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData; +import org.bouncycastle.openpgp.bc.BcPGPObjectFactory; +import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory; +import org.bouncycastle.openpgp.operator.PGPDataEncryptorBuilder; +import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory; +import org.bouncycastle.openpgp.operator.PublicKeyKeyEncryptionMethodGenerator; +import org.bouncycastle.openpgp.operator.bc.BcPGPDataEncryptorBuilder; import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair; +import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory; +import org.bouncycastle.openpgp.operator.bc.BcPublicKeyKeyEncryptionMethodGenerator; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; - +import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.io.Streams; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.security.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.Date; public class DedicatedX448KeyPairTest @@ -31,6 +61,99 @@ public void performTest() { testConversionOfJcaKeyPair(); testConversionOfBcKeyPair(); + + testV4MessageEncryptionDecryptionWithJcaKey(); + testV4MessageEncryptionDecryptionWithBcKey(); + } + + private void testV4MessageEncryptionDecryptionWithJcaKey() + throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException + { + BouncyCastleProvider provider = new BouncyCastleProvider(); + + Date date = currentTimeRounded(); + KeyPairGenerator gen = KeyPairGenerator.getInstance("XDH", provider); + gen.initialize(new XDHParameterSpec("X448")); + KeyPair kp = gen.generateKeyPair(); + PGPKeyPair keyPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.X448, kp, date); + + byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + PGPDataEncryptorBuilder encBuilder = new JcePGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256) + .setProvider(provider); + PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(encBuilder); + PublicKeyKeyEncryptionMethodGenerator metGen = new JcePublicKeyKeyEncryptionMethodGenerator(keyPair.getPublicKey()) + .setProvider(provider); + encGen.addMethod(metGen); + PGPLiteralDataGenerator litGen = new PGPLiteralDataGenerator(); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + OutputStream encOut = encGen.open(bOut, new byte[4096]); + OutputStream litOut = litGen.open(encOut, PGPLiteralData.BINARY, "", PGPLiteralData.NOW, new byte[4096]); + litOut.write(data); + litGen.close(); + encGen.close(); + + byte[] encrypted = bOut.toByteArray(); + + ByteArrayInputStream bIn = new ByteArrayInputStream(encrypted); + PGPObjectFactory objectFactory = new JcaPGPObjectFactory(bIn); + PGPEncryptedDataList encDataList = (PGPEncryptedDataList) objectFactory.nextObject(); + PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) encDataList.get(0); + PublicKeyDataDecryptorFactory decFactory = new JcePublicKeyDataDecryptorFactoryBuilder() + .setProvider(provider) + .build(keyPair.getPrivateKey()); + InputStream decIn = encData.getDataStream(decFactory); + objectFactory = new JcaPGPObjectFactory(decIn); + PGPLiteralData lit = (PGPLiteralData) objectFactory.nextObject(); + InputStream litIn = lit.getDataStream(); + byte[] plaintext = Streams.readAll(litIn); + litIn.close(); + decIn.close(); + + isTrue(Arrays.areEqual(data, plaintext)); + } + + private void testV4MessageEncryptionDecryptionWithBcKey() + throws PGPException, IOException + { + Date date = currentTimeRounded(); + X448KeyPairGenerator gen = new X448KeyPairGenerator(); + gen.init(new X448KeyGenerationParameters(new SecureRandom())); + AsymmetricCipherKeyPair kp = gen.generateKeyPair(); + BcPGPKeyPair keyPair = new BcPGPKeyPair(PublicKeyAlgorithmTags.X448, kp, date); + + byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + PGPDataEncryptorBuilder encBuilder = new BcPGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256); + PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(encBuilder); + PublicKeyKeyEncryptionMethodGenerator metGen = new BcPublicKeyKeyEncryptionMethodGenerator(keyPair.getPublicKey()); + encGen.addMethod(metGen); + PGPLiteralDataGenerator litGen = new PGPLiteralDataGenerator(); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + OutputStream encOut = encGen.open(bOut, new byte[4096]); + OutputStream litOut = litGen.open(encOut, PGPLiteralData.BINARY, "", PGPLiteralData.NOW, new byte[4096]); + litOut.write(data); + litGen.close(); + encGen.close(); + + byte[] encrypted = bOut.toByteArray(); + + ByteArrayInputStream bIn = new ByteArrayInputStream(encrypted); + PGPObjectFactory objectFactory = new BcPGPObjectFactory(bIn); + PGPEncryptedDataList encDataList = (PGPEncryptedDataList) objectFactory.nextObject(); + PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) encDataList.get(0); + PublicKeyDataDecryptorFactory decFactory = new BcPublicKeyDataDecryptorFactory(keyPair.getPrivateKey()); + InputStream decIn = encData.getDataStream(decFactory); + objectFactory = new BcPGPObjectFactory(decIn); + PGPLiteralData lit = (PGPLiteralData) objectFactory.nextObject(); + InputStream litIn = lit.getDataStream(); + byte[] plaintext = Streams.readAll(litIn); + litIn.close(); + decIn.close(); + + isTrue(Arrays.areEqual(data, plaintext)); } private void testConversionOfJcaKeyPair() diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyEd25519KeyPairTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyEd25519KeyPairTest.java index f3efe8bc1e..b24a934db0 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyEd25519KeyPairTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyEd25519KeyPairTest.java @@ -24,7 +24,11 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.security.*; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.Date; public class LegacyEd25519KeyPairTest diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyX25519KeyPairTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyX25519KeyPairTest.java index 55a008875b..f58d08b211 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyX25519KeyPairTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyX25519KeyPairTest.java @@ -3,17 +3,47 @@ import org.bouncycastle.bcpg.ECDHPublicBCPGKey; import org.bouncycastle.bcpg.ECSecretBCPGKey; import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.generators.X25519KeyPairGenerator; import org.bouncycastle.crypto.params.X25519KeyGenerationParameters; import org.bouncycastle.jcajce.spec.XDHParameterSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openpgp.PGPEncryptedDataGenerator; +import org.bouncycastle.openpgp.PGPEncryptedDataList; import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPLiteralData; +import org.bouncycastle.openpgp.PGPLiteralDataGenerator; +import org.bouncycastle.openpgp.PGPObjectFactory; +import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData; +import org.bouncycastle.openpgp.bc.BcPGPObjectFactory; +import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory; +import org.bouncycastle.openpgp.operator.PGPDataEncryptorBuilder; +import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory; +import org.bouncycastle.openpgp.operator.PublicKeyKeyEncryptionMethodGenerator; +import org.bouncycastle.openpgp.operator.bc.BcPGPDataEncryptorBuilder; import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair; +import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory; +import org.bouncycastle.openpgp.operator.bc.BcPublicKeyKeyEncryptionMethodGenerator; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; - +import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.io.Streams; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.security.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.Date; public class LegacyX25519KeyPairTest @@ -31,6 +61,99 @@ public void performTest() { testConversionOfJcaKeyPair(); testConversionOfBcKeyPair(); + + testV4MessageEncryptionDecryptionWithJcaKey(); + testV4MessageEncryptionDecryptionWithBcKey(); + } + + private void testV4MessageEncryptionDecryptionWithJcaKey() + throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException + { + BouncyCastleProvider provider = new BouncyCastleProvider(); + + Date date = currentTimeRounded(); + KeyPairGenerator gen = KeyPairGenerator.getInstance("XDH", provider); + gen.initialize(new XDHParameterSpec("X25519")); + KeyPair kp = gen.generateKeyPair(); + PGPKeyPair keyPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.ECDH, kp, date); + + byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + PGPDataEncryptorBuilder encBuilder = new JcePGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256) + .setProvider(provider); + PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(encBuilder); + PublicKeyKeyEncryptionMethodGenerator metGen = new JcePublicKeyKeyEncryptionMethodGenerator(keyPair.getPublicKey()) + .setProvider(provider); + encGen.addMethod(metGen); + PGPLiteralDataGenerator litGen = new PGPLiteralDataGenerator(); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + OutputStream encOut = encGen.open(bOut, new byte[4096]); + OutputStream litOut = litGen.open(encOut, PGPLiteralData.BINARY, "", PGPLiteralData.NOW, new byte[4096]); + litOut.write(data); + litGen.close(); + encGen.close(); + + byte[] encrypted = bOut.toByteArray(); + + ByteArrayInputStream bIn = new ByteArrayInputStream(encrypted); + PGPObjectFactory objectFactory = new JcaPGPObjectFactory(bIn); + PGPEncryptedDataList encDataList = (PGPEncryptedDataList) objectFactory.nextObject(); + PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) encDataList.get(0); + PublicKeyDataDecryptorFactory decFactory = new JcePublicKeyDataDecryptorFactoryBuilder() + .setProvider(provider) + .build(keyPair.getPrivateKey()); + InputStream decIn = encData.getDataStream(decFactory); + objectFactory = new JcaPGPObjectFactory(decIn); + PGPLiteralData lit = (PGPLiteralData) objectFactory.nextObject(); + InputStream litIn = lit.getDataStream(); + byte[] plaintext = Streams.readAll(litIn); + litIn.close(); + decIn.close(); + + isTrue(Arrays.areEqual(data, plaintext)); + } + + private void testV4MessageEncryptionDecryptionWithBcKey() + throws PGPException, IOException + { + Date date = currentTimeRounded(); + X25519KeyPairGenerator gen = new X25519KeyPairGenerator(); + gen.init(new X25519KeyGenerationParameters(new SecureRandom())); + AsymmetricCipherKeyPair kp = gen.generateKeyPair(); + BcPGPKeyPair keyPair = new BcPGPKeyPair(PublicKeyAlgorithmTags.ECDH, kp, date); + + byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + PGPDataEncryptorBuilder encBuilder = new BcPGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256); + PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(encBuilder); + PublicKeyKeyEncryptionMethodGenerator metGen = new BcPublicKeyKeyEncryptionMethodGenerator(keyPair.getPublicKey()); + encGen.addMethod(metGen); + PGPLiteralDataGenerator litGen = new PGPLiteralDataGenerator(); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + OutputStream encOut = encGen.open(bOut, new byte[4096]); + OutputStream litOut = litGen.open(encOut, PGPLiteralData.BINARY, "", PGPLiteralData.NOW, new byte[4096]); + litOut.write(data); + litGen.close(); + encGen.close(); + + byte[] encrypted = bOut.toByteArray(); + + ByteArrayInputStream bIn = new ByteArrayInputStream(encrypted); + PGPObjectFactory objectFactory = new BcPGPObjectFactory(bIn); + PGPEncryptedDataList encDataList = (PGPEncryptedDataList) objectFactory.nextObject(); + PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) encDataList.get(0); + PublicKeyDataDecryptorFactory decFactory = new BcPublicKeyDataDecryptorFactory(keyPair.getPrivateKey()); + InputStream decIn = encData.getDataStream(decFactory); + objectFactory = new BcPGPObjectFactory(decIn); + PGPLiteralData lit = (PGPLiteralData) objectFactory.nextObject(); + InputStream litIn = lit.getDataStream(); + byte[] plaintext = Streams.readAll(litIn); + litIn.close(); + decIn.close(); + + isTrue(Arrays.areEqual(data, plaintext)); } private void testConversionOfJcaKeyPair() diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyX448KeyPairTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyX448KeyPairTest.java index 61c04c5f54..616d9bd026 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyX448KeyPairTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/LegacyX448KeyPairTest.java @@ -1,6 +1,8 @@ package org.bouncycastle.openpgp.test; -import org.bouncycastle.bcpg.*; +import org.bouncycastle.bcpg.ECDHPublicBCPGKey; +import org.bouncycastle.bcpg.ECSecretBCPGKey; +import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.generators.X448KeyPairGenerator; import org.bouncycastle.crypto.params.X448KeyGenerationParameters; @@ -11,7 +13,11 @@ import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; import java.io.IOException; -import java.security.*; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.Date; public class LegacyX448KeyPairTest