001// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
002//
003// SPDX-License-Identifier: Apache-2.0
004
005package org.pgpainless.decryption_verification;
006
007import javax.annotation.Nullable;
008
009import org.bouncycastle.openpgp.PGPSignature;
010import org.bouncycastle.util.encoders.Hex;
011import org.pgpainless.exception.SignatureValidationException;
012import org.pgpainless.key.SubkeyIdentifier;
013
014/**
015 * Tuple of a signature and an identifier of its corresponding verification key.
016 * Semantic meaning of the signature verification (success, failure) is merely given by context.
017 * E.g. {@link OpenPgpMetadata#getVerifiedInbandSignatures()} contains verified verifications,
018 * while the class {@link Failure} contains failed verifications.
019 */
020public class SignatureVerification {
021
022    private final PGPSignature signature;
023    private final SubkeyIdentifier signingKey;
024
025    /**
026     * Construct a verification tuple.
027     *
028     * @param signature PGPSignature object
029     * @param signingKey identifier of the signing key
030     */
031    public SignatureVerification(PGPSignature signature, @Nullable SubkeyIdentifier signingKey) {
032        this.signature = signature;
033        this.signingKey = signingKey;
034    }
035
036    /**
037     * Return the {@link PGPSignature}.
038     *
039     * @return signature
040     */
041    public PGPSignature getSignature() {
042        return signature;
043    }
044
045    /**
046     * Return a {@link SubkeyIdentifier} of the (sub-) key that is used for signature verification.
047     * Note, that this method might return null, e.g. in case of a {@link Failure} due to missing verification key.
048     *
049     * @return verification key identifier
050     */
051    @Nullable
052    public SubkeyIdentifier getSigningKey() {
053        return signingKey;
054    }
055
056    @Override
057    public String toString() {
058        return "Signature: " + (signature != null ? Hex.toHexString(signature.getDigestPrefix()) : "null")
059                + "; Key: " + (signingKey != null ? signingKey.toString() : "null") + ";";
060    }
061
062    /**
063     * Tuple object of a {@link SignatureVerification} and the corresponding {@link SignatureValidationException}
064     * that caused the verification to fail.
065     */
066    public static class Failure {
067
068        private final SignatureVerification signatureVerification;
069        private final SignatureValidationException validationException;
070
071        /**
072         * Construct a signature verification failure object.
073         *
074         * @param verification verification
075         * @param validationException exception that caused the verification to fail
076         */
077        public Failure(SignatureVerification verification, SignatureValidationException validationException) {
078            this.signatureVerification = verification;
079            this.validationException = validationException;
080        }
081
082        /**
083         * Return the verification (tuple of {@link PGPSignature} and corresponding {@link SubkeyIdentifier})
084         * of the signing/verification key.
085         *
086         * @return verification
087         */
088        public SignatureVerification getSignatureVerification() {
089            return signatureVerification;
090        }
091
092        /**
093         * Return the {@link SignatureValidationException} that caused the verification to fail.
094         *
095         * @return exception
096         */
097        public SignatureValidationException getValidationException() {
098            return validationException;
099        }
100
101        @Override
102        public String toString() {
103            return signatureVerification.toString() + " Failure: " + getValidationException().getMessage();
104        }
105    }
106}