001// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org> 002// 003// SPDX-License-Identifier: Apache-2.0 004 005package org.pgpainless.signature.subpackets; 006 007import org.bouncycastle.bcpg.SignatureSubpacket; 008import org.bouncycastle.bcpg.sig.EmbeddedSignature; 009import org.bouncycastle.bcpg.sig.Exportable; 010import org.bouncycastle.bcpg.sig.Features; 011import org.bouncycastle.bcpg.sig.IntendedRecipientFingerprint; 012import org.bouncycastle.bcpg.sig.KeyExpirationTime; 013import org.bouncycastle.bcpg.sig.KeyFlags; 014import org.bouncycastle.bcpg.sig.NotationData; 015import org.bouncycastle.bcpg.sig.PreferredAlgorithms; 016import org.bouncycastle.bcpg.sig.PrimaryUserID; 017import org.bouncycastle.bcpg.sig.Revocable; 018import org.bouncycastle.bcpg.sig.RevocationKey; 019import org.bouncycastle.bcpg.sig.RevocationReason; 020import org.bouncycastle.bcpg.sig.SignatureExpirationTime; 021import org.bouncycastle.bcpg.sig.SignatureTarget; 022import org.bouncycastle.bcpg.sig.SignerUserID; 023import org.bouncycastle.bcpg.sig.TrustSignature; 024import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator; 025import org.bouncycastle.openpgp.PGPSignatureSubpacketVector; 026import org.pgpainless.algorithm.Feature; 027import org.pgpainless.algorithm.HashAlgorithm; 028import org.pgpainless.algorithm.KeyFlag; 029import org.pgpainless.algorithm.PublicKeyAlgorithm; 030import org.pgpainless.key.util.RevocationAttributes; 031 032public class SignatureSubpacketsHelper { 033 034 public static SignatureSubpackets applyFrom(PGPSignatureSubpacketVector vector, SignatureSubpackets subpackets) { 035 for (SignatureSubpacket subpacket : vector.toArray()) { 036 org.pgpainless.algorithm.SignatureSubpacket type = org.pgpainless.algorithm.SignatureSubpacket.fromCode(subpacket.getType()); 037 switch (type) { 038 case signatureCreationTime: 039 case issuerKeyId: 040 case issuerFingerprint: 041 // ignore, we override this anyways 042 break; 043 case signatureExpirationTime: 044 SignatureExpirationTime sigExpTime = (SignatureExpirationTime) subpacket; 045 subpackets.setSignatureExpirationTime(sigExpTime.isCritical(), sigExpTime.getTime()); 046 break; 047 case exportableCertification: 048 Exportable exp = (Exportable) subpacket; 049 subpackets.setExportable(exp.isCritical(), exp.isExportable()); 050 break; 051 case trustSignature: 052 TrustSignature trustSignature = (TrustSignature) subpacket; 053 subpackets.setTrust(trustSignature.isCritical(), trustSignature.getDepth(), trustSignature.getTrustAmount()); 054 break; 055 case revocable: 056 Revocable rev = (Revocable) subpacket; 057 subpackets.setRevocable(rev.isCritical(), rev.isRevocable()); 058 break; 059 case keyExpirationTime: 060 KeyExpirationTime keyExpTime = (KeyExpirationTime) subpacket; 061 subpackets.setKeyExpirationTime(keyExpTime.isCritical(), keyExpTime.getTime()); 062 break; 063 case preferredSymmetricAlgorithms: 064 subpackets.setPreferredSymmetricKeyAlgorithms((PreferredAlgorithms) subpacket); 065 break; 066 case revocationKey: 067 RevocationKey revocationKey = (RevocationKey) subpacket; 068 subpackets.addRevocationKey(revocationKey); 069 break; 070 case notationData: 071 NotationData notationData = (NotationData) subpacket; 072 subpackets.addNotationData(notationData.isCritical(), notationData.getNotationName(), notationData.getNotationValue()); 073 break; 074 case preferredHashAlgorithms: 075 subpackets.setPreferredHashAlgorithms((PreferredAlgorithms) subpacket); 076 break; 077 case preferredCompressionAlgorithms: 078 subpackets.setPreferredCompressionAlgorithms((PreferredAlgorithms) subpacket); 079 break; 080 case primaryUserId: 081 PrimaryUserID primaryUserID = (PrimaryUserID) subpacket; 082 subpackets.setPrimaryUserId(primaryUserID); 083 break; 084 case keyFlags: 085 KeyFlags flags = (KeyFlags) subpacket; 086 subpackets.setKeyFlags(flags.isCritical(), KeyFlag.fromBitmask(flags.getFlags()).toArray(new KeyFlag[0])); 087 break; 088 case signerUserId: 089 SignerUserID signerUserID = (SignerUserID) subpacket; 090 subpackets.setSignerUserId(signerUserID.isCritical(), signerUserID.getID()); 091 break; 092 case revocationReason: 093 RevocationReason reason = (RevocationReason) subpacket; 094 subpackets.setRevocationReason(reason.isCritical(), 095 RevocationAttributes.Reason.fromCode(reason.getRevocationReason()), 096 reason.getRevocationDescription()); 097 break; 098 case features: 099 Features f = (Features) subpacket; 100 subpackets.setFeatures(f.isCritical(), Feature.fromBitmask(f.getData()[0]).toArray(new Feature[0])); 101 break; 102 case signatureTarget: 103 SignatureTarget target = (SignatureTarget) subpacket; 104 subpackets.setSignatureTarget(target.isCritical(), 105 PublicKeyAlgorithm.fromId(target.getPublicKeyAlgorithm()), 106 HashAlgorithm.fromId(target.getHashAlgorithm()), 107 target.getHashData()); 108 break; 109 case embeddedSignature: 110 EmbeddedSignature embeddedSignature = (EmbeddedSignature) subpacket; 111 subpackets.addEmbeddedSignature(embeddedSignature); 112 break; 113 case intendedRecipientFingerprint: 114 IntendedRecipientFingerprint intendedRecipientFingerprint = (IntendedRecipientFingerprint) subpacket; 115 subpackets.addIntendedRecipientFingerprint(intendedRecipientFingerprint); 116 break; 117 118 case regularExpression: 119 case keyServerPreferences: 120 case preferredKeyServers: 121 case policyUrl: 122 case placeholder: 123 case preferredAEADAlgorithms: 124 case attestedCertification: 125 subpackets.addResidualSubpacket(subpacket); 126 break; 127 } 128 } 129 return subpackets; 130 } 131 132 public static PGPSignatureSubpacketGenerator applyTo(SignatureSubpackets subpackets, PGPSignatureSubpacketGenerator generator) { 133 addSubpacket(generator, subpackets.getIssuerKeyIdSubpacket()); 134 addSubpacket(generator, subpackets.getIssuerFingerprintSubpacket()); 135 addSubpacket(generator, subpackets.getSignatureCreationTimeSubpacket()); 136 addSubpacket(generator, subpackets.getSignatureExpirationTimeSubpacket()); 137 addSubpacket(generator, subpackets.getExportableSubpacket()); 138 for (NotationData notationData : subpackets.getNotationDataSubpackets()) { 139 addSubpacket(generator, notationData); 140 } 141 for (IntendedRecipientFingerprint intendedRecipientFingerprint : subpackets.getIntendedRecipientFingerprintSubpackets()) { 142 addSubpacket(generator, intendedRecipientFingerprint); 143 } 144 for (RevocationKey revocationKey : subpackets.getRevocationKeySubpackets()) { 145 addSubpacket(generator, revocationKey); 146 } 147 addSubpacket(generator, subpackets.getSignatureTargetSubpacket()); 148 addSubpacket(generator, subpackets.getFeaturesSubpacket()); 149 addSubpacket(generator, subpackets.getKeyFlagsSubpacket()); 150 addSubpacket(generator, subpackets.getTrustSubpacket()); 151 addSubpacket(generator, subpackets.getPreferredCompressionAlgorithmsSubpacket()); 152 addSubpacket(generator, subpackets.getPreferredSymmetricKeyAlgorithmsSubpacket()); 153 addSubpacket(generator, subpackets.getPreferredHashAlgorithmsSubpacket()); 154 for (EmbeddedSignature embeddedSignature : subpackets.getEmbeddedSignatureSubpackets()) { 155 addSubpacket(generator, embeddedSignature); 156 } 157 addSubpacket(generator, subpackets.getSignerUserIdSubpacket()); 158 addSubpacket(generator, subpackets.getKeyExpirationTimeSubpacket()); 159 addSubpacket(generator, subpackets.getPrimaryUserIdSubpacket()); 160 addSubpacket(generator, subpackets.getRevocableSubpacket()); 161 addSubpacket(generator, subpackets.getRevocationReasonSubpacket()); 162 for (SignatureSubpacket subpacket : subpackets.getResidualSubpackets()) { 163 addSubpacket(generator, subpacket); 164 } 165 166 return generator; 167 } 168 169 private static void addSubpacket(PGPSignatureSubpacketGenerator generator, SignatureSubpacket subpacket) { 170 if (subpacket != null) { 171 generator.addCustomSubpacket(subpacket); 172 } 173 } 174 175 public static PGPSignatureSubpacketVector toVector(SignatureSubpackets subpackets) { 176 PGPSignatureSubpacketGenerator generator = new PGPSignatureSubpacketGenerator(); 177 applyTo(subpackets, generator); 178 return generator.generate(); 179 } 180 181 public static PGPSignatureSubpacketVector toVector(RevocationSignatureSubpackets subpackets) { 182 PGPSignatureSubpacketGenerator generator = new PGPSignatureSubpacketGenerator(); 183 applyTo((SignatureSubpackets) subpackets, generator); 184 return generator.generate(); 185 } 186}