From b99822f405eaaf9283ea5d5a959fa08d6d318306 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 19 Nov 2024 13:58:54 +0100 Subject: [PATCH] Ignore certificate signatures of unknown type --- .../decryption_verification/OpenPgpInputStream.java | 9 +++++---- .../exception/SignatureValidationException.java | 9 ++++++++- .../pgpainless/key/util/OpenPgpKeyAttributeUtil.java | 10 +++++++--- .../kotlin/org/pgpainless/algorithm/SignatureType.kt | 3 ++- .../bouncycastle/extensions/PGPSignatureExtensions.kt | 5 +++-- .../signature/consumer/SignatureValidator.kt | 6 ++++-- .../pgpainless/signature/consumer/SignatureVerifier.kt | 5 +++-- .../org/pgpainless/algorithm/SignatureTypeTest.java | 3 +-- 8 files changed, 33 insertions(+), 17 deletions(-) diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpInputStream.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpInputStream.java index ff020a7b..3522f509 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpInputStream.java +++ b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpInputStream.java @@ -32,6 +32,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; +import java.util.NoSuchElementException; import org.bouncycastle.bcpg.BCPGInputStream; import org.bouncycastle.openpgp.PGPCompressedData; @@ -208,8 +209,8 @@ public class OpenPgpInputStream extends BufferedInputStream { } try { - SignatureType.valueOf(sigType); - } catch (IllegalArgumentException e) { + SignatureType.requireFromCode(sigType); + } catch (NoSuchElementException e) { return; } @@ -236,8 +237,8 @@ public class OpenPgpInputStream extends BufferedInputStream { if (opsVersion == 3) { int opsSigType = bcpgIn.read(); try { - SignatureType.valueOf(opsSigType); - } catch (IllegalArgumentException e) { + SignatureType.requireFromCode(opsSigType); + } catch (NoSuchElementException e) { return; } int opsHashAlg = bcpgIn.read(); diff --git a/pgpainless-core/src/main/java/org/pgpainless/exception/SignatureValidationException.java b/pgpainless-core/src/main/java/org/pgpainless/exception/SignatureValidationException.java index b5b8941d..2141ec5c 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/exception/SignatureValidationException.java +++ b/pgpainless-core/src/main/java/org/pgpainless/exception/SignatureValidationException.java @@ -28,7 +28,14 @@ public class SignatureValidationException extends PGPException { StringBuilder sb = new StringBuilder(); sb.append(rejections.size()).append(" rejected signatures:\n"); for (PGPSignature signature : rejections.keySet()) { - sb.append(SignatureType.valueOf(signature.getSignatureType())).append(' ') + String typeString; + SignatureType type = SignatureType.fromCode(signature.getSignatureType()); + if (type == null) { + typeString = "0x" + Long.toHexString(signature.getSignatureType()); + } else { + typeString = type.toString(); + } + sb.append(typeString).append(' ') .append(signature.getCreationTime()).append(": ") .append(rejections.get(signature).getMessage()).append('\n'); } diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/util/OpenPgpKeyAttributeUtil.java b/pgpainless-core/src/main/java/org/pgpainless/key/util/OpenPgpKeyAttributeUtil.java index e97a2d7a..f7a78404 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/key/util/OpenPgpKeyAttributeUtil.java +++ b/pgpainless-core/src/main/java/org/pgpainless/key/util/OpenPgpKeyAttributeUtil.java @@ -34,7 +34,11 @@ public final class OpenPgpKeyAttributeUtil { continue; } - SignatureType signatureType = SignatureType.valueOf(signature.getSignatureType()); + SignatureType signatureType = SignatureType.fromCode(signature.getSignatureType()); + if (signatureType == null) { + // unknown signature type + continue; + } if (signatureType == SignatureType.POSITIVE_CERTIFICATION || signatureType == SignatureType.GENERIC_CERTIFICATION) { int[] hashAlgos = signature.getHashedSubPackets().getPreferredHashAlgorithms(); @@ -71,8 +75,8 @@ public final class OpenPgpKeyAttributeUtil { continue; } - SignatureType signatureType = SignatureType.valueOf(signature.getSignatureType()); - if (signatureType != SignatureType.POSITIVE_CERTIFICATION + SignatureType signatureType = SignatureType.fromCode(signature.getSignatureType()); + if (signatureType == null || signatureType != SignatureType.POSITIVE_CERTIFICATION && signatureType != SignatureType.GENERIC_CERTIFICATION) { continue; } diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/algorithm/SignatureType.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/algorithm/SignatureType.kt index e6b2299f..be6917df 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/algorithm/SignatureType.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/algorithm/SignatureType.kt @@ -170,7 +170,8 @@ enum class SignatureType(val code: Int) { @JvmStatic fun isRevocationSignature(signatureType: Int): Boolean { - return isRevocationSignature(valueOf(signatureType)) + val sigType = fromCode(signatureType) + return sigType?.let { isRevocationSignature(it) } ?: false } @JvmStatic diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPSignatureExtensions.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPSignatureExtensions.kt index df40c461..1393883c 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPSignatureExtensions.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPSignatureExtensions.kt @@ -77,7 +77,8 @@ fun PGPSignature.wasIssuedBy(key: PGPPublicKey): Boolean = wasIssuedBy(OpenPgpFi /** Return true, if this signature is a hard revocation. */ val PGPSignature.isHardRevocation get() = - when (SignatureType.requireFromCode(signatureType)) { + when (SignatureType.fromCode(signatureType)) { + null -> false SignatureType.KEY_REVOCATION, SignatureType.SUBKEY_REVOCATION, SignatureType.CERTIFICATION_REVOCATION -> { @@ -104,4 +105,4 @@ val PGPSignature.signatureHashAlgorithm: HashAlgorithm get() = HashAlgorithm.requireFromId(hashAlgorithm) fun PGPSignature.isOfType(type: SignatureType): Boolean = - SignatureType.requireFromCode(signatureType) == type + SignatureType.fromCode(signatureType) == type diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/SignatureValidator.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/SignatureValidator.kt index e16ef158..951beb0f 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/SignatureValidator.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/SignatureValidator.kt @@ -235,7 +235,8 @@ abstract class SignatureValidator { signature: PGPSignature, policy: Policy ): Policy.HashAlgorithmPolicy { - return when (SignatureType.requireFromCode(signature.signatureType)) { + return when (SignatureType.fromCode(signature.signatureType)) { + null -> policy.certificationSignatureHashAlgorithmPolicy SignatureType.CERTIFICATION_REVOCATION, SignatureType.KEY_REVOCATION, SignatureType.SUBKEY_REVOCATION -> policy.revocationSignatureHashAlgorithmPolicy @@ -598,7 +599,8 @@ abstract class SignatureValidator { if (signatureType.none { signature.isOfType(it) }) { throw SignatureValidationException( "Signature is of type" + - " ${SignatureType.requireFromCode(signature.signatureType)}, " + + " ${SignatureType.fromCode(signature.signatureType) ?: + ("0x" + signature.signatureType.toString(16))}, " + "while only ${signatureType.contentToString()} are allowed here.") } } diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/SignatureVerifier.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/SignatureVerifier.kt index 77793c90..d51b2379 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/SignatureVerifier.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/SignatureVerifier.kt @@ -59,12 +59,13 @@ class SignatureVerifier { policy: Policy, referenceTime: Date ): Boolean { - val type = SignatureType.requireFromCode(signature.signatureType) + val type = SignatureType.fromCode(signature.signatureType) return when (type) { SignatureType.GENERIC_CERTIFICATION, SignatureType.NO_CERTIFICATION, SignatureType.CASUAL_CERTIFICATION, - SignatureType.POSITIVE_CERTIFICATION -> + SignatureType.POSITIVE_CERTIFICATION, + null -> verifyUserIdCertification( userId, signature, signingKey, keyWithUserId, policy, referenceTime) SignatureType.CERTIFICATION_REVOCATION -> diff --git a/pgpainless-core/src/test/java/org/pgpainless/algorithm/SignatureTypeTest.java b/pgpainless-core/src/test/java/org/pgpainless/algorithm/SignatureTypeTest.java index 1bf78776..7f2bc2a6 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/algorithm/SignatureTypeTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/algorithm/SignatureTypeTest.java @@ -5,7 +5,6 @@ package org.pgpainless.algorithm; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; @@ -31,6 +30,6 @@ public class SignatureTypeTest { assertFalse(SignatureType.isRevocationSignature(SignatureType.STANDALONE.getCode())); assertFalse(SignatureType.isRevocationSignature(SignatureType.TIMESTAMP.getCode())); - assertThrows(IllegalArgumentException.class, () -> SignatureType.isRevocationSignature(-3)); + assertFalse(SignatureType.isRevocationSignature(-3)); } }