diff --git a/src/main/java/org/pgpainless/pgpainless/key/collection/PGPKeyRing.java b/src/main/java/org/pgpainless/pgpainless/key/collection/PGPKeyRing.java new file mode 100644 index 00000000..cd0ea5d5 --- /dev/null +++ b/src/main/java/org/pgpainless/pgpainless/key/collection/PGPKeyRing.java @@ -0,0 +1,40 @@ +/* + * Copyright 2018 Paul Schaub. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pgpainless.pgpainless.key.collection; + +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRing; + +public class PGPKeyRing { + + private PGPPublicKeyRing publicKeys; + private PGPSecretKeyRing secretKeys; + + public PGPKeyRing(PGPPublicKeyRing publicKeys, PGPSecretKeyRing secretKeys) { + this.publicKeys = publicKeys; + this.secretKeys = secretKeys; + } + + public PGPPublicKeyRing getPublicKeys() { + return publicKeys; + } + + public PGPSecretKeyRing getSecretKeys() { + return secretKeys; + } + + +} diff --git a/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilder.java b/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilder.java index fe84b5d1..65796f67 100644 --- a/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilder.java +++ b/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilder.java @@ -33,6 +33,7 @@ import org.bouncycastle.openpgp.PGPEncryptedData; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPKeyPair; import org.bouncycastle.openpgp.PGPKeyRingGenerator; +import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPSignatureSubpacketVector; @@ -44,6 +45,7 @@ import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBu import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; import org.pgpainless.pgpainless.algorithm.KeyFlag; +import org.pgpainless.pgpainless.key.collection.PGPKeyRing; import org.pgpainless.pgpainless.key.generation.type.ECDH; import org.pgpainless.pgpainless.key.generation.type.ECDSA; import org.pgpainless.pgpainless.key.generation.type.KeyType; @@ -71,7 +73,7 @@ public class KeyRingBuilder implements KeyRingBuilderInterface { * @throws NoSuchProviderException * @throws InvalidAlgorithmParameterException */ - public PGPSecretKeyRing simpleRsaKeyRing(String userId, RsaLength length) + public PGPKeyRing simpleRsaKeyRing(String userId, RsaLength length) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { return withMasterKey( KeySpec.getBuilder(RSA_GENERAL.withLength(length)) @@ -94,7 +96,7 @@ public class KeyRingBuilder implements KeyRingBuilderInterface { * @throws NoSuchProviderException * @throws InvalidAlgorithmParameterException */ - public PGPSecretKeyRing simpleEcKeyRing(String userId) + public PGPKeyRing simpleEcKeyRing(String userId) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { return withSubKey( KeySpec.getBuilder(ECDH.fromCurve(EllipticCurve._P256)) @@ -160,7 +162,7 @@ public class KeyRingBuilder implements KeyRingBuilderInterface { class BuildImpl implements Build { @Override - public PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, + public PGPKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, InvalidAlgorithmParameterException { // Hash Calculator @@ -206,7 +208,9 @@ public class KeyRingBuilder implements KeyRingBuilderInterface { } } - return ringGenerator.generateSecretKeyRing(); + PGPPublicKeyRing publicKeys = ringGenerator.generatePublicKeyRing(); + PGPSecretKeyRing secretKeys = ringGenerator.generateSecretKeyRing(); + return new PGPKeyRing(publicKeys, secretKeys); } private PGPKeyPair generateKeyPair(KeySpec spec) diff --git a/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilderInterface.java b/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilderInterface.java index 9b5e18d8..64c803c0 100644 --- a/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilderInterface.java +++ b/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilderInterface.java @@ -20,7 +20,7 @@ import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.pgpainless.pgpainless.key.collection.PGPKeyRing; public interface KeyRingBuilderInterface { @@ -47,7 +47,7 @@ public interface KeyRingBuilderInterface { interface Build { - PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, + PGPKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, InvalidAlgorithmParameterException; } diff --git a/src/main/java/org/pgpainless/pgpainless/key/selection/key/KeySelectionStrategy.java b/src/main/java/org/pgpainless/pgpainless/key/selection/key/KeySelectionStrategy.java index 92a1c82d..7b1283b2 100644 --- a/src/main/java/org/pgpainless/pgpainless/key/selection/key/KeySelectionStrategy.java +++ b/src/main/java/org/pgpainless/pgpainless/key/selection/key/KeySelectionStrategy.java @@ -23,7 +23,7 @@ import org.pgpainless.pgpainless.util.MultiMap; /** * Interface that describes a selection strategy for OpenPGP keys. * @param Type of the Key - * @param Type of the KeyRing + * @param Type of the PGPKeyRing * @param Type that describes the owner of this key */ public interface KeySelectionStrategy { diff --git a/src/main/java/org/pgpainless/pgpainless/util/BCUtil.java b/src/main/java/org/pgpainless/pgpainless/util/BCUtil.java index 3994c252..38d317b1 100644 --- a/src/main/java/org/pgpainless/pgpainless/util/BCUtil.java +++ b/src/main/java/org/pgpainless/pgpainless/util/BCUtil.java @@ -19,11 +19,9 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; -import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -63,33 +61,18 @@ public class BCUtil { return new PGPSecretKeyRingCollection(Arrays.asList(rings)); } - /* - PGPSecretKeyRing -> PGPPublicKeyRing - */ - - public static PGPPublicKeyRing publicKeyRingFromSecretKeyRing(PGPSecretKeyRing secring) { - List list = new ArrayList<>(); - for (Iterator i = secring.getPublicKeys(); i.hasNext(); ) { - PGPPublicKey k = i.next(); - list.add(k); - } - - return new PGPPublicKeyRing(list); - } - /* PGPXxxKeyRingCollection -> PGPXxxKeyRing */ public static PGPSecretKeyRing getKeyRingFromCollection(PGPSecretKeyRingCollection collection, Long id) - throws PGPException { + throws PGPException, IOException { PGPSecretKeyRing uncleanedRing = collection.getSecretKeyRing(id); - PGPPublicKeyRing publicKeys = publicKeyRingFromSecretKeyRing(uncleanedRing); // Determine ids of signed keys Set signedKeyIds = new HashSet<>(); signedKeyIds.add(id); // Add the signing key itself - Iterator signedPubKeys = publicKeys.getKeysWithSignaturesBy(id); + Iterator signedPubKeys = uncleanedRing.getKeysWithSignaturesBy(id); while (signedPubKeys.hasNext()) { signedKeyIds.add(signedPubKeys.next().getKeyID()); } @@ -275,12 +258,12 @@ public class BCUtil { PGPPublicKey masterOne = getMasterKeyFrom(one); if (masterOne == null) { - throw new IllegalArgumentException("First KeyRing has no master key"); + throw new IllegalArgumentException("First PGPKeyRing has no master key"); } PGPPublicKey masterOther = getMasterKeyFrom(other); if (masterOther == null) { - throw new IllegalArgumentException("Other KeyRing has no master key"); + throw new IllegalArgumentException("Other PGPKeyRing has no master key"); } if (masterOne.getKeyID() != masterOther.getKeyID() || diff --git a/src/test/java/org/pgpainless/pgpainless/BCUtilTest.java b/src/test/java/org/pgpainless/pgpainless/BCUtilTest.java index 10aac211..3331b9b7 100644 --- a/src/test/java/org/pgpainless/pgpainless/BCUtilTest.java +++ b/src/test/java/org/pgpainless/pgpainless/BCUtilTest.java @@ -37,6 +37,9 @@ import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.junit.Test; +import org.pgpainless.pgpainless.key.collection.PGPKeyRing; +import org.pgpainless.pgpainless.key.generation.KeySpec; +import org.pgpainless.pgpainless.key.generation.type.RSA_GENERAL; import org.pgpainless.pgpainless.key.generation.type.length.RsaLength; import org.pgpainless.pgpainless.util.BCUtil; @@ -48,29 +51,32 @@ public class BCUtilTest extends AbstractPGPainlessTest { public void keyRingToCollectionTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException { - PGPSecretKeyRing sec = PGPainless.generateKeyRing().simpleEcKeyRing("donald@duck.tails"); - PGPPublicKeyRing pub = BCUtil.publicKeyRingFromSecretKeyRing(sec); + PGPKeyRing ring = PGPainless.generateKeyRing() + .withSubKey(KeySpec.getBuilder(RSA_GENERAL.withLength(RsaLength._3072)).withDefaultKeyFlags().withDefaultAlgorithms()) + .withMasterKey(KeySpec.getBuilder(RSA_GENERAL.withLength(RsaLength._3072)).withDefaultKeyFlags().withDefaultAlgorithms()) + .withPrimaryUserId("donald@duck.tails").withoutPassphrase().build(); + PGPSecretKeyRing sec = ring.getSecretKeys(); + PGPPublicKeyRing pub = ring.getPublicKeys(); LOGGER.log(Level.INFO, "Main ID: " + sec.getPublicKey().getKeyID() + " " + pub.getPublicKey().getKeyID()); - int secSize = 0; + int secSize = 1; Iterator secPubIt = sec.getPublicKeys(); while (secPubIt.hasNext()) { PGPPublicKey k = secPubIt.next(); - LOGGER.log(Level.INFO, "" + k.getKeyID() + " " + k.isEncryptionKey() + " " + k.isMasterKey()); + LOGGER.log(Level.INFO, secSize + " " + k.getKeyID() + " " + k.isEncryptionKey() + " " + k.isMasterKey()); secSize++; } LOGGER.log(Level.INFO, "After BCUtil.publicKeyRingFromSecretKeyRing()"); - int pubSize = 0; + int pubSize = 1; Iterator pubPubIt = pub.getPublicKeys(); while (pubPubIt.hasNext()) { PGPPublicKey k = pubPubIt.next(); - LOGGER.log(Level.INFO, "" + k.getKeyID() + " " + k.isEncryptionKey() + " " + k.isMasterKey()); + LOGGER.log(Level.INFO, pubSize + " " + k.getKeyID() + " " + k.isEncryptionKey() + " " + k.isMasterKey()); pubSize++; } - LOGGER.log(Level.INFO, " Pub: " + pubSize + " Sec: " + secSize); assertEquals(secSize, pubSize); PGPSecretKeyRingCollection secCol = BCUtil.keyRingsToKeyRingCollection(sec); @@ -101,11 +107,11 @@ public class BCUtilTest extends AbstractPGPainlessTest { @Test public void removeUnsignedKeysTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { - PGPSecretKeyRing alice = PGPainless.generateKeyRing().simpleRsaKeyRing("alice@wonderland.lit", RsaLength._1024); - PGPSecretKeyRing mallory = PGPainless.generateKeyRing().simpleEcKeyRing("mallory@mall.ory"); + PGPKeyRing alice = PGPainless.generateKeyRing().simpleRsaKeyRing("alice@wonderland.lit", RsaLength._1024); + PGPKeyRing mallory = PGPainless.generateKeyRing().simpleEcKeyRing("mallory@mall.ory"); PGPSecretKey subKey = null; - Iterator sit = mallory.getSecretKeys(); + Iterator sit = mallory.getSecretKeys().getSecretKeys(); while (sit.hasNext()) { PGPSecretKey s = sit.next(); if (!s.isMasterKey()) { @@ -116,12 +122,12 @@ public class BCUtilTest extends AbstractPGPainlessTest { assertNotNull(subKey); - PGPSecretKeyRing alice_mallory = PGPSecretKeyRing.insertSecretKey(alice, subKey); + PGPSecretKeyRing alice_mallory = PGPSecretKeyRing.insertSecretKey(alice.getSecretKeys(), subKey); // Check, if alice_mallory contains mallory's key assertNotNull(alice_mallory.getSecretKey(subKey.getKeyID())); - PGPSecretKeyRing cleaned = BCUtil.removeUnassociatedKeysFromKeyRing(alice_mallory, alice.getPublicKey()); + PGPSecretKeyRing cleaned = BCUtil.removeUnassociatedKeysFromKeyRing(alice_mallory, alice.getPublicKeys().getPublicKey()); assertNull(cleaned.getSecretKey(subKey.getKeyID())); } @@ -129,12 +135,13 @@ public class BCUtilTest extends AbstractPGPainlessTest { public void removeUnsignedKeysECTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("alice@wonderland.lit"); - PGPSecretKeyRing secCleaned = BCUtil.removeUnassociatedKeysFromKeyRing(secretKeys, secretKeys.getPublicKey()); + PGPKeyRing ring = PGPainless.generateKeyRing().simpleEcKeyRing("alice@wonderland.lit"); + PGPPublicKeyRing publicKeys = ring.getPublicKeys(); + PGPSecretKeyRing secretKeys = ring.getSecretKeys(); + PGPSecretKeyRing secCleaned = ring.getSecretKeys(); assertTrue(Arrays.equals(secretKeys.getEncoded(), secCleaned.getEncoded())); - PGPPublicKeyRing publicKeys = BCUtil.publicKeyRingFromSecretKeyRing(secretKeys); PGPPublicKeyRing pubCleaned = BCUtil.removeUnassociatedKeysFromKeyRing(publicKeys, publicKeys.getPublicKey()); assertTrue(Arrays.equals(publicKeys.getEncoded(), pubCleaned.getEncoded())); diff --git a/src/test/java/org/pgpainless/pgpainless/BouncycastleExportSubkeys.java b/src/test/java/org/pgpainless/pgpainless/BouncycastleExportSubkeys.java new file mode 100644 index 00000000..1ea40509 --- /dev/null +++ b/src/test/java/org/pgpainless/pgpainless/BouncycastleExportSubkeys.java @@ -0,0 +1,132 @@ +/* + * Copyright 2018 Paul Schaub. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pgpainless.pgpainless; + +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.util.Date; + +import org.bouncycastle.bcpg.CompressionAlgorithmTags; +import org.bouncycastle.bcpg.HashAlgorithmTags; +import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; +import org.bouncycastle.bcpg.sig.Features; +import org.bouncycastle.bcpg.sig.KeyFlags; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPKeyRingGenerator; +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator; +import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.PGPDigestCalculator; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; +import org.junit.Test; + +public class BouncycastleExportSubkeys { + + @Test + public void testExportImport() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, PGPException, IOException { + Security.addProvider(new BouncyCastleProvider()); + + KeyPairGenerator generator; + KeyPair pair; + + // Generate master key + + generator = KeyPairGenerator.getInstance("ECDSA", BouncyCastleProvider.PROVIDER_NAME); + generator.initialize(new ECNamedCurveGenParameterSpec("P-256")); + + pair = generator.generateKeyPair(); + PGPKeyPair pgpMasterKey = new JcaPGPKeyPair(PublicKeyAlgorithmTags.ECDSA, pair, new Date()); + + PGPSignatureSubpacketGenerator subPackets = new PGPSignatureSubpacketGenerator(); + subPackets.setKeyFlags(false, KeyFlags.AUTHENTICATION & KeyFlags.CERTIFY_OTHER & KeyFlags.SIGN_DATA); + subPackets.setPreferredCompressionAlgorithms(false, new int[] { + SymmetricKeyAlgorithmTags.AES_256, + SymmetricKeyAlgorithmTags.AES_128, + SymmetricKeyAlgorithmTags.AES_128}); + subPackets.setPreferredHashAlgorithms(false, new int[] { + HashAlgorithmTags.SHA512, + HashAlgorithmTags.SHA384, + HashAlgorithmTags.SHA256, + HashAlgorithmTags.SHA224}); + subPackets.setPreferredCompressionAlgorithms(false, new int[] { + CompressionAlgorithmTags.ZLIB, + CompressionAlgorithmTags.BZIP2, + CompressionAlgorithmTags.ZIP, + CompressionAlgorithmTags.UNCOMPRESSED}); + subPackets.setFeature(false, Features.FEATURE_MODIFICATION_DETECTION); + + // Generate sub key + + generator = KeyPairGenerator.getInstance("ECDH", BouncyCastleProvider.PROVIDER_NAME); + generator.initialize(new ECNamedCurveGenParameterSpec("P-256")); + + pair = generator.generateKeyPair(); + PGPKeyPair pgpSubKey = new JcaPGPKeyPair(PublicKeyAlgorithmTags.ECDH, pair, new Date()); + + // Assemble key + + PGPDigestCalculator calculator = new JcaPGPDigestCalculatorProviderBuilder() + .setProvider(BouncyCastleProvider.PROVIDER_NAME) + .build() + .get(HashAlgorithmTags.SHA1); + + PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( + pgpMasterKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA512) + .setProvider(BouncyCastleProvider.PROVIDER_NAME); + + PGPKeyRingGenerator pgpGenerator = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, + pgpMasterKey, "alice@wonderland.lit", calculator, subPackets.generate(), null, + signerBuilder, null); + + // Add sub key + + subPackets.setKeyFlags(false, KeyFlags.ENCRYPT_STORAGE & KeyFlags.ENCRYPT_COMMS); + + pgpGenerator.addSubKey(pgpSubKey, subPackets.generate(), null); + + // Generate SecretKeyRing + + PGPSecretKeyRing secretKeys = pgpGenerator.generateSecretKeyRing(); + PGPPublicKeyRing publicKeys = pgpGenerator.generatePublicKeyRing(); + + // Test + + /* + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(2048); + outputStream.write(secretKeys.getEncoded()); + + PGPPublicKeyRing publicKeys = new PGPPublicKeyRing(outputStream.toByteArray(), new BcKeyFingerprintCalculator()); + + Iterator iterator = secretKeys.getPublicKeys(); + while (iterator.hasNext()) { + assertNotNull(publicKeys.getPublicKey(iterator.next().getKeyID())); + } + */ + } +} diff --git a/src/test/java/org/pgpainless/pgpainless/EncryptDecryptTest.java b/src/test/java/org/pgpainless/pgpainless/EncryptDecryptTest.java index 3a2f635a..8acf13e2 100644 --- a/src/test/java/org/pgpainless/pgpainless/EncryptDecryptTest.java +++ b/src/test/java/org/pgpainless/pgpainless/EncryptDecryptTest.java @@ -42,6 +42,7 @@ import org.pgpainless.pgpainless.algorithm.SymmetricKeyAlgorithm; import org.pgpainless.pgpainless.decryption_verification.DecryptionStream; import org.pgpainless.pgpainless.decryption_verification.PainlessResult; import org.pgpainless.pgpainless.encryption_signing.EncryptionStream; +import org.pgpainless.pgpainless.key.collection.PGPKeyRing; import org.pgpainless.pgpainless.key.generation.KeySpec; import org.pgpainless.pgpainless.key.generation.type.ElGamal_GENERAL; import org.pgpainless.pgpainless.key.generation.type.RSA_GENERAL; @@ -71,8 +72,8 @@ public class EncryptDecryptTest extends AbstractPGPainlessTest { public void freshKeysRsaToElGamalTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException { - PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("romeo@montague.lit", RsaLength._3072); - PGPSecretKeyRing recipient = PGPainless.generateKeyRing() + PGPKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("romeo@montague.lit", RsaLength._3072); + PGPKeyRing recipient = PGPainless.generateKeyRing() .withSubKey(KeySpec.getBuilder(ElGamal_GENERAL.withLength(ElGamalLength._3072)).withKeyFlags(KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS).withDefaultAlgorithms()) .withMasterKey(KeySpec.getBuilder(RSA_GENERAL.withLength(RsaLength._4096)).withKeyFlags(KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER).withDefaultAlgorithms()) .withPrimaryUserId("juliet@capulet.lit").withoutPassphrase().build(); @@ -84,8 +85,8 @@ public class EncryptDecryptTest extends AbstractPGPainlessTest { public void freshKeysRsaToRsaTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException { - PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("romeo@montague.lit", RsaLength._4096); - PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._4096); + PGPKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("romeo@montague.lit", RsaLength._4096); + PGPKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._4096); encryptDecryptForSecretKeyRings(sender, recipient); } @@ -93,8 +94,8 @@ public class EncryptDecryptTest extends AbstractPGPainlessTest { @Test public void freshKeysEcToEcTest() throws IOException, PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { - PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("romeo@montague.lit"); - PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("juliet@capulet.lit"); + PGPKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("romeo@montague.lit"); + PGPKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("juliet@capulet.lit"); encryptDecryptForSecretKeyRings(sender, recipient); } @@ -103,8 +104,8 @@ public class EncryptDecryptTest extends AbstractPGPainlessTest { public void freshKeysEcToRsaTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException { - PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("romeo@montague.lit"); - PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._4096); + PGPKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("romeo@montague.lit"); + PGPKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._4096); encryptDecryptForSecretKeyRings(sender, recipient); } @@ -113,18 +114,20 @@ public class EncryptDecryptTest extends AbstractPGPainlessTest { public void freshKeysRsaToEcTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException { - PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("romeo@montague.lit", RsaLength._4096); - PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("juliet@capulet.lit"); + PGPKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("romeo@montague.lit", RsaLength._4096); + PGPKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("juliet@capulet.lit"); encryptDecryptForSecretKeyRings(sender, recipient); } @Ignore - private void encryptDecryptForSecretKeyRings(PGPSecretKeyRing sender, PGPSecretKeyRing recipient) + private void encryptDecryptForSecretKeyRings(PGPKeyRing sender, PGPKeyRing recipient) throws PGPException, IOException { - PGPPublicKeyRing recipientPub = BCUtil.publicKeyRingFromSecretKeyRing(recipient); - PGPPublicKeyRing senderPub = BCUtil.publicKeyRingFromSecretKeyRing(sender); + PGPSecretKeyRing recipientSec = recipient.getSecretKeys(); + PGPSecretKeyRing senderSec = sender.getSecretKeys(); + PGPPublicKeyRing recipientPub = recipient.getPublicKeys(); + PGPPublicKeyRing senderPub = sender.getPublicKeys(); SecretKeyRingProtector keyDecryptor = new UnprotectedKeysProtector(); @@ -136,19 +139,19 @@ public class EncryptDecryptTest extends AbstractPGPainlessTest { .onOutputStream(envelope) .toRecipients(recipientPub) .usingSecureAlgorithms() - .signWith(keyDecryptor, sender) + .signWith(keyDecryptor, senderSec) .noArmor(); PainlessResult encryptionResult = encryptor.getResult(); assertFalse(encryptionResult.getAllSignatureKeyFingerprints().isEmpty()); for (long keyId : encryptionResult.getAllSignatureKeyFingerprints()) { - assertTrue(BCUtil.keyRingContainsKeyWithId(sender, keyId)); + assertTrue(BCUtil.keyRingContainsKeyWithId(senderPub, keyId)); } assertFalse(encryptionResult.getRecipientKeyIds().isEmpty()); for (long keyId : encryptionResult.getRecipientKeyIds()) { - assertTrue(BCUtil.keyRingContainsKeyWithId(recipient, keyId)); + assertTrue(BCUtil.keyRingContainsKeyWithId(recipientPub, keyId)); } assertEquals(SymmetricKeyAlgorithm.AES_256, encryptionResult.getSymmetricKeyAlgorithm()); @@ -157,8 +160,8 @@ public class EncryptDecryptTest extends AbstractPGPainlessTest { encryptor.close(); byte[] encryptedSecretMessage = envelope.toByteArray(); - LOGGER.log(Level.INFO, "Sender: " + PublicKeyAlgorithm.fromId(sender.getPublicKey().getAlgorithm()) + - " Receiver: " + PublicKeyAlgorithm.fromId(recipient.getPublicKey().getAlgorithm()) + + LOGGER.log(Level.INFO, "Sender: " + PublicKeyAlgorithm.fromId(senderPub.getPublicKey().getAlgorithm()) + + " Receiver: " + PublicKeyAlgorithm.fromId(recipientPub.getPublicKey().getAlgorithm()) + " Encrypted Length: " + encryptedSecretMessage.length); // Juliet trieth to comprehend Romeos words @@ -166,7 +169,7 @@ public class EncryptDecryptTest extends AbstractPGPainlessTest { ByteArrayInputStream envelopeIn = new ByteArrayInputStream(encryptedSecretMessage); DecryptionStream decryptor = PGPainless.createDecryptor() .onInputStream(envelopeIn) - .decryptWith(keyDecryptor, BCUtil.keyRingsToKeyRingCollection(recipient)) + .decryptWith(keyDecryptor, BCUtil.keyRingsToKeyRingCollection(recipientSec)) .verifyWith(BCUtil.keyRingsToKeyRingCollection(senderPub)) .ignoreMissingPublicKeys() .build(); diff --git a/src/test/java/org/pgpainless/pgpainless/ImportExportKeyTest.java b/src/test/java/org/pgpainless/pgpainless/ImportExportKeyTest.java index 5d806771..0972b190 100644 --- a/src/test/java/org/pgpainless/pgpainless/ImportExportKeyTest.java +++ b/src/test/java/org/pgpainless/pgpainless/ImportExportKeyTest.java @@ -23,14 +23,16 @@ import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.util.Arrays; +import java.util.Iterator; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator; import org.junit.Test; -import org.pgpainless.pgpainless.util.BCUtil; +import org.pgpainless.pgpainless.key.collection.PGPKeyRing; public class ImportExportKeyTest { @@ -50,12 +52,18 @@ public class ImportExportKeyTest { public void test() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("alice@bla.blub"); - PGPPublicKeyRing publicKeys = BCUtil.publicKeyRingFromSecretKeyRing(secretKeys); + PGPKeyRing keyRing = PGPainless.generateKeyRing().simpleEcKeyRing("alice@bla.blub"); + PGPSecretKeyRing secretKeys = keyRing.getSecretKeys(); + PGPPublicKeyRing publicKeys = keyRing.getPublicKeys(); BcKeyFingerprintCalculator calc = new BcKeyFingerprintCalculator(); byte[] bytes = publicKeys.getEncoded(); PGPPublicKeyRing parsed = new PGPPublicKeyRing(bytes, calc); assertTrue(Arrays.equals(publicKeys.getEncoded(), parsed.getEncoded())); + + Iterator it = secretKeys.getPublicKeys(); + assertTrue(it.hasNext()); + it.next(); + assertTrue(it.hasNext()); } } diff --git a/src/test/java/org/pgpainless/pgpainless/LengthTest.java b/src/test/java/org/pgpainless/pgpainless/LengthTest.java index 9e4a2fde..f006dbab 100644 --- a/src/test/java/org/pgpainless/pgpainless/LengthTest.java +++ b/src/test/java/org/pgpainless/pgpainless/LengthTest.java @@ -31,10 +31,10 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.util.io.Streams; import org.junit.Ignore; +import org.pgpainless.pgpainless.key.collection.PGPKeyRing; +import org.pgpainless.pgpainless.key.generation.type.length.RsaLength; import org.pgpainless.pgpainless.key.protection.SecretKeyRingProtector; import org.pgpainless.pgpainless.key.protection.UnprotectedKeysProtector; -import org.pgpainless.pgpainless.key.generation.type.length.RsaLength; -import org.pgpainless.pgpainless.util.BCUtil; /** * Class used to determine the length of cipher-text depending on used algorithms. @@ -48,8 +48,8 @@ public class LengthTest extends AbstractPGPainlessTest { throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException { LOGGER.log(Level.INFO, "\nEC -> EC"); - PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("simplejid@server.tld"); - PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("otherjid@other.srv"); + PGPKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("simplejid@server.tld"); + PGPKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("otherjid@other.srv"); encryptDecryptForSecretKeyRings(sender, recipient); } @@ -59,8 +59,8 @@ public class LengthTest extends AbstractPGPainlessTest { throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException { LOGGER.log(Level.INFO, "\nRSA-2048 -> RSA-2048"); - PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("simplejid@server.tld", RsaLength._2048); - PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("otherjid@other.srv", RsaLength._2048); + PGPKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("simplejid@server.tld", RsaLength._2048); + PGPKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("otherjid@other.srv", RsaLength._2048); encryptDecryptForSecretKeyRings(sender, recipient); } @@ -69,8 +69,8 @@ public class LengthTest extends AbstractPGPainlessTest { throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException { LOGGER.log(Level.INFO, "\nRSA-4096 -> RSA-4096"); - PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("simplejid@server.tld", RsaLength._4096); - PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("otherjid@other.srv", RsaLength._4096); + PGPKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("simplejid@server.tld", RsaLength._4096); + PGPKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("otherjid@other.srv", RsaLength._4096); encryptDecryptForSecretKeyRings(sender, recipient); } @@ -78,8 +78,8 @@ public class LengthTest extends AbstractPGPainlessTest { public void rsaEc() throws PGPException, IOException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException { LOGGER.log(Level.INFO, "\nRSA-2048 -> EC"); - PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("simplejid@server.tld", RsaLength._2048); - PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("otherjid@other.srv"); + PGPKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("simplejid@server.tld", RsaLength._2048); + PGPKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("otherjid@other.srv"); encryptDecryptForSecretKeyRings(sender, recipient); } @@ -88,17 +88,19 @@ public class LengthTest extends AbstractPGPainlessTest { throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException { LOGGER.log(Level.INFO, "\nEC -> RSA-2048"); - PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("simplejid@server.tld"); - PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("otherjid@other.srv", RsaLength._2048); + PGPKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("simplejid@server.tld"); + PGPKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("otherjid@other.srv", RsaLength._2048); encryptDecryptForSecretKeyRings(sender, recipient); } @Ignore - private void encryptDecryptForSecretKeyRings(PGPSecretKeyRing sender, PGPSecretKeyRing recipient) + private void encryptDecryptForSecretKeyRings(PGPKeyRing sender, PGPKeyRing recipient) throws PGPException, IOException { - PGPPublicKeyRing recipientPub = BCUtil.publicKeyRingFromSecretKeyRing(recipient); - PGPPublicKeyRing senderPub = BCUtil.publicKeyRingFromSecretKeyRing(sender); + PGPSecretKeyRing recipientSec = recipient.getSecretKeys(); + PGPSecretKeyRing senderSec = sender.getSecretKeys(); + PGPPublicKeyRing recipientPub = recipient.getPublicKeys(); + PGPPublicKeyRing senderPub = sender.getPublicKeys(); SecretKeyRingProtector keyDecryptor = new UnprotectedKeysProtector(); @@ -113,7 +115,7 @@ public class LengthTest extends AbstractPGPainlessTest { .toRecipients(recipientPub) // .doNotEncrypt() .usingSecureAlgorithms() - .signWith(keyDecryptor, sender) + .signWith(keyDecryptor, senderSec) .noArmor(); Streams.pipeAll(new ByteArrayInputStream(secretMessage), encryptor); diff --git a/src/test/java/org/pgpainless/pgpainless/TestKeysTest.java b/src/test/java/org/pgpainless/pgpainless/TestKeysTest.java index d7ddea18..2923c219 100644 --- a/src/test/java/org/pgpainless/pgpainless/TestKeysTest.java +++ b/src/test/java/org/pgpainless/pgpainless/TestKeysTest.java @@ -26,13 +26,13 @@ import java.util.Arrays; import java.util.Collections; import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.util.io.Streams; import org.junit.Test; import org.pgpainless.pgpainless.decryption_verification.DecryptionStream; import org.pgpainless.pgpainless.key.protection.UnprotectedKeysProtector; -import org.pgpainless.pgpainless.util.BCUtil; public class TestKeysTest extends AbstractPGPainlessTest { @@ -57,7 +57,7 @@ public class TestKeysTest extends AbstractPGPainlessTest { DecryptionStream decryptor = PGPainless.createDecryptor() .onInputStream(new ByteArrayInputStream(encryptedMessage.getBytes())) .decryptWith(new UnprotectedKeysProtector(), new PGPSecretKeyRingCollection(Collections.singleton(juliet))) - .verifyWith(BCUtil.keyRingsToKeyRingCollection(BCUtil.publicKeyRingFromSecretKeyRing(juliet))) + .verifyWith(Collections.singleton(new PGPPublicKeyRing(Collections.singletonList(juliet.getPublicKey())))) .ignoreMissingPublicKeys() .build();