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}