001// SPDX-FileCopyrightText: 2020 Paul Schaub <vanitasvitae@fsfe.org>
002//
003// SPDX-License-Identifier: Apache-2.0
004
005package org.pgpainless.algorithm;
006
007import org.bouncycastle.openpgp.PGPSignature;
008
009import java.util.Map;
010import java.util.concurrent.ConcurrentHashMap;
011
012/**
013 * Enum that enlists all the Signature Types defined in rfc4880 section 5.2.1
014 * See {@link org.bouncycastle.openpgp.PGPSignature} for comparison.
015 *
016 * @see <a href="https://tools.ietf.org/html/rfc4880#section-5.11">rfc4880 ยง5.2.1. Signature Types</a>
017 */
018public enum SignatureType {
019
020    /**
021     * Signature of a binary document.
022     * This means the signer owns it, created it, or certifies that it
023     * has not been modified.
024     */
025    BINARY_DOCUMENT(PGPSignature.BINARY_DOCUMENT),
026
027    /**
028     * Signature of a canonical text document.
029     * This means the signer owns it, created it, or certifies that it
030     * has not been modified.  The signature is calculated over the text
031     * data with its line endings converted to {@code <CR><LF>}.
032     */
033    CANONICAL_TEXT_DOCUMENT(PGPSignature.CANONICAL_TEXT_DOCUMENT),
034
035    /**
036     * Standalone signature.
037     * This signature is a signature of only its own subpacket contents.
038     * It is calculated identically to a signature over a zero-length
039     * binary document.  Note that it doesn't make sense to have a V3
040     * standalone signature.
041     */
042    STANDALONE(PGPSignature.STAND_ALONE),
043
044    /**
045     * Generic certification of a User ID and Public-Key packet.
046     * The issuer of this certification does not make any particular
047     * assertion as to how well the certifier has checked that the owner
048     * of the key is in fact the person described by the User ID.
049     */
050    GENERIC_CERTIFICATION(PGPSignature.DEFAULT_CERTIFICATION),
051
052    /**
053     * Persona certification of a User ID and Public-Key packet.
054     * The issuer of this certification has not done any verification of
055     * the claim that the owner of this key is the User ID specified.
056     */
057    NO_CERTIFICATION(PGPSignature.NO_CERTIFICATION),
058
059    /**
060     * Casual certification of a User ID and Public-Key packet.
061     * The issuer of this certification has done some casual
062     * verification of the claim of identity.
063     */
064    CASUAL_CERTIFICATION(PGPSignature.CASUAL_CERTIFICATION),
065
066    /**
067     * Positive certification of a User ID and Public-Key packet.
068     * The issuer of this certification has done substantial
069     * verification of the claim of identity.
070     */
071    POSITIVE_CERTIFICATION(PGPSignature.POSITIVE_CERTIFICATION),
072
073    /**
074     * Subkey Binding Signature.
075     * This signature is a statement by the top-level signing key that
076     * indicates that it owns the subkey.  This signature is calculated
077     * directly on the primary key and subkey, and not on any User ID or
078     * other packets.  A signature that binds a signing subkey MUST have
079     * an Embedded Signature subpacket in this binding signature that
080     * contains a {@link #PRIMARYKEY_BINDING} signature made by the
081     * signing subkey on the primary key and subkey.
082     */
083    SUBKEY_BINDING(PGPSignature.SUBKEY_BINDING),
084
085    /**
086     * Primary Key Binding Signature
087     * This signature is a statement by a signing subkey, indicating
088     * that it is owned by the primary key and subkey.  This signature
089     * is calculated the same way as a {@link #SUBKEY_BINDING} signature:
090     * directly on the primary key and subkey, and not on any User ID or
091     * other packets.
092     */
093    PRIMARYKEY_BINDING(PGPSignature.PRIMARYKEY_BINDING),
094
095    /**
096     * Signature directly on a key
097     * This signature is calculated directly on a key.  It binds the
098     * information in the Signature subpackets to the key, and is
099     * appropriate to be used for subpackets that provide information
100     * about the key, such as the Revocation Key subpacket.  It is also
101     * appropriate for statements that non-self certifiers want to make
102     * about the key itself, rather than the binding between a key and a
103     * name.
104     */
105    DIRECT_KEY(PGPSignature.DIRECT_KEY),
106
107    /**
108     * Key revocation signature
109     * The signature is calculated directly on the key being revoked.  A
110     * revoked key is not to be used.  Only revocation signatures by the
111     * key being revoked, or by an authorized revocation key, should be
112     * considered valid revocation signatures.
113     */
114    KEY_REVOCATION(PGPSignature.KEY_REVOCATION),
115
116    /**
117     * Subkey revocation signature
118     * The signature is calculated directly on the subkey being revoked.
119     * A revoked subkey is not to be used.  Only revocation signatures
120     * by the top-level signature key that is bound to this subkey, or
121     * by an authorized revocation key, should be considered valid
122     * revocation signatures.
123     */
124    SUBKEY_REVOCATION(PGPSignature.SUBKEY_REVOCATION),
125
126    /**
127     * Certification revocation signature
128     * This signature revokes an earlier User ID certification signature
129     * (signature class 0x10 through 0x13) or signature {@link #DIRECT_KEY}.
130     * It should be issued by the same key that issued the
131     * revoked signature or an authorized revocation key.  The signature
132     * is computed over the same data as the certificate that it
133     * revokes, and should have a later creation date than that
134     * certificate.
135     */
136    CERTIFICATION_REVOCATION(PGPSignature.CERTIFICATION_REVOCATION),
137
138    /**
139     * Timestamp signature.
140     * This signature is only meaningful for the timestamp contained in
141     * it.
142     */
143    TIMESTAMP(PGPSignature.TIMESTAMP),
144
145    /**
146     * Third-Party Confirmation signature.
147     * This signature is a signature over some other OpenPGP Signature
148     * packet(s).  It is analogous to a notary seal on the signed data.
149     * A third-party signature SHOULD include Signature Target
150     * subpacket(s) to give easy identification.  Note that we really do
151     * mean SHOULD.  There are plausible uses for this (such as a blind
152     * party that only sees the signature, not the key or source
153     * document) that cannot include a target subpacket.
154     */
155    THIRD_PARTY_CONFIRMATION(0x50)
156    ;
157
158    private static final Map<Integer, SignatureType> map = new ConcurrentHashMap<>();
159    static {
160        for (SignatureType sigType : SignatureType.values()) {
161            map.put(sigType.getCode(), sigType);
162        }
163    }
164
165    /**
166     * Convert a numerical id into a {@link SignatureType}.
167     *
168     * @param code numeric id
169     * @return signature type enum
170     */
171    public static SignatureType valueOf(int code) {
172        SignatureType type = map.get(code);
173        if (type != null) {
174            return type;
175        }
176        throw new IllegalArgumentException("Signature type 0x" + Integer.toHexString(code) + " appears to be invalid.");
177    }
178
179    private final int code;
180
181    SignatureType(int code) {
182        this.code = code;
183    }
184
185    /**
186     * Return the numeric id of the signature type enum.
187     *
188     * @return numeric id
189     */
190    public int getCode() {
191        return code;
192    }
193
194    public static boolean isRevocationSignature(int signatureType) {
195        return isRevocationSignature(SignatureType.valueOf(signatureType));
196    }
197
198    public static boolean isRevocationSignature(SignatureType signatureType) {
199        switch (signatureType) {
200            case BINARY_DOCUMENT:
201            case CANONICAL_TEXT_DOCUMENT:
202            case STANDALONE:
203            case GENERIC_CERTIFICATION:
204            case NO_CERTIFICATION:
205            case CASUAL_CERTIFICATION:
206            case POSITIVE_CERTIFICATION:
207            case SUBKEY_BINDING:
208            case PRIMARYKEY_BINDING:
209            case DIRECT_KEY:
210            case TIMESTAMP:
211            case THIRD_PARTY_CONFIRMATION:
212                return false;
213            case KEY_REVOCATION:
214            case SUBKEY_REVOCATION:
215            case CERTIFICATION_REVOCATION:
216                return true;
217            default:
218                throw new IllegalArgumentException("Unknown signature type: " + signatureType);
219        }
220    }
221
222}