diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStreamFactory.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStreamFactory.java index d552ead8..f792460d 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStreamFactory.java +++ b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStreamFactory.java @@ -110,14 +110,31 @@ public final class DecryptionStreamFactory { private void initializeDetachedSignatures(Set signatures) { for (PGPSignature signature : signatures) { - long issuerKeyId = SignatureUtils.determineIssuerKeyId(signature); - PGPPublicKeyRing signingKeyRing = findSignatureVerificationKeyRing(issuerKeyId); + + List issuers = SignatureUtils.determineSignatureIssuers(signature); + if (issuers.isEmpty()) { + resultBuilder.addInvalidDetachedSignature(new SignatureVerification(signature, null), + new SignatureValidationException("Signature does not contain issuer information.")); + continue; + } + + PGPPublicKeyRing signingKeyRing = null; + long issuerKeyId = 0; + for (long candidate : issuers) { + issuerKeyId = candidate; + signingKeyRing = findSignatureVerificationKeyRing(issuerKeyId); + if (signingKeyRing != null) { + break; + } + } + if (signingKeyRing == null) { SignatureValidationException ex = new SignatureValidationException( - "Missing verification certificate " + Long.toHexString(issuerKeyId)); + "Missing verification certificate " + Long.toHexString(issuers.get(0))); resultBuilder.addInvalidDetachedSignature(new SignatureVerification(signature, null), ex); continue; } + PGPPublicKey signingKey = signingKeyRing.getPublicKey(issuerKeyId); SubkeyIdentifier signingKeyIdentifier = new SubkeyIdentifier(signingKeyRing, signingKey.getKeyID()); try { 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 1ebbdda4..3dc074bd 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureUtils.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/SignatureUtils.java @@ -10,6 +10,7 @@ import java.io.InputStream; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -296,6 +297,15 @@ public final class SignatureUtils { return 0; } + public static List determineSignatureIssuers(PGPSignature signature) { + Set issuers = new HashSet<>(SignatureSubpacketsUtil.getIssuerKeyIdsAsLongs(signature)); + List fingerprints = SignatureSubpacketsUtil.getIssuerFingerprintsAsOpenPgpFingerprints(signature); + for (OpenPgpFingerprint fingerprint : fingerprints) { + issuers.add(fingerprint.getKeyId()); + } + return new ArrayList<>(issuers); + } + /** * Return the digest prefix of the signature as hex-encoded String. * diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/consumer/SignatureValidator.java b/pgpainless-core/src/main/java/org/pgpainless/signature/consumer/SignatureValidator.java index e6c02ae0..12b61328 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/consumer/SignatureValidator.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/consumer/SignatureValidator.java @@ -60,27 +60,35 @@ public abstract class SignatureValidator { OpenPgpFingerprint signingKeyFingerprint = OpenPgpFingerprint.of(signingKey); List issuers = SignatureSubpacketsUtil.getIssuerKeyIdsAsLongs(signature); - boolean match = false; for (Long issuer : issuers) { if (issuer == 0L || issuer == signingKey.getKeyID()) { - match = true; - break; + // Match or wildcard issuer + return; } } - if (!match) { + List fingerprints = SignatureSubpacketsUtil.getIssuerFingerprintsAsOpenPgpFingerprints(signature); + for (OpenPgpFingerprint fingerprint : fingerprints) { + if (fingerprint.equals(signingKeyFingerprint)) { + // Match + return; + } + } + + // There were only mismatching fingerprints + if (!fingerprints.isEmpty()) { + throw new SignatureValidationException("Signature was not created by " + signingKeyFingerprint + + " (signature fingerprints: " + Arrays.toString(fingerprints.toArray(new OpenPgpFingerprint[0])) + ")"); + } + + // There were only mismatching issuers + if (!issuers.isEmpty()) { String[] hex = new String[issuers.size()]; for (int i = 0; i < hex.length; i++) { hex[i] = Long.toHexString(issuers.get(i)); } - throw new SignatureValidationException("Signature was not created by " + signingKeyFingerprint + " (signature issuers: " + Arrays.toString(hex) + ")"); - } - - OpenPgpFingerprint fingerprint = SignatureSubpacketsUtil.getIssuerFingerprintAsOpenPgpFingerprint(signature); - if (fingerprint != null) { - if (!fingerprint.equals(signingKeyFingerprint)) { - throw new SignatureValidationException("Signature was not created by " + signingKeyFingerprint + " (signature fingerprint: " + fingerprint + ")"); - } + throw new SignatureValidationException("Signature was not created by " + signingKeyFingerprint + + " (signature issuer: " + Arrays.toString(hex) + ")"); } // No issuer information found, so we cannot rule out that we did not create the sig diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketsUtil.java b/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketsUtil.java index 46af9d6c..cfc444cc 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketsUtil.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketsUtil.java @@ -45,6 +45,7 @@ import org.pgpainless.algorithm.SignatureSubpacket; import org.pgpainless.algorithm.SymmetricKeyAlgorithm; import org.pgpainless.key.OpenPgpFingerprint; import org.pgpainless.key.OpenPgpV4Fingerprint; +import org.pgpainless.key.OpenPgpV5Fingerprint; import org.pgpainless.key.generation.type.KeyType; import org.pgpainless.signature.SignatureUtils; @@ -72,6 +73,12 @@ public final class SignatureSubpacketsUtil { return hashedOrUnhashed(signature, SignatureSubpacket.issuerFingerprint); } + public static List getIssuerFingerprints(PGPSignature signature) { + List fingerprints = getSignatureSubpackets(signature.getHashedSubPackets(), SignatureSubpacket.issuerFingerprint); + fingerprints.addAll(getSignatureSubpackets(signature.getUnhashedSubPackets(), SignatureSubpacket.issuerFingerprint)); + return fingerprints; + } + /** * Return the {@link IssuerFingerprint} subpacket of the signature into a {@link org.pgpainless.key.OpenPgpFingerprint}. * If no v4 issuer fingerprint is present in the signature, return null. @@ -85,12 +92,31 @@ public final class SignatureSubpacketsUtil { return null; } - OpenPgpFingerprint fingerprint = null; - if (subpacket.getKeyVersion() == 4) { - fingerprint = new OpenPgpV4Fingerprint(subpacket.getFingerprint()); + return issuerFingerprintToOpenPgpFingerprint(subpacket); + } + + public static List getIssuerFingerprintsAsOpenPgpFingerprints(PGPSignature signature) { + List subpackets = getIssuerFingerprints(signature); + List fingerprints = new ArrayList<>(); + + for (IssuerFingerprint subpacket : subpackets) { + OpenPgpFingerprint fingerprint = issuerFingerprintToOpenPgpFingerprint(subpacket); + if (fingerprint != null) { + fingerprints.add(fingerprint); + } } - return fingerprint; + return fingerprints; + } + + private static OpenPgpFingerprint issuerFingerprintToOpenPgpFingerprint(@Nonnull IssuerFingerprint issuerFingerprint) { + if (issuerFingerprint.getKeyVersion() == 4) { + return new OpenPgpV4Fingerprint(issuerFingerprint.getFingerprint()); + } else if (issuerFingerprint.getKeyVersion() == 5) { + return new OpenPgpV5Fingerprint(issuerFingerprint.getFingerprint()); + } else { + return null; + } } public static List getIssuerKeyIds(PGPSignature signature) { diff --git a/pgpainless-core/src/test/java/org/pgpainless/signature/CertificateValidatorTest.java b/pgpainless-core/src/test/java/org/pgpainless/signature/CertificateValidatorTest.java index a17f700e..2c435501 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/signature/CertificateValidatorTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/signature/CertificateValidatorTest.java @@ -1320,6 +1320,50 @@ public class CertificateValidatorTest { return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)); } + private static final String CERT = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" + + "Comment: Bob's OpenPGP certificate\n" + + "\n" + + "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\n" + + "NEJd3XZRzaXZE2aAMQ==\n" + + "=NXei\n" + + "-----END PGP PUBLIC KEY BLOCK-----\n"; + private static final String DATA = "Hello World :)"; + @Test public void testNoIssuer() throws IOException, PGPException { String SIG = "-----BEGIN PGP SIGNATURE-----\n" + @@ -1338,49 +1382,134 @@ public class CertificateValidatorTest { "=NDO/\n" + "-----END PGP SIGNATURE-----\n"; - String CERT = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" + - "Comment: Bob's OpenPGP certificate\n" + + DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify() + .onInputStream(new ByteArrayInputStream(DATA.getBytes(StandardCharsets.UTF_8))) + .withOptions(new ConsumerOptions() + .addVerificationCert(PGPainless.readKeyRing().publicKeyRing(CERT)) + .addVerificationOfDetachedSignatures(new ByteArrayInputStream(SIG.getBytes(StandardCharsets.UTF_8)))); + + Streams.drain(decryptionStream); + + decryptionStream.close(); + OpenPgpMetadata metadata = decryptionStream.getResult(); + + assertFalse(metadata.getVerifiedSignatures().isEmpty()); + } + + @Test + public void testIssuerFakeIssuer() throws IOException, PGPException { + String SIG = "-----BEGIN PGP SIGNATURE-----\n" + "\n" + - "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\n" + - "NEJd3XZRzaXZE2aAMQ==\n" + - "=NXei\n" + - "-----END PGP PUBLIC KEY BLOCK-----\n"; - String DATA = "Hello World :)"; + "wsEuBAABCABOBYJiVdvoRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEt\n" + + "cGdwLm9yZziTJYEXbvrPrSZC/ZhOrQRXem5VvmP4cAAyu8+OsWYMABQJEPv8yCoB\n" + + "XnMwCRCqqru7zMzd3WftC/9IjroXgdTFm7HUrDoYoqj17IwoIRhjeUkuPfmZKfSv\n" + + "6F6YgHgTFQcMyLTcUzL30qzLDYLjWxZboiv2dvZylMWwzwXLfMM9DD2xNs/zAsgJ\n" + + "5op9wgzerx2WCzJYWg79wknkMNzILyscjBOIiSK1nXYZg8D7+Y6ZGr5qjufQ6++u\n" + + "xT6EDEK8WwjWIFyV1JO30e6o/mFXiskC4HeClblhBbcNV2tx3Uz0rY8Jstfa2Drr\n" + + "Eb4G3MoxCE8GVh3xGwbXZIeVzUX7xNI0n/9KoTjNq3CJEt+bN0AZCL/MIsns0b4B\n" + + "URMrM9KcC8CAUulqVqWp1pPvWxNR4Z5rBy5VIboFN1Lmdk261u5xhEDQd1ZYceaX\n" + + "AR46tmdim/hdh3wJ66KGofKGvk47ZZi5uGZngwWPOUfsyPkMWt4+e6HKiOHeWPlo\n" + + "wE9zbawxE4kXGZXtPyzYWJ93kYpKiYBsTBIaBEHu7TekWL90kyOxvLojBxvKzV5b\n" + + "LTBxodwh1J36MsCTyl7J8a4=\n" + + "=hGQP\n" + + "-----END PGP SIGNATURE-----\n"; + + DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify() + .onInputStream(new ByteArrayInputStream(DATA.getBytes(StandardCharsets.UTF_8))) + .withOptions(new ConsumerOptions() + .addVerificationCert(PGPainless.readKeyRing().publicKeyRing(CERT)) + .addVerificationOfDetachedSignatures(new ByteArrayInputStream(SIG.getBytes(StandardCharsets.UTF_8)))); + + Streams.drain(decryptionStream); + + decryptionStream.close(); + OpenPgpMetadata metadata = decryptionStream.getResult(); + + assertFalse(metadata.getVerifiedSignatures().isEmpty()); + } + + @Test + public void testFakeIssuerIssuer() throws IOException, PGPException { + String SIG = "-----BEGIN PGP SIGNATURE-----\n" + + "\n" + + "wsEuBAABCABOBYJiVdvoRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEt\n" + + "cGdwLm9yZxmM4YWln474ON+fma6Zg9RcflZ5IxmwImPZCATNyow8ABQJEKqqu7vM\n" + + "zN3dCRD7/MgqAV5zMB4GC/9qR05itFbTxjlHti1S7V2foZgqgb5KR8LbWLyX/m3j\n" + + "YctvlPyDmnIAp9vzI1P8JwQK5ubCx5/BcDgU6JgL9hl5JmtpDLfCdBypOCdZJhrz\n" + + "+MDvrxohWXXVHhWTbBoDu3U+5e7HuoDPrvsxEFTG/BVxXlLlOnVKJeTES3BEFj+G\n" + + "U8x8chWW82Koh/3sBE2+FPHCepZAlkrr6TF+j8QVmZ3kz5Qd7Y7hXjXi3BA2Fb1g\n" + + "LNCNATzt/Uuc42MIjaDuXqvvqrnR/DlRCKXZKwurp1Gcc2kGE4iYw1vzf2kcKUS6\n" + + "0gQ2wCexgdiojUheHXNaDp6pgng9V2B+T1GOUhEUCYh8pnQRva0HkueLbu5MVXuE\n" + + "h6GbId1qkRvmDiVSjJIY6AbU1uryvNjRCAh+zTPhVSBc5ZuWpAuGeiK+os+sVLbM\n" + + "TYozxdINWMwlLbueD0rPy2iAKVF9xRy/uMIUlXBOOFa0vtr/LbEbt/Z+HEmkEbSA\n" + + "nOU6uODYKlnq6J5e1oykx1I=\n" + + "=HwGW\n" + + "-----END PGP SIGNATURE-----\n"; + + DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify() + .onInputStream(new ByteArrayInputStream(DATA.getBytes(StandardCharsets.UTF_8))) + .withOptions(new ConsumerOptions() + .addVerificationCert(PGPainless.readKeyRing().publicKeyRing(CERT)) + .addVerificationOfDetachedSignatures(new ByteArrayInputStream(SIG.getBytes(StandardCharsets.UTF_8)))); + + Streams.drain(decryptionStream); + + decryptionStream.close(); + OpenPgpMetadata metadata = decryptionStream.getResult(); + + assertFalse(metadata.getVerifiedSignatures().isEmpty()); + } + + @Test + public void testIssuerFakeIssuerV6IssuerFp() throws IOException, PGPException { + String SIG = "-----BEGIN PGP SIGNATURE-----\n" + + "\n" + + "wsFTBAABCABOBYJiVdvoRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEt\n" + + "cGdwLm9yZ3l3fkL3IE31d0/2jrnPb7vgSpgZLx/yyaA/rq5a4IgFADkJEPv8yCoB\n" + + "XnMwCRCqqru7zMzd3SQhBqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\n" + + "qqq1NgwAj0/RjdIITzOC6RblmUrFiB4GxcE5704Kcs++AfEDNTkHOT7j6VGdj+IL\n" + + "xKeEHq0LTH8OIWXtAQUxZjJaHVMwwsA7D3BYWaL8YJ5dgbDrtSAXyGXz5+WBPVFQ\n" + + "ucka8ZRsolCF2VA6WuY1LI4cUYVx0Y6ZvaNtbyhEUtDQhu9UDJN8Ty18uq3M2Trb\n" + + "MwGJBpb92zrLtmIhhuoeIienSPYek+nCs1dVPBIu/Z4nyUaDoWSEWPgKJd+7dB6q\n" + + "v6kMHKpN/tu6Wq0jJ28E2IkvNH4+OdPmKFzHcDF3dXxd8hwzsXPolDA3yPO+891Q\n" + + "wnDKUvvlKbzz2Dvfce2Qv2DQkWufWrhSS8j6zqo0O97AEPpDSGoIMFlphvpcp/S5\n" + + "sz+okAOMU1lfhrMx3rZPi31HgfhcPExRmQBQOdxRXD0nqaCwZJWKRsUK1XxtQNHk\n" + + "r7al/8tPjlHs2KhE/XPYSjI3rc8ZnSvhnl3yzjSkDGkcM0bt7O+HpZUuQNvTy76K\n" + + "tXgaehUQ\n" + + "=v71i\n" + + "-----END PGP SIGNATURE-----\n"; + + DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify() + .onInputStream(new ByteArrayInputStream(DATA.getBytes(StandardCharsets.UTF_8))) + .withOptions(new ConsumerOptions() + .addVerificationCert(PGPainless.readKeyRing().publicKeyRing(CERT)) + .addVerificationOfDetachedSignatures(new ByteArrayInputStream(SIG.getBytes(StandardCharsets.UTF_8)))); + + Streams.drain(decryptionStream); + + decryptionStream.close(); + OpenPgpMetadata metadata = decryptionStream.getResult(); + + assertFalse(metadata.getVerifiedSignatures().isEmpty()); + } + + @Test + public void testFakeIssuerIssuerV6IssuerFp() throws IOException, PGPException { + String SIG = "-----BEGIN PGP SIGNATURE-----\n" + + "\n" + + "wsEuBAABCABOBYJiVdvoRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEt\n" + + "cGdwLm9yZziTJYEXbvrPrSZC/ZhOrQRXem5VvmP4cAAyu8+OsWYMABQJEPv8yCoB\n" + + "XnMwCRCqqru7zMzd3WftC/9IjroXgdTFm7HUrDoYoqj17IwoIRhjeUkuPfmZKfSv\n" + + "6F6YgHgTFQcMyLTcUzL30qzLDYLjWxZboiv2dvZylMWwzwXLfMM9DD2xNs/zAsgJ\n" + + "5op9wgzerx2WCzJYWg79wknkMNzILyscjBOIiSK1nXYZg8D7+Y6ZGr5qjufQ6++u\n" + + "xT6EDEK8WwjWIFyV1JO30e6o/mFXiskC4HeClblhBbcNV2tx3Uz0rY8Jstfa2Drr\n" + + "Eb4G3MoxCE8GVh3xGwbXZIeVzUX7xNI0n/9KoTjNq3CJEt+bN0AZCL/MIsns0b4B\n" + + "URMrM9KcC8CAUulqVqWp1pPvWxNR4Z5rBy5VIboFN1Lmdk261u5xhEDQd1ZYceaX\n" + + "AR46tmdim/hdh3wJ66KGofKGvk47ZZi5uGZngwWPOUfsyPkMWt4+e6HKiOHeWPlo\n" + + "wE9zbawxE4kXGZXtPyzYWJ93kYpKiYBsTBIaBEHu7TekWL90kyOxvLojBxvKzV5b\n" + + "LTBxodwh1J36MsCTyl7J8a4=\n" + + "=hGQP\n" + + "-----END PGP SIGNATURE-----\n"; DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify() .onInputStream(new ByteArrayInputStream(DATA.getBytes(StandardCharsets.UTF_8)))