diff --git a/pgpainless-core/src/main/java/org/pgpainless/algorithm/SignatureType.java b/pgpainless-core/src/main/java/org/pgpainless/algorithm/SignatureType.java index 30caef04..35d7706c 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/algorithm/SignatureType.java +++ b/pgpainless-core/src/main/java/org/pgpainless/algorithm/SignatureType.java @@ -226,7 +226,7 @@ public enum SignatureType { case CERTIFICATION_REVOCATION: return true; default: - throw new IllegalArgumentException("Unknown type: " + signatureType); + throw new IllegalArgumentException("Unknown signature type: " + signatureType); } } diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStream.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStream.java index 145a883d..3b9b28d3 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStream.java +++ b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStream.java @@ -26,7 +26,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.pgpainless.PGPainless; import org.pgpainless.signature.DetachedSignature; import org.pgpainless.signature.SignatureChainValidator; -import org.pgpainless.signature.SignatureValidationException; +import org.pgpainless.exception.SignatureValidationException; import org.pgpainless.util.IntegrityProtectedInputStream; /** diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/SignatureVerifyingInputStream.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/SignatureVerifyingInputStream.java index 2274d28f..5e8eae44 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/SignatureVerifyingInputStream.java +++ b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/SignatureVerifyingInputStream.java @@ -38,7 +38,7 @@ import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.policy.Policy; import org.pgpainless.signature.OnePassSignature; import org.pgpainless.signature.SignatureChainValidator; -import org.pgpainless.signature.SignatureValidationException; +import org.pgpainless.exception.SignatureValidationException; public class SignatureVerifyingInputStream extends FilterInputStream { diff --git a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilder.java b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilder.java index 68882e63..67ee58ec 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilder.java +++ b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilder.java @@ -33,6 +33,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; import org.pgpainless.PGPainless; import org.pgpainless.algorithm.CompressionAlgorithm; @@ -176,7 +177,7 @@ public class EncryptionBuilder implements EncryptionBuilderInterface { } } if (encryptionKeys.isEmpty()) { - throw new IllegalArgumentException("No suitable encryption key found in key ring " + new OpenPgpV4Fingerprint(ring)); + throw new IllegalArgumentException("No suitable encryption key found in the key ring " + new OpenPgpV4Fingerprint(ring)); } EncryptionBuilder.this.encryptionKeys.putAll(encryptionKeys); } @@ -194,7 +195,7 @@ public class EncryptionBuilder implements EncryptionBuilderInterface { } } if (encryptionKeys.isEmpty()) { - throw new IllegalArgumentException("No suitable encryption key found in key ring " + new OpenPgpV4Fingerprint(ring)); + throw new IllegalArgumentException("No suitable encryption key found in the key ring " + new OpenPgpV4Fingerprint(ring)); } EncryptionBuilder.this.encryptionKeys.putAll(encryptionKeys); } @@ -246,6 +247,11 @@ public class EncryptionBuilder implements EncryptionBuilderInterface { return new SignWithImpl().signWith(decryptor, keyRings); } + @Override + public DocumentType signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKeyRingCollection keyRings) { + return new SignWithImpl().signWith(decryptor, keyRings); + } + } class SignWithImpl implements SignWith { @@ -254,7 +260,7 @@ public class EncryptionBuilder implements EncryptionBuilderInterface { public DocumentType signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKeyRing... keyRings) { if (keyRings.length == 0) { - throw new IllegalArgumentException("Recipient list MUST NOT be empty."); + throw new IllegalArgumentException("Signing key list MUST NOT be empty."); } for (PGPSecretKeyRing ring : keyRings) { Map signingKeys = new ConcurrentHashMap<>(); @@ -266,7 +272,7 @@ public class EncryptionBuilder implements EncryptionBuilderInterface { } if (signingKeys.isEmpty()) { - throw new IllegalArgumentException("No suitable signing key found in key ring " + new OpenPgpV4Fingerprint(ring)); + throw new IllegalArgumentException("No suitable signing key found in the key ring " + new OpenPgpV4Fingerprint(ring)); } EncryptionBuilder.this.signingKeys.putAll(signingKeys); @@ -274,6 +280,33 @@ public class EncryptionBuilder implements EncryptionBuilderInterface { EncryptionBuilder.this.signingKeysDecryptor = decryptor; return new DocumentTypeImpl(); } + + @Override + public DocumentType signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKeyRingCollection keyRings) { + Iterator iterator = keyRings.iterator(); + if (!iterator.hasNext()) { + throw new IllegalArgumentException("Signing key collection MUST NOT be empty."); + } + while (iterator.hasNext()) { + PGPSecretKeyRing ring = iterator.next(); + Map signingKeys = new ConcurrentHashMap<>(); + for (Iterator i = ring.getSecretKeys(); i.hasNext(); ) { + PGPSecretKey s = i.next(); + if (EncryptionBuilder.this.signingKeySelector().accept(s)) { + signingKeys.put(new SubkeyIdentifier(ring, s.getKeyID()), ring); + } + } + + if (signingKeys.isEmpty()) { + throw new IllegalArgumentException("No suitable signing key found in the key ring " + new OpenPgpV4Fingerprint(ring)); + } + + EncryptionBuilder.this.signingKeys.putAll(signingKeys); + } + + EncryptionBuilder.this.signingKeysDecryptor = decryptor; + return new DocumentTypeImpl(); + } } class DocumentTypeImpl implements DocumentType { diff --git a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilderInterface.java b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilderInterface.java index 9e584dfa..0e16f33e 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilderInterface.java +++ b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilderInterface.java @@ -24,6 +24,7 @@ import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.HashAlgorithm; import org.pgpainless.algorithm.StreamEncoding; @@ -191,6 +192,8 @@ public interface EncryptionBuilderInterface { */ DocumentType signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKeyRing... keyRings); + DocumentType signWith(@Nonnull SecretKeyRingProtector decryptor, @Nonnull PGPSecretKeyRingCollection keyRings); + } interface DocumentType { diff --git a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionStream.java b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionStream.java index 3c44b290..8cc4d974 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionStream.java +++ b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionStream.java @@ -213,7 +213,7 @@ public final class EncryptionStream extends OutputStream { private void prepareCompression() throws IOException { compressedDataGenerator = new PGPCompressedDataGenerator( - compressionAlgorithm.getAlgorithmId()); + compressionAlgorithm.getAlgorithmId()); if (compressionAlgorithm == CompressionAlgorithm.UNCOMPRESSED) { return; } @@ -290,7 +290,11 @@ public final class EncryptionStream extends OutputStream { literalDataStream.close(); literalDataGenerator.close(); - writeSignatures(); + try { + writeSignatures(); + } catch (PGPException e) { + throw new IOException("Exception while writing signatures.", e); + } // Compressed Data compressedDataGenerator.close(); @@ -309,20 +313,16 @@ public final class EncryptionStream extends OutputStream { closed = true; } - private void writeSignatures() throws IOException { + private void writeSignatures() throws PGPException, IOException { for (SubkeyIdentifier signingKey : signatureGenerators.keySet()) { PGPSignatureGenerator signatureGenerator = signatureGenerators.get(signingKey).getSecond(); - try { - PGPSignature signature = signatureGenerator.generate(); - if (!detachedSignature) { - signature.encode(outermostStream); - } - DetachedSignature detachedSignature = new DetachedSignature( - signature, signatureGenerators.get(signingKey).getFirst(), signingKey); - resultBuilder.addDetachedSignature(detachedSignature); - } catch (PGPException e) { - throw new IOException(e); + PGPSignature signature = signatureGenerator.generate(); + if (!detachedSignature) { + signature.encode(outermostStream); } + DetachedSignature detachedSignature = new DetachedSignature( + signature, signatureGenerators.get(signingKey).getFirst(), signingKey); + resultBuilder.addDetachedSignature(detachedSignature); } } diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureValidationException.java b/pgpainless-core/src/main/java/org/pgpainless/exception/SignatureValidationException.java similarity index 65% rename from pgpainless-core/src/main/java/org/pgpainless/signature/SignatureValidationException.java rename to pgpainless-core/src/main/java/org/pgpainless/exception/SignatureValidationException.java index 70d771ee..34a4a581 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureValidationException.java +++ b/pgpainless-core/src/main/java/org/pgpainless/exception/SignatureValidationException.java @@ -13,20 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.pgpainless.signature; +package org.pgpainless.exception; import java.util.Map; +import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPSignature; import org.pgpainless.algorithm.SignatureType; -public class SignatureValidationException extends Exception { +public class SignatureValidationException extends PGPException { public SignatureValidationException(String message) { super(message); } - public SignatureValidationException(String message, Throwable underlying) { + public SignatureValidationException(String message, Exception underlying) { super(message, underlying); } @@ -35,11 +36,13 @@ public class SignatureValidationException extends Exception { } private static String exceptionMapToString(Map rejections) { - String out = ""; - out += rejections.size() + " Rejected signatures:\n"; + StringBuilder sb = new StringBuilder(); + sb.append(rejections.size()).append(" rejected signatures:\n"); for (PGPSignature signature : rejections.keySet()) { - out += SignatureType.valueOf(signature.getSignatureType()) + " " + signature.getCreationTime() + ": " + rejections.get(signature).getMessage() + "\n"; + sb.append(SignatureType.valueOf(signature.getSignatureType())).append(' ') + .append(signature.getCreationTime()).append(": ") + .append(rejections.get(signature).getMessage()).append('\n'); } - return out; - }; + return sb.toString(); + } } diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/KeyRingValidator.java b/pgpainless-core/src/main/java/org/pgpainless/key/KeyRingValidator.java index 12be46cc..598dc2d3 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/key/KeyRingValidator.java +++ b/pgpainless-core/src/main/java/org/pgpainless/key/KeyRingValidator.java @@ -36,7 +36,7 @@ import org.pgpainless.key.util.KeyRingUtils; import org.pgpainless.policy.Policy; import org.pgpainless.signature.SelectSignatureFromKey; import org.pgpainless.signature.SignatureCreationDateComparator; -import org.pgpainless.signature.SignatureValidationException; +import org.pgpainless.exception.SignatureValidationException; import org.pgpainless.signature.SignatureValidator; import org.pgpainless.util.CollectionUtils; @@ -74,7 +74,7 @@ public class KeyRingValidator { Iterator directKeyIterator = primaryKey.getSignaturesOfType(SignatureType.DIRECT_KEY.getCode()); List directKeyCertifications = CollectionUtils.iteratorToList(directKeyIterator); - Collections.sort(directKeyCertifications, new SignatureCreationDateComparator(SignatureCreationDateComparator.Order.new_to_old)); + Collections.sort(directKeyCertifications, new SignatureCreationDateComparator(SignatureCreationDateComparator.Order.NEW_TO_OLD)); for (PGPSignature signature : directKeyCertifications) { try { if (SignatureValidator.verifyDirectKeySignature(signature, blank, policy, validationDate)) { @@ -87,7 +87,7 @@ public class KeyRingValidator { Iterator revocationIterator = primaryKey.getSignaturesOfType(SignatureType.KEY_REVOCATION.getCode()); List directKeyRevocations = CollectionUtils.iteratorToList(revocationIterator); - Collections.sort(directKeyRevocations, new SignatureCreationDateComparator(SignatureCreationDateComparator.Order.new_to_old)); + Collections.sort(directKeyRevocations, new SignatureCreationDateComparator(SignatureCreationDateComparator.Order.NEW_TO_OLD)); for (PGPSignature signature : directKeyRevocations) { try { if (SignatureValidator.verifyKeyRevocationSignature(signature, primaryKey, policy, validationDate)) { @@ -103,7 +103,7 @@ public class KeyRingValidator { String userId = userIdIterator.next(); Iterator userIdSigs = primaryKey.getSignaturesForID(userId); List signatures = CollectionUtils.iteratorToList(userIdSigs); - Collections.sort(signatures, new SignatureCreationDateComparator(SignatureCreationDateComparator.Order.new_to_old)); + Collections.sort(signatures, new SignatureCreationDateComparator(SignatureCreationDateComparator.Order.NEW_TO_OLD)); for (PGPSignature signature : signatures) { try { if (SignatureType.valueOf(signature.getSignatureType()) == SignatureType.CERTIFICATION_REVOCATION) { diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/info/KeyRingInfo.java b/pgpainless-core/src/main/java/org/pgpainless/key/info/KeyRingInfo.java index 70656001..46ae9e4a 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/key/info/KeyRingInfo.java +++ b/pgpainless-core/src/main/java/org/pgpainless/key/info/KeyRingInfo.java @@ -143,11 +143,11 @@ public class KeyRingInfo { if (publicKey == getPublicKey()) { return revocationSelfSignature == null; - } else { - PGPSignature binding = mostRecentSubkeyBindings.get(keyId); - PGPSignature revocation = mostRecentSubkeyRevocations.get(keyId); - return binding != null && revocation == null; } + + PGPSignature binding = mostRecentSubkeyBindings.get(keyId); + PGPSignature revocation = mostRecentSubkeyRevocations.get(keyId); + return binding != null && revocation == null; } /** @@ -264,10 +264,7 @@ public class KeyRingInfo { PGPSignature certification = mostRecentUserIdSignatures.get(userId); PGPSignature revocation = mostRecentUserIdRevocations.get(userId); - if (certification == null) { - return false; - } - return revocation == null; + return certification != null && revocation == null; } /** diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureChainValidator.java b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureChainValidator.java index cbe36f8f..52ed9a3f 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureChainValidator.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureChainValidator.java @@ -31,6 +31,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSignature; import org.pgpainless.algorithm.KeyFlag; import org.pgpainless.algorithm.SignatureType; +import org.pgpainless.exception.SignatureValidationException; import org.pgpainless.policy.Policy; import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil; @@ -76,7 +77,7 @@ public class SignatureChainValidator { } } - Collections.sort(directKeySignatures, new SignatureValidityComparator(SignatureCreationDateComparator.Order.new_to_old)); + Collections.sort(directKeySignatures, new SignatureValidityComparator(SignatureCreationDateComparator.Order.NEW_TO_OLD)); if (directKeySignatures.isEmpty()) { } else { @@ -102,7 +103,7 @@ public class SignatureChainValidator { LOGGER.log(Level.INFO, "Rejecting user-id signature.", e); } } - Collections.sort(signaturesOnUserId, new SignatureValidityComparator(SignatureCreationDateComparator.Order.new_to_old)); + Collections.sort(signaturesOnUserId, new SignatureValidityComparator(SignatureCreationDateComparator.Order.NEW_TO_OLD)); userIdSignatures.put(userId, signaturesOnUserId); } @@ -150,7 +151,7 @@ public class SignatureChainValidator { } } - Collections.sort(subkeySigs, new SignatureValidityComparator(SignatureCreationDateComparator.Order.new_to_old)); + Collections.sort(subkeySigs, new SignatureValidityComparator(SignatureCreationDateComparator.Order.NEW_TO_OLD)); if (subkeySigs.isEmpty()) { throw new SignatureValidationException("Subkey is not bound.", rejections); } diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureCreationDateComparator.java b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureCreationDateComparator.java index 7ac3f505..2f53e1a3 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureCreationDateComparator.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureCreationDateComparator.java @@ -21,11 +21,11 @@ import org.bouncycastle.openpgp.PGPSignature; public class SignatureCreationDateComparator implements Comparator { - public static final Order DEFAULT_ORDER = Order.old_to_new; + public static final Order DEFAULT_ORDER = Order.OLD_TO_NEW; public enum Order { - old_to_new, - new_to_old + OLD_TO_NEW, + NEW_TO_OLD } private final Order order; @@ -40,7 +40,7 @@ public class SignatureCreationDateComparator implements Comparator @Override public int compare(PGPSignature one, PGPSignature two) { - return order == Order.old_to_new + return order == Order.OLD_TO_NEW ? one.getCreationTime().compareTo(two.getCreationTime()) : two.getCreationTime().compareTo(one.getCreationTime()); } diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureUtils.java b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureUtils.java index 42e819aa..5df4d15a 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureUtils.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureUtils.java @@ -170,6 +170,16 @@ public class SignatureUtils { return datePlusSeconds(creationDate, expiresInSecs); } + /** + * Return a new date which represents the given date plus the given amount of seconds added. + * + * Since '0' is a special value in the OpenPGP specification when it comes to dates + * (e.g. '0' means no expiration for expiration dates), this method will return 'null' if seconds is 0. + * + * @param date date + * @param seconds number of seconds to be added + * @return date plus seconds or null if seconds is '0' + */ public static Date datePlusSeconds(Date date, long seconds) { if (seconds == 0) { return null; @@ -183,10 +193,7 @@ public class SignatureUtils { public static boolean isSignatureExpired(PGPSignature signature, Date comparisonDate) { Date expirationDate = getSignatureExpirationDate(signature); - if (expirationDate == null) { - return false; - } - return comparisonDate.after(expirationDate); + return expirationDate != null && comparisonDate.after(expirationDate); } public static void sortByCreationTimeAscending(List signatures) { diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureValidator.java b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureValidator.java index 35b2663e..7b3dfd12 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureValidator.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureValidator.java @@ -36,6 +36,7 @@ import org.pgpainless.algorithm.HashAlgorithm; import org.pgpainless.algorithm.PublicKeyAlgorithm; import org.pgpainless.algorithm.SignatureSubpacket; import org.pgpainless.algorithm.SignatureType; +import org.pgpainless.exception.SignatureValidationException; import org.pgpainless.implementation.ImplementationFactory; import org.pgpainless.policy.Policy; import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil; diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureValidityComparator.java b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureValidityComparator.java index 67a09045..d60fb39e 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureValidityComparator.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureValidityComparator.java @@ -35,13 +35,12 @@ public class SignatureValidityComparator implements Comparator { @Override public int compare(PGPSignature one, PGPSignature two) { - int compareByCreationTime = creationDateComparator.compare(one, two); boolean oneIsHard = SignatureUtils.isHardRevocation(one); boolean twoIsHard = SignatureUtils.isHardRevocation(two); // both have same "hardness", so compare creation time if (oneIsHard == twoIsHard) { - return compareByCreationTime; + return creationDateComparator.compare(one, two); } // favor the "harder" signature return oneIsHard ? -1 : 1; diff --git a/pgpainless-core/src/main/java/org/pgpainless/util/BCUtil.java b/pgpainless-core/src/main/java/org/pgpainless/util/BCUtil.java index 5fd9a022..3eab058a 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/util/BCUtil.java +++ b/pgpainless-core/src/main/java/org/pgpainless/util/BCUtil.java @@ -259,8 +259,15 @@ public class BCUtil { return ring.getSecretKey(keyId) != null; } - public static PGPSignatureList readSignatures(String encoding) throws IOException { - InputStream inputStream = getPgpDecoderInputStream(encoding.getBytes(Charset.forName("UTF8"))); + /** + * Parse an ASCII encoded list of OpenPGP signatures into a {@link PGPSignatureList}. + * + * @param encodedSignatures ASCII armored signature list + * @return signature list + * @throws IOException if the signatures cannot be read + */ + public static PGPSignatureList readSignatures(String encodedSignatures) throws IOException { + InputStream inputStream = getPgpDecoderInputStream(encodedSignatures.getBytes(Charset.forName("UTF8"))); PGPObjectFactory objectFactory = new PGPObjectFactory(inputStream, ImplementationFactory.getInstance().getKeyFingerprintCalculator()); Object next = objectFactory.nextObject(); while (next != null) { @@ -271,5 +278,5 @@ public class BCUtil { return (PGPSignatureList) next; } return null; - }; + } } diff --git a/pgpainless-core/src/main/java/org/pgpainless/util/Tuple.java b/pgpainless-core/src/main/java/org/pgpainless/util/Tuple.java index 208fcd61..e2eceef7 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/util/Tuple.java +++ b/pgpainless-core/src/main/java/org/pgpainless/util/Tuple.java @@ -16,19 +16,19 @@ package org.pgpainless.util; public class Tuple { - private final A a; - private final B b; + private final A first; + private final B second; - public Tuple(A a, B b) { - this.a = a; - this.b = b; + public Tuple(A first, B second) { + this.first = first; + this.second = second; } public A getFirst() { - return a; + return first; } public B getSecond() { - return b; + return second; } } diff --git a/pgpainless-core/src/test/java/org/junit/JUtils.java b/pgpainless-core/src/test/java/org/junit/JUtils.java index 553d1f61..c053027f 100644 --- a/pgpainless-core/src/test/java/org/junit/JUtils.java +++ b/pgpainless-core/src/test/java/org/junit/JUtils.java @@ -17,16 +17,9 @@ package org.junit; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; - public class JUtils { public static void assertEquals(long a, long b, long delta) { assertTrue(a - delta <= b && a + delta >= b); } - - @Test - public void comparatorLearningTest() { - assertEquals(-1, Integer.compare(5,6), 0); - } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/signature/BindingSignatureSubpacketsTest.java b/pgpainless-core/src/test/java/org/pgpainless/signature/BindingSignatureSubpacketsTest.java index 453aed79..501837fd 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/signature/BindingSignatureSubpacketsTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/signature/BindingSignatureSubpacketsTest.java @@ -28,6 +28,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSignature; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; +import org.pgpainless.exception.SignatureValidationException; import org.pgpainless.policy.Policy; import org.pgpainless.util.BCUtil; diff --git a/pgpainless-core/src/test/java/org/pgpainless/signature/KeyRevocationTest.java b/pgpainless-core/src/test/java/org/pgpainless/signature/KeyRevocationTest.java index 0b0f7788..1bf1a7c5 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/signature/KeyRevocationTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/signature/KeyRevocationTest.java @@ -26,6 +26,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSignature; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; +import org.pgpainless.exception.SignatureValidationException; import org.pgpainless.util.BCUtil; public class KeyRevocationTest { diff --git a/pgpainless-core/src/test/java/org/pgpainless/signature/SignatureChainValidatorTest.java b/pgpainless-core/src/test/java/org/pgpainless/signature/SignatureChainValidatorTest.java index b89b8382..c42dfec9 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/signature/SignatureChainValidatorTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/signature/SignatureChainValidatorTest.java @@ -28,6 +28,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSignature; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; +import org.pgpainless.exception.SignatureValidationException; import org.pgpainless.policy.Policy; import org.pgpainless.util.BCUtil; diff --git a/pgpainless-core/src/test/java/org/pgpainless/util/selection/signature/SelectSignatureFromKeyTest.java b/pgpainless-core/src/test/java/org/pgpainless/util/selection/signature/SelectSignatureFromKeyTest.java index ffd1ac9e..11dc3bb1 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/util/selection/signature/SelectSignatureFromKeyTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/util/selection/signature/SelectSignatureFromKeyTest.java @@ -15,10 +15,13 @@ */ package org.pgpainless.util.selection.signature; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + import java.io.IOException; import java.util.Iterator; -import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSignature; @@ -29,7 +32,7 @@ import org.pgpainless.signature.SelectSignatureFromKey; public class SelectSignatureFromKeyTest { @Test - public void validKeyTest() throws IOException, PGPException { + public void validKeyTest() throws IOException { String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" + "\n" + "xsDNBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv\n" + @@ -90,19 +93,19 @@ public class SelectSignatureFromKeyTest { PGPPublicKey primaryKey = publicKeys.getPublicKey(); while (keyIt.hasNext()) { PGPPublicKey publicKey = keyIt.next(); - // CHECKSTYLE:OFF - System.out.println(publicKey.getKeyID()); - // CHECKSTYLE:ON + if (publicKey == primaryKey) { + continue; + } + boolean validBinding = false; Iterator signatures = publicKey.getSignatures(); while (signatures.hasNext()) { PGPSignature signature = signatures.next(); if (SelectSignatureFromKey.isValidSubkeyBindingSignature(primaryKey, publicKey).accept(signature, publicKey, publicKeys)) { - // CHECKSTYLE:OFF - System.out.println("Valid subkey binding signature"); - // CHECKSTYLE:ON + validBinding = true; } } + assertTrue(validBinding); } } @@ -156,31 +159,17 @@ public class SelectSignatureFromKeyTest { PGPPublicKey primaryKey = publicKeys.getPublicKey(); while (keyIt.hasNext()) { PGPPublicKey publicKey = keyIt.next(); - // CHECKSTYLE:OFF - System.out.println(publicKey.getKeyID()); - // CHECKSTYLE:ON - if (publicKey.isMasterKey()) { - Iterator signatures = publicKey.getSignatures(); - boolean isValidPrimaryKey = false; - boolean isRevokedPrimaryKey = false; - while (signatures.hasNext()) { - PGPSignature signature = signatures.next(); - } - } else { - Iterator signatures = publicKey.getSignatures(); - while (signatures.hasNext()) { - PGPSignature signature = signatures.next(); - - if (SelectSignatureFromKey.isValidSubkeyBindingSignature(primaryKey, publicKey).accept(signature, publicKey, publicKeys)) { - // CHECKSTYLE:OFF - System.out.println("Valid subkey binding signature"); - // CHECKSTYLE:ON - } - } + if (publicKey == primaryKey) { + continue; } - - + Iterator signatures = publicKey.getSignatures(); + while (signatures.hasNext()) { + PGPSignature signature = signatures.next(); + if (SelectSignatureFromKey.isValidSubkeyBindingSignature(primaryKey, publicKey).accept(signature, publicKey, publicKeys)) { + fail("Implementation MUST NOT accept this subkey as bound valid since the backsig is missing."); + } + } } } }