From 19b45644ae73d74db487a4b65052ee3ed2526027 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 26 Oct 2023 12:52:04 +0200 Subject: [PATCH] Kotlin conversion: SignatureVerifier --- .../signature/consumer/SignatureVerifier.java | 486 -------------- .../signature/consumer/package-info.java | 8 - .../pgpainless/signature/consumer/README.md | 0 .../signature/consumer/SignatureVerifier.kt | 596 ++++++++++++++++++ 4 files changed, 596 insertions(+), 494 deletions(-) delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/signature/consumer/SignatureVerifier.java delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/signature/consumer/package-info.java rename pgpainless-core/src/main/{java => kotlin}/org/pgpainless/signature/consumer/README.md (100%) create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/SignatureVerifier.kt diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/consumer/SignatureVerifier.java b/pgpainless-core/src/main/java/org/pgpainless/signature/consumer/SignatureVerifier.java deleted file mode 100644 index a55037e5..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/consumer/SignatureVerifier.java +++ /dev/null @@ -1,486 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.signature.consumer; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Date; - -import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPPublicKey; -import org.bouncycastle.openpgp.PGPSignature; -import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVector; -import org.pgpainless.algorithm.SignatureType; -import org.pgpainless.exception.SignatureValidationException; -import org.pgpainless.implementation.ImplementationFactory; -import org.pgpainless.policy.Policy; - -/** - * Collection of static methods for signature verification. - * Signature verification entails validation of certain criteria (see {@link SignatureValidator}), as well as - * cryptographic verification of signature correctness. - */ -public final class SignatureVerifier { - - private SignatureVerifier() { - - } - - /** - * Verify a signature (certification or revocation) over a user-id. - * - * @param userId user-id - * @param signature certification signature - * @param signingKey key that created the certification - * @param keyWithUserId key carrying the user-id - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if signature verification is successful - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifySignatureOverUserId(String userId, PGPSignature signature, PGPPublicKey signingKey, - PGPPublicKey keyWithUserId, Policy policy, Date referenceDate) - throws SignatureValidationException { - SignatureType type = SignatureType.valueOf(signature.getSignatureType()); - switch (type) { - case GENERIC_CERTIFICATION: - case NO_CERTIFICATION: - case CASUAL_CERTIFICATION: - case POSITIVE_CERTIFICATION: - return verifyUserIdCertification(userId, signature, signingKey, keyWithUserId, policy, referenceDate); - case CERTIFICATION_REVOCATION: - return verifyUserIdRevocation(userId, signature, signingKey, keyWithUserId, policy, referenceDate); - default: - throw new SignatureValidationException("Signature is not a valid user-id certification/revocation signature: " + type); - } - } - - /** - * Verify a certification self-signature over a user-id. - * - * @param userId user-id - * @param signature certification signature - * @param primaryKey primary key - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if the self-signature is verified successfully - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyUserIdCertification(String userId, PGPSignature signature, PGPPublicKey primaryKey, - Policy policy, Date referenceDate) - throws SignatureValidationException { - return verifyUserIdCertification(userId, signature, primaryKey, primaryKey, policy, referenceDate); - } - - /** - * Verify a user-id certification. - * - * @param userId user-id - * @param signature certification signature - * @param signingKey key that created the certification - * @param keyWithUserId primary key that carries the user-id - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if signature verification is successful - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyUserIdCertification(String userId, PGPSignature signature, PGPPublicKey signingKey, - PGPPublicKey keyWithUserId, Policy policy, Date referenceDate) - throws SignatureValidationException { - SignatureValidator.wasPossiblyMadeByKey(signingKey).verify(signature); - SignatureValidator.signatureIsCertification().verify(signature); - SignatureValidator.signatureStructureIsAcceptable(signingKey, policy).verify(signature); - SignatureValidator.signatureIsEffective(referenceDate).verify(signature); - SignatureValidator.correctSignatureOverUserId(userId, keyWithUserId, signingKey).verify(signature); - - return true; - } - - /** - * Verify a user-id revocation self-signature. - * - * @param userId user-id - * @param signature user-id revocation signature - * @param primaryKey primary key - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if the user-id revocation signature is successfully verified - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyUserIdRevocation(String userId, PGPSignature signature, PGPPublicKey primaryKey, - Policy policy, Date referenceDate) - throws SignatureValidationException { - return verifyUserIdRevocation(userId, signature, primaryKey, primaryKey, policy, referenceDate); - } - - /** - * Verify a user-id revocation signature. - * - * @param userId user-id - * @param signature revocation signature - * @param signingKey key that created the revocation signature - * @param keyWithUserId primary key carrying the user-id - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if the user-id revocation signature is successfully verified - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyUserIdRevocation(String userId, PGPSignature signature, PGPPublicKey signingKey, - PGPPublicKey keyWithUserId, Policy policy, Date referenceDate) - throws SignatureValidationException { - SignatureValidator.wasPossiblyMadeByKey(signingKey).verify(signature); - SignatureValidator.signatureIsOfType(SignatureType.CERTIFICATION_REVOCATION).verify(signature); - SignatureValidator.signatureStructureIsAcceptable(signingKey, policy).verify(signature); - SignatureValidator.signatureIsEffective(referenceDate).verify(signature); - SignatureValidator.correctSignatureOverUserId(userId, keyWithUserId, signingKey).verify(signature); - - return true; - } - - /** - * Verify a certification self-signature over a user-attributes packet. - * - * @param userAttributes user attributes - * @param signature certification self-signature - * @param primaryKey primary key that carries the user-attributes - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if the signature can be verified successfully - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyUserAttributesCertification(PGPUserAttributeSubpacketVector userAttributes, - PGPSignature signature, PGPPublicKey primaryKey, - Policy policy, Date referenceDate) - throws SignatureValidationException { - return verifyUserAttributesCertification(userAttributes, signature, primaryKey, primaryKey, policy, - referenceDate); - } - - /** - * Verify a certification signature over a user-attributes packet. - * - * @param userAttributes user attributes - * @param signature certification signature - * @param signingKey key that created the user-attributes certification - * @param keyWithUserAttributes key that carries the user-attributes certification - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if the signature can be verified successfully - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyUserAttributesCertification(PGPUserAttributeSubpacketVector userAttributes, - PGPSignature signature, PGPPublicKey signingKey, - PGPPublicKey keyWithUserAttributes, Policy policy, - Date referenceDate) - throws SignatureValidationException { - SignatureValidator.wasPossiblyMadeByKey(signingKey).verify(signature); - SignatureValidator.signatureIsCertification().verify(signature); - SignatureValidator.signatureStructureIsAcceptable(signingKey, policy).verify(signature); - SignatureValidator.signatureIsEffective(referenceDate).verify(signature); - SignatureValidator.correctSignatureOverUserAttributes(userAttributes, keyWithUserAttributes, signingKey) - .verify(signature); - - return true; - } - - /** - * Verify a user-attributes revocation self-signature. - * - * @param userAttributes user-attributes - * @param signature user-attributes revocation signature - * @param primaryKey primary key that carries the user-attributes - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if the revocation signature can be verified successfully - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyUserAttributesRevocation(PGPUserAttributeSubpacketVector userAttributes, - PGPSignature signature, PGPPublicKey primaryKey, - Policy policy, Date referenceDate) - throws SignatureValidationException { - return verifyUserAttributesRevocation(userAttributes, signature, primaryKey, primaryKey, policy, referenceDate); - } - - /** - * Verify a user-attributes revocation signature. - * - * @param userAttributes user-attributes - * @param signature revocation signature - * @param signingKey revocation key - * @param keyWithUserAttributes key that carries the user-attributes - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if the revocation signature can be verified successfully - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyUserAttributesRevocation(PGPUserAttributeSubpacketVector userAttributes, - PGPSignature signature, PGPPublicKey signingKey, - PGPPublicKey keyWithUserAttributes, Policy policy, - Date referenceDate) - throws SignatureValidationException { - SignatureValidator.wasPossiblyMadeByKey(signingKey).verify(signature); - SignatureValidator.signatureIsOfType(SignatureType.CERTIFICATION_REVOCATION).verify(signature); - SignatureValidator.signatureStructureIsAcceptable(signingKey, policy).verify(signature); - SignatureValidator.signatureIsEffective(referenceDate).verify(signature); - SignatureValidator.correctSignatureOverUserAttributes(userAttributes, keyWithUserAttributes, signingKey) - .verify(signature); - - return true; - } - - /** - * Verify a subkey binding signature. - * - * @param signature binding signature - * @param primaryKey primary key - * @param subkey subkey - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if the binding signature can be verified successfully - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifySubkeyBindingSignature(PGPSignature signature, PGPPublicKey primaryKey, - PGPPublicKey subkey, Policy policy, Date referenceDate) - throws SignatureValidationException { - SignatureValidator.signatureIsOfType(SignatureType.SUBKEY_BINDING).verify(signature); - SignatureValidator.signatureStructureIsAcceptable(primaryKey, policy).verify(signature); - SignatureValidator.signatureDoesNotPredateSignee(subkey).verify(signature); - SignatureValidator.signatureIsEffective(referenceDate).verify(signature); - SignatureValidator.hasValidPrimaryKeyBindingSignatureIfRequired(primaryKey, subkey, policy, referenceDate) - .verify(signature); - SignatureValidator.correctSubkeyBindingSignature(primaryKey, subkey).verify(signature); - - return true; - } - - /** - * Verify a subkey revocation signature. - * - * @param signature subkey revocation signature - * @param primaryKey primary key - * @param subkey subkey - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if the subkey revocation signature can be verified successfully - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifySubkeyBindingRevocation(PGPSignature signature, PGPPublicKey primaryKey, - PGPPublicKey subkey, Policy policy, Date referenceDate) - throws SignatureValidationException { - SignatureValidator.signatureIsOfType(SignatureType.SUBKEY_REVOCATION).verify(signature); - SignatureValidator.signatureStructureIsAcceptable(primaryKey, policy).verify(signature); - SignatureValidator.signatureDoesNotPredateSignee(subkey).verify(signature); - SignatureValidator.signatureIsEffective(referenceDate).verify(signature); - SignatureValidator.correctSignatureOverKey(primaryKey, subkey).verify(signature); - - return true; - } - - /** - * Verify a direct-key self-signature. - * - * @param signature signature - * @param primaryKey primary key - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if the signature can be verified successfully - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyDirectKeySignature(PGPSignature signature, PGPPublicKey primaryKey, - Policy policy, Date referenceDate) - throws SignatureValidationException { - return verifyDirectKeySignature(signature, primaryKey, primaryKey, policy, referenceDate); - } - - /** - * Verify a direct-key signature. - * - * @param signature signature - * @param signingKey signing key - * @param signedKey signed key - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if signature verification is successful - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyDirectKeySignature(PGPSignature signature, PGPPublicKey signingKey, - PGPPublicKey signedKey, Policy policy, Date referenceDate) - throws SignatureValidationException { - SignatureValidator.signatureIsOfType(SignatureType.DIRECT_KEY).verify(signature); - SignatureValidator.signatureStructureIsAcceptable(signingKey, policy).verify(signature); - SignatureValidator.signatureDoesNotPredateSignee(signedKey).verify(signature); - SignatureValidator.signatureIsEffective(referenceDate).verify(signature); - SignatureValidator.correctSignatureOverKey(signingKey, signedKey).verify(signature); - - return true; - } - - /** - * Verify a key revocation signature. - * - * @param signature signature - * @param primaryKey primary key - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if signature verification is successful - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyKeyRevocationSignature(PGPSignature signature, PGPPublicKey primaryKey, - Policy policy, Date referenceDate) - throws SignatureValidationException { - SignatureValidator.signatureIsOfType(SignatureType.KEY_REVOCATION).verify(signature); - SignatureValidator.signatureStructureIsAcceptable(primaryKey, policy).verify(signature); - SignatureValidator.signatureIsEffective(referenceDate).verify(signature); - SignatureValidator.correctSignatureOverKey(primaryKey, primaryKey).verify(signature); - - return true; - } - - /** - * Initialize a signature and verify it afterwards by updating it with the signed data. - * - * @param signature OpenPGP signature - * @param signedData input stream containing the signed data - * @param signingKey the key that created the signature - * @param policy policy - * @param referenceDate reference date of signature verification - * @return true if the signature is successfully verified - * - * @throws SignatureValidationException if the signature verification fails for some reason - */ - public static boolean verifyUninitializedSignature(PGPSignature signature, InputStream signedData, - PGPPublicKey signingKey, Policy policy, Date referenceDate) - throws SignatureValidationException { - initializeSignatureAndUpdateWithSignedData(signature, signedData, signingKey); - return verifyInitializedSignature(signature, signingKey, policy, referenceDate); - } - - /** - * Initialize a signature and then update it with the signed data from the given {@link InputStream}. - * - * @param signature OpenPGP signature - * @param signedData input stream containing signed data - * @param signingKey key that created the signature - * - * @throws SignatureValidationException in case the signature cannot be verified for some reason - */ - public static void initializeSignatureAndUpdateWithSignedData(PGPSignature signature, InputStream signedData, - PGPPublicKey signingKey) - throws SignatureValidationException { - try { - signature.init(ImplementationFactory.getInstance().getPgpContentVerifierBuilderProvider(), signingKey); - int read; - byte[] buf = new byte[8192]; - byte lastByte = -1; - while ((read = signedData.read(buf)) != -1) { - // If we previously omitted a newline, but the stream is not yet empty, add it now - if (lastByte == (byte) '\n') { - signature.update(lastByte); - } - lastByte = buf[read - 1]; - - if (lastByte == (byte) '\n') { - // if last byte in buffer is newline, omit it for now - signature.update(buf, 0, read - 1); - } else { - // otherwise, write buffer as usual - signature.update(buf, 0, read); - } - } - } catch (PGPException e) { - throw new SignatureValidationException("Cannot init signature.", e); - } catch (IOException e) { - throw new SignatureValidationException("Cannot update signature.", e); - } - } - - /** - * Verify an initialized signature. - * An initialized signature was already updated with the signed data. - * - * @param signature OpenPGP signature - * @param signingKey key that created the signature - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if signature is verified successfully - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifyInitializedSignature(PGPSignature signature, PGPPublicKey signingKey, Policy policy, - Date referenceDate) - throws SignatureValidationException { - SignatureValidator.wasPossiblyMadeByKey(signingKey).verify(signature); - SignatureValidator.signatureStructureIsAcceptable(signingKey, policy).verify(signature); - SignatureValidator.signatureIsEffective(referenceDate).verify(signature); - - try { - if (!signature.verify()) { - throw new SignatureValidationException("Signature is not correct."); - } - return true; - } catch (PGPException e) { - throw new SignatureValidationException("Could not verify signature correctness.", e); - } - } - - public static boolean verifyOnePassSignature(PGPSignature signature, PGPPublicKey signingKey, - OnePassSignatureCheck onePassSignature, Policy policy) - throws SignatureValidationException { - try { - SignatureValidator.wasPossiblyMadeByKey(signingKey).verify(signature); - SignatureValidator.signatureStructureIsAcceptable(signingKey, policy).verify(signature); - SignatureValidator.signatureIsEffective().verify(signature); - } catch (SignatureValidationException e) { - throw new SignatureValidationException("Signature is not valid: " + e.getMessage(), e); - } - - try { - if (onePassSignature.getSignature() == null) { - throw new IllegalStateException("No comparison signature provided."); - } - if (!onePassSignature.getOnePassSignature().verify(signature)) { - throw new SignatureValidationException("Bad signature of key " + - Long.toHexString(signingKey.getKeyID())); - } - } catch (PGPException e) { - throw new SignatureValidationException("Could not verify correctness of One-Pass-Signature: " + - e.getMessage(), e); - } - - return true; - } - - /** - * Verify a signature (certification or revocation) over a user-id. - * - * @param userId user-id - * @param signature self-signature - * @param primaryKey primary key that created the signature - * @param policy policy - * @param referenceDate reference date for signature verification - * @return true if the signature is successfully verified - * - * @throws SignatureValidationException if signature verification fails for some reason - */ - public static boolean verifySignatureOverUserId(String userId, PGPSignature signature, PGPPublicKey primaryKey, - Policy policy, Date referenceDate) - throws SignatureValidationException { - return verifySignatureOverUserId(userId, signature, primaryKey, primaryKey, policy, referenceDate); - } -} diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/consumer/package-info.java b/pgpainless-core/src/main/java/org/pgpainless/signature/consumer/package-info.java deleted file mode 100644 index e8e53285..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/consumer/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -/** - * Classes related to OpenPGP signature verification. - */ -package org.pgpainless.signature.consumer; diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/consumer/README.md b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/README.md similarity index 100% rename from pgpainless-core/src/main/java/org/pgpainless/signature/consumer/README.md rename to pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/README.md 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 new file mode 100644 index 00000000..77793c90 --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/SignatureVerifier.kt @@ -0,0 +1,596 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.signature.consumer + +import java.io.IOException +import java.io.InputStream +import java.util.* +import openpgp.openPgpKeyId +import org.bouncycastle.openpgp.PGPException +import org.bouncycastle.openpgp.PGPPublicKey +import org.bouncycastle.openpgp.PGPSignature +import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVector +import org.pgpainless.algorithm.SignatureType +import org.pgpainless.exception.SignatureValidationException +import org.pgpainless.implementation.ImplementationFactory.Companion.getInstance +import org.pgpainless.policy.Policy +import org.pgpainless.signature.consumer.SignatureValidator.Companion.correctSignatureOverKey +import org.pgpainless.signature.consumer.SignatureValidator.Companion.correctSignatureOverUserAttributes +import org.pgpainless.signature.consumer.SignatureValidator.Companion.correctSignatureOverUserId +import org.pgpainless.signature.consumer.SignatureValidator.Companion.correctSubkeyBindingSignature +import org.pgpainless.signature.consumer.SignatureValidator.Companion.hasValidPrimaryKeyBindingSignatureIfRequired +import org.pgpainless.signature.consumer.SignatureValidator.Companion.signatureDoesNotPredateSignee +import org.pgpainless.signature.consumer.SignatureValidator.Companion.signatureIsCertification +import org.pgpainless.signature.consumer.SignatureValidator.Companion.signatureIsEffective +import org.pgpainless.signature.consumer.SignatureValidator.Companion.signatureIsOfType +import org.pgpainless.signature.consumer.SignatureValidator.Companion.signatureStructureIsAcceptable +import org.pgpainless.signature.consumer.SignatureValidator.Companion.wasPossiblyMadeByKey + +/** + * Collection of static methods for signature verification. Signature verification entails + * validation of certain criteria (see [SignatureValidator]), as well as cryptographic verification + * of signature correctness. + */ +class SignatureVerifier { + + companion object { + + /** + * Verify a signature (certification or revocation) over a user-id. + * + * @param userId user-id + * @param signature certification signature + * @param signingKey key that created the certification + * @param keyWithUserId key carrying the user-id + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if signature verification is successful + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifySignatureOverUserId( + userId: CharSequence, + signature: PGPSignature, + signingKey: PGPPublicKey, + keyWithUserId: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + val type = SignatureType.requireFromCode(signature.signatureType) + return when (type) { + SignatureType.GENERIC_CERTIFICATION, + SignatureType.NO_CERTIFICATION, + SignatureType.CASUAL_CERTIFICATION, + SignatureType.POSITIVE_CERTIFICATION -> + verifyUserIdCertification( + userId, signature, signingKey, keyWithUserId, policy, referenceTime) + SignatureType.CERTIFICATION_REVOCATION -> + verifyUserIdRevocation( + userId, signature, signingKey, keyWithUserId, policy, referenceTime) + else -> + throw SignatureValidationException( + "Signature is not a valid user-id certification/revocation signature: $type") + } + } + + /** + * Verify a certification self-signature over a user-id. + * + * @param userId user-id + * @param signature certification signature + * @param primaryKey primary key + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if the self-signature is verified successfully + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyUserIdCertification( + userId: CharSequence, + signature: PGPSignature, + primaryKey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + return verifyUserIdCertification( + userId, signature, primaryKey, primaryKey, policy, referenceTime) + } + + /** + * Verify a user-id certification. + * + * @param userId user-id + * @param signature certification signature + * @param signingKey key that created the certification + * @param keyWithUserId primary key that carries the user-id + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if signature verification is successful + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyUserIdCertification( + userId: CharSequence, + signature: PGPSignature, + signingKey: PGPPublicKey, + keyWithUserId: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + wasPossiblyMadeByKey(signingKey).verify(signature) + signatureIsCertification().verify(signature) + signatureStructureIsAcceptable(signingKey, policy).verify(signature) + signatureIsEffective(referenceTime).verify(signature) + correctSignatureOverUserId(userId, keyWithUserId, signingKey).verify(signature) + + return true + } + + /** + * Verify a user-id revocation self-signature. + * + * @param userId user-id + * @param signature user-id revocation signature + * @param primaryKey primary key + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if the user-id revocation signature is successfully verified + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyUserIdRevocation( + userId: CharSequence, + signature: PGPSignature, + primaryKey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + return verifyUserIdRevocation( + userId, signature, primaryKey, primaryKey, policy, referenceTime) + } + + /** + * Verify a user-id revocation signature. + * + * @param userId user-id + * @param signature revocation signature + * @param signingKey key that created the revocation signature + * @param keyWithUserId primary key carrying the user-id + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if the user-id revocation signature is successfully verified + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyUserIdRevocation( + userId: CharSequence, + signature: PGPSignature, + signingKey: PGPPublicKey, + keyWithUserId: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + wasPossiblyMadeByKey(signingKey).verify(signature) + signatureIsOfType(SignatureType.CERTIFICATION_REVOCATION).verify(signature) + signatureStructureIsAcceptable(signingKey, policy).verify(signature) + signatureIsEffective(referenceTime).verify(signature) + correctSignatureOverUserId(userId, keyWithUserId, signingKey).verify(signature) + + return true + } + + /** + * Verify a certification self-signature over a user-attributes packet. + * + * @param userAttributes user attributes + * @param signature certification self-signature + * @param primaryKey primary key that carries the user-attributes + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if the signature can be verified successfully + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyUserAttributesCertification( + userAttributes: PGPUserAttributeSubpacketVector, + signature: PGPSignature, + primaryKey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + return verifyUserAttributesCertification( + userAttributes, signature, primaryKey, primaryKey, policy, referenceTime) + } + + /** + * Verify a certification signature over a user-attributes packet. + * + * @param userAttributes user attributes + * @param signature certification signature + * @param signingKey key that created the user-attributes certification + * @param keyWithAttributes key that carries the user-attributes certification + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if the signature can be verified successfully + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyUserAttributesCertification( + userAttributes: PGPUserAttributeSubpacketVector, + signature: PGPSignature, + signingKey: PGPPublicKey, + keyWithAttributes: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + wasPossiblyMadeByKey(signingKey).verify(signature) + signatureIsCertification().verify(signature) + signatureStructureIsAcceptable(signingKey, policy).verify(signature) + signatureIsEffective(referenceTime).verify(signature) + correctSignatureOverUserAttributes(userAttributes, keyWithAttributes, signingKey) + .verify(signature) + + return true + } + + /** + * Verify a user-attributes revocation self-signature. + * + * @param userAttributes user-attributes + * @param signature user-attributes revocation signature + * @param primaryKey primary key that carries the user-attributes + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if the revocation signature can be verified successfully + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyUserAttributesRevocation( + userAttributes: PGPUserAttributeSubpacketVector, + signature: PGPSignature, + primaryKey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + return verifyUserAttributesRevocation( + userAttributes, signature, primaryKey, primaryKey, policy, referenceTime) + } + + /** + * Verify a user-attributes revocation signature. + * + * @param userAttributes user-attributes + * @param signature revocation signature + * @param signingKey revocation key + * @param keyWithAttributes key that carries the user-attributes + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if the revocation signature can be verified successfully + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyUserAttributesRevocation( + userAttributes: PGPUserAttributeSubpacketVector, + signature: PGPSignature, + signingKey: PGPPublicKey, + keyWithAttributes: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + wasPossiblyMadeByKey(signingKey).verify(signature) + signatureIsOfType(SignatureType.CERTIFICATION_REVOCATION).verify(signature) + signatureStructureIsAcceptable(signingKey, policy).verify(signature) + signatureIsEffective(referenceTime).verify(signature) + correctSignatureOverUserAttributes(userAttributes, keyWithAttributes, signingKey) + .verify(signature) + + return true + } + + /** + * Verify a subkey binding signature. + * + * @param signature binding signature + * @param primaryKey primary key + * @param subkey subkey + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if the binding signature can be verified successfully + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifySubkeyBindingSignature( + signature: PGPSignature, + primaryKey: PGPPublicKey, + subkey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + signatureIsOfType(SignatureType.SUBKEY_BINDING).verify(signature) + signatureStructureIsAcceptable(primaryKey, policy).verify(signature) + signatureDoesNotPredateSignee(subkey).verify(signature) + signatureIsEffective(referenceTime).verify(signature) + hasValidPrimaryKeyBindingSignatureIfRequired(primaryKey, subkey, policy, referenceTime) + .verify(signature) + correctSubkeyBindingSignature(primaryKey, subkey).verify(signature) + + return true + } + + /** + * Verify a subkey revocation signature. + * + * @param signature subkey revocation signature + * @param primaryKey primary key + * @param subkey subkey + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if the subkey revocation signature can be verified successfully + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifySubkeyBindingRevocation( + signature: PGPSignature, + primaryKey: PGPPublicKey, + subkey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + signatureIsOfType(SignatureType.SUBKEY_REVOCATION).verify(signature) + signatureStructureIsAcceptable(primaryKey, policy).verify(signature) + signatureDoesNotPredateSignee(subkey).verify(signature) + signatureIsEffective(referenceTime).verify(signature) + correctSignatureOverKey(primaryKey, subkey).verify(signature) + + return true + } + + /** + * Verify a direct-key self-signature. + * + * @param signature signature + * @param primaryKey primary key + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if the signature can be verified successfully + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyDirectKeySignature( + signature: PGPSignature, + primaryKey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + return verifyDirectKeySignature( + signature, primaryKey, primaryKey, policy, referenceTime) + } + + /** + * Verify a direct-key signature. + * + * @param signature signature + * @param signingKey signing key + * @param signedKey signed key + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if signature verification is successful + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyDirectKeySignature( + signature: PGPSignature, + signingKey: PGPPublicKey, + signedKey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + signatureIsOfType(SignatureType.DIRECT_KEY).verify(signature) + signatureStructureIsAcceptable(signingKey, policy).verify(signature) + signatureDoesNotPredateSignee(signedKey).verify(signature) + signatureIsEffective(referenceTime).verify(signature) + correctSignatureOverKey(signingKey, signedKey).verify(signature) + + return true + } + + /** + * Verify a key revocation signature. + * + * @param signature signature + * @param primaryKey primary key + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if signature verification is successful + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyKeyRevocationSignature( + signature: PGPSignature, + primaryKey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + signatureIsOfType(SignatureType.KEY_REVOCATION).verify(signature) + signatureStructureIsAcceptable(primaryKey, policy).verify(signature) + signatureIsEffective(referenceTime).verify(signature) + correctSignatureOverKey(primaryKey, primaryKey).verify(signature) + + return true + } + + /** + * Initialize a signature and verify it afterwards by updating it with the signed data. + * + * @param signature OpenPGP signature + * @param signedData input stream containing the signed data + * @param signingKey the key that created the signature + * @param policy policy + * @param referenceTime reference date of signature verification + * @return true if the signature is successfully verified + * @throws SignatureValidationException if the signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyUninitializedSignature( + signature: PGPSignature, + signedData: InputStream, + signingKey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + initializeSignatureAndUpdateWithSignedData(signature, signedData, signingKey) + return verifyInitializedSignature(signature, signingKey, policy, referenceTime) + } + + /** + * Initialize a signature and then update it with the signed data from the given + * [InputStream]. + * + * @param signature OpenPGP signature + * @param signedData input stream containing signed data + * @param signingKey key that created the signature + * @throws SignatureValidationException in case the signature cannot be verified for some + * reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun initializeSignatureAndUpdateWithSignedData( + signature: PGPSignature, + signedData: InputStream, + signingKey: PGPPublicKey + ) { + try { + signature.init( + getInstance().pgpContentVerifierBuilderProvider, + signingKey, + ) + var read: Int + val buf = ByteArray(8192) + var lastByte: Byte = -1 + while (signedData.read(buf).also { read = it } != -1) { + // If we previously omitted a newline, but the stream is not yet empty, add it + // now + if (lastByte == '\n'.code.toByte()) { + signature.update(lastByte) + } + lastByte = buf[read - 1] + if (lastByte == '\n'.code.toByte()) { + // if last byte in buffer is newline, omit it for now + signature.update(buf, 0, read - 1) + } else { + // otherwise, write buffer as usual + signature.update(buf, 0, read) + } + } + } catch (e: PGPException) { + throw SignatureValidationException("Cannot init signature.", e) + } catch (e: IOException) { + throw SignatureValidationException("Cannot update signature.", e) + } + } + + /** + * Verify an initialized signature. An initialized signature was already updated with the + * signed data. + * + * @param signature OpenPGP signature + * @param signingKey key that created the signature + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if signature is verified successfully + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyInitializedSignature( + signature: PGPSignature, + signingKey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + wasPossiblyMadeByKey(signingKey).verify(signature) + signatureStructureIsAcceptable(signingKey, policy).verify(signature) + signatureIsEffective(referenceTime).verify(signature) + + return try { + if (!signature.verify()) { + throw SignatureValidationException("Signature is not correct.") + } + true + } catch (e: PGPException) { + throw SignatureValidationException("Could not verify signature correctness.", e) + } + } + + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifyOnePassSignature( + signature: PGPSignature, + signingKey: PGPPublicKey, + onePassSignature: OnePassSignatureCheck, + policy: Policy + ): Boolean { + try { + wasPossiblyMadeByKey(signingKey).verify(signature) + signatureStructureIsAcceptable(signingKey, policy).verify(signature) + signatureIsEffective().verify(signature) + } catch (e: SignatureValidationException) { + throw SignatureValidationException("Signature is not valid: ${e.message}", e) + } + + try { + checkNotNull(onePassSignature.signature) { "No comparison signature provided." } + if (!onePassSignature.onePassSignature.verify(signature)) { + throw SignatureValidationException( + "Bad signature of key ${signingKey.keyID.openPgpKeyId()}") + } + } catch (e: PGPException) { + throw SignatureValidationException( + "Could not verify correctness of One-Pass-Signature: ${e.message}", e) + } + + return true + } + + /** + * Verify a signature (certification or revocation) over a user-id. + * + * @param userId user-id + * @param signature self-signature + * @param primaryKey primary key that created the signature + * @param policy policy + * @param referenceTime reference date for signature verification + * @return true if the signature is successfully verified + * @throws SignatureValidationException if signature verification fails for some reason + */ + @JvmStatic + @Throws(SignatureValidationException::class) + fun verifySignatureOverUserId( + userId: CharSequence, + signature: PGPSignature, + primaryKey: PGPPublicKey, + policy: Policy, + referenceTime: Date + ): Boolean { + return verifySignatureOverUserId( + userId, signature, primaryKey, primaryKey, policy, referenceTime) + } + } +}