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 java.io.IOException;
008import java.util.ArrayList;
009import java.util.Arrays;
010import java.util.Date;
011import java.util.Iterator;
012import java.util.LinkedHashSet;
013import java.util.List;
014import java.util.Set;
015import javax.annotation.Nonnull;
016import javax.annotation.Nullable;
017
018import org.bouncycastle.bcpg.SignatureSubpacket;
019import org.bouncycastle.bcpg.SignatureSubpacketTags;
020import org.bouncycastle.bcpg.sig.EmbeddedSignature;
021import org.bouncycastle.bcpg.sig.Exportable;
022import org.bouncycastle.bcpg.sig.Features;
023import org.bouncycastle.bcpg.sig.IntendedRecipientFingerprint;
024import org.bouncycastle.bcpg.sig.IssuerFingerprint;
025import org.bouncycastle.bcpg.sig.IssuerKeyID;
026import org.bouncycastle.bcpg.sig.KeyExpirationTime;
027import org.bouncycastle.bcpg.sig.KeyFlags;
028import org.bouncycastle.bcpg.sig.NotationData;
029import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
030import org.bouncycastle.bcpg.sig.PrimaryUserID;
031import org.bouncycastle.bcpg.sig.Revocable;
032import org.bouncycastle.bcpg.sig.RevocationKey;
033import org.bouncycastle.bcpg.sig.RevocationReason;
034import org.bouncycastle.bcpg.sig.SignatureCreationTime;
035import org.bouncycastle.bcpg.sig.SignatureExpirationTime;
036import org.bouncycastle.bcpg.sig.SignatureTarget;
037import org.bouncycastle.bcpg.sig.SignerUserID;
038import org.bouncycastle.bcpg.sig.TrustSignature;
039import org.bouncycastle.openpgp.PGPPublicKey;
040import org.bouncycastle.openpgp.PGPSignature;
041import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
042import org.pgpainless.algorithm.CompressionAlgorithm;
043import org.pgpainless.algorithm.Feature;
044import org.pgpainless.algorithm.HashAlgorithm;
045import org.pgpainless.algorithm.KeyFlag;
046import org.pgpainless.algorithm.PublicKeyAlgorithm;
047import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
048import org.pgpainless.key.util.RevocationAttributes;
049
050public class SignatureSubpackets
051        implements BaseSignatureSubpackets, SelfSignatureSubpackets, CertificationSubpackets, RevocationSignatureSubpackets {
052
053    private SignatureCreationTime signatureCreationTime;
054    private SignatureExpirationTime signatureExpirationTime;
055    private IssuerKeyID issuerKeyID;
056    private IssuerFingerprint issuerFingerprint;
057    private final List<NotationData> notationDataList = new ArrayList<>();
058    private final List<IntendedRecipientFingerprint> intendedRecipientFingerprintList = new ArrayList<>();
059    private final List<RevocationKey> revocationKeyList = new ArrayList<>();
060    private Exportable exportable;
061    private SignatureTarget signatureTarget;
062    private Features features;
063    private KeyFlags keyFlags;
064    private TrustSignature trust;
065    private PreferredAlgorithms preferredCompressionAlgorithms;
066    private PreferredAlgorithms preferredSymmetricKeyAlgorithms;
067    private PreferredAlgorithms preferredHashAlgorithms;
068    private final List<EmbeddedSignature> embeddedSignatureList = new ArrayList<>();
069    private SignerUserID signerUserId;
070    private KeyExpirationTime keyExpirationTime;
071    private PrimaryUserID primaryUserId;
072    private Revocable revocable;
073    private RevocationReason revocationReason;
074    private final List<SignatureSubpacket> residualSubpackets = new ArrayList<>();
075
076    public SignatureSubpackets() {
077
078    }
079
080    public static SignatureSubpackets refreshHashedSubpackets(PGPPublicKey issuer, PGPSignature oldSignature) {
081        return createHashedSubpacketsFrom(issuer, oldSignature.getHashedSubPackets());
082    }
083
084    public static SignatureSubpackets refreshUnhashedSubpackets(PGPSignature oldSignature) {
085        return createSubpacketsFrom(oldSignature.getUnhashedSubPackets());
086    }
087
088    public static SignatureSubpackets createHashedSubpacketsFrom(PGPPublicKey issuer, PGPSignatureSubpacketVector base) {
089        SignatureSubpackets wrapper = createSubpacketsFrom(base);
090        wrapper.setIssuerFingerprintAndKeyId(issuer);
091        return wrapper;
092    }
093
094    public static SignatureSubpackets createSubpacketsFrom(PGPSignatureSubpacketVector base) {
095        SignatureSubpackets wrapper = new SignatureSubpackets();
096        SignatureSubpacketsHelper.applyFrom(base, wrapper);
097        return wrapper;
098    }
099
100    public static SignatureSubpackets createHashedSubpackets(PGPPublicKey issuer) {
101        SignatureSubpackets wrapper = new SignatureSubpackets();
102        wrapper.setIssuerFingerprintAndKeyId(issuer);
103        return wrapper;
104    }
105
106    public static SignatureSubpackets createEmptySubpackets() {
107        return new SignatureSubpackets();
108    }
109
110    @Override
111    public SignatureSubpackets setIssuerFingerprintAndKeyId(PGPPublicKey key) {
112        setIssuerKeyId(key.getKeyID());
113        setIssuerFingerprint(key);
114        return this;
115    }
116
117    @Override
118    public SignatureSubpackets setIssuerKeyId(long keyId) {
119        return setIssuerKeyId(true, keyId);
120    }
121
122    @Override
123    public SignatureSubpackets setIssuerKeyId(boolean isCritical, long keyId) {
124        return setIssuerKeyId(new IssuerKeyID(isCritical, keyId));
125    }
126
127    @Override
128    public SignatureSubpackets setIssuerKeyId(@Nullable IssuerKeyID issuerKeyID) {
129        this.issuerKeyID = issuerKeyID;
130        return this;
131    }
132
133    public IssuerKeyID getIssuerKeyIdSubpacket() {
134        return issuerKeyID;
135    }
136
137    @Override
138    public SignatureSubpackets setIssuerFingerprint(@Nonnull PGPPublicKey key) {
139        return setIssuerFingerprint(true, key);
140    }
141
142    @Override
143    public SignatureSubpackets setIssuerFingerprint(boolean isCritical, @Nonnull PGPPublicKey key) {
144        return setIssuerFingerprint(new IssuerFingerprint(isCritical, key.getVersion(), key.getFingerprint()));
145    }
146
147    @Override
148    public SignatureSubpackets setIssuerFingerprint(@Nullable IssuerFingerprint fingerprint) {
149        this.issuerFingerprint = fingerprint;
150        return this;
151    }
152
153    public IssuerFingerprint getIssuerFingerprintSubpacket() {
154        return issuerFingerprint;
155    }
156
157    @Override
158    public SignatureSubpackets setKeyFlags(KeyFlag... keyFlags) {
159        return setKeyFlags(true, keyFlags);
160    }
161
162    @Override
163    public SignatureSubpackets setKeyFlags(boolean isCritical, KeyFlag... keyFlags) {
164        int bitmask = KeyFlag.toBitmask(keyFlags);
165        return setKeyFlags(new KeyFlags(isCritical, bitmask));
166    }
167
168    @Override
169    public SignatureSubpackets setKeyFlags(@Nullable KeyFlags keyFlags) {
170        this.keyFlags = keyFlags;
171        return this;
172    }
173
174    public KeyFlags getKeyFlagsSubpacket() {
175        return keyFlags;
176    }
177
178    @Override
179    public SignatureSubpackets setSignatureCreationTime(@Nonnull Date creationTime) {
180        return setSignatureCreationTime(true, creationTime);
181    }
182
183    @Override
184    public SignatureSubpackets setSignatureCreationTime(boolean isCritical, @Nonnull Date creationTime) {
185        return setSignatureCreationTime(new SignatureCreationTime(isCritical, creationTime));
186    }
187
188    @Override
189    public SignatureSubpackets setSignatureCreationTime(@Nullable SignatureCreationTime signatureCreationTime) {
190        this.signatureCreationTime = signatureCreationTime;
191        return this;
192    }
193
194    public SignatureCreationTime getSignatureCreationTimeSubpacket() {
195        return signatureCreationTime;
196    }
197
198    @Override
199    public SignatureSubpackets setSignatureExpirationTime(@Nonnull Date creationTime, @Nonnull Date expirationTime) {
200        return setSignatureExpirationTime(true, creationTime, expirationTime);
201    }
202
203    @Override
204    public SignatureSubpackets setSignatureExpirationTime(boolean isCritical, @Nonnull Date creationTime, @Nonnull Date expirationTime) {
205        return setSignatureExpirationTime(isCritical, (expirationTime.getTime() / 1000) - (creationTime.getTime() / 1000));
206    }
207
208    @Override
209    public SignatureSubpackets setSignatureExpirationTime(boolean isCritical, long seconds) {
210        if (seconds < 0) {
211            throw new IllegalArgumentException("Expiration time cannot be negative.");
212        }
213        return setSignatureExpirationTime(new SignatureExpirationTime(isCritical, seconds));
214    }
215
216    @Override
217    public SignatureSubpackets setSignatureExpirationTime(@Nullable SignatureExpirationTime expirationTime) {
218        this.signatureExpirationTime = expirationTime;
219        return this;
220    }
221
222    public SignatureExpirationTime getSignatureExpirationTimeSubpacket() {
223        return signatureExpirationTime;
224    }
225
226    @Override
227    public SignatureSubpackets setSignerUserId(@Nonnull String userId) {
228        return setSignerUserId(false, userId);
229    }
230
231    @Override
232    public SignatureSubpackets setSignerUserId(boolean isCritical, @Nonnull String userId) {
233        return setSignerUserId(new SignerUserID(isCritical, userId));
234    }
235
236    @Override
237    public SignatureSubpackets setSignerUserId(@Nullable SignerUserID signerUserId) {
238        this.signerUserId = signerUserId;
239        return this;
240    }
241
242    public SignerUserID getSignerUserIdSubpacket() {
243        return signerUserId;
244    }
245
246    @Override
247    public SignatureSubpackets setPrimaryUserId() {
248        return setPrimaryUserId(true);
249    }
250
251    @Override
252    public SignatureSubpackets setPrimaryUserId(boolean isCritical) {
253        return setPrimaryUserId(new PrimaryUserID(isCritical, true));
254    }
255
256    @Override
257    public SignatureSubpackets setPrimaryUserId(@Nullable PrimaryUserID primaryUserId) {
258        this.primaryUserId = primaryUserId;
259        return this;
260    }
261
262    public PrimaryUserID getPrimaryUserIdSubpacket() {
263        return primaryUserId;
264    }
265
266    @Override
267    public SignatureSubpackets setKeyExpirationTime(@Nonnull PGPPublicKey key, @Nonnull Date keyExpirationTime) {
268        return setKeyExpirationTime(key.getCreationTime(), keyExpirationTime);
269    }
270
271    @Override
272    public SignatureSubpackets setKeyExpirationTime(@Nonnull Date keyCreationTime, @Nonnull Date keyExpirationTime) {
273        return setKeyExpirationTime(true, keyCreationTime, keyExpirationTime);
274    }
275
276    @Override
277    public SignatureSubpackets setKeyExpirationTime(boolean isCritical, @Nonnull Date keyCreationTime, @Nonnull Date keyExpirationTime) {
278        return setKeyExpirationTime(isCritical, (keyExpirationTime.getTime() / 1000) - (keyCreationTime.getTime() / 1000));
279    }
280
281    @Override
282    public SignatureSubpackets setKeyExpirationTime(boolean isCritical, long secondsFromCreationToExpiration) {
283        if (secondsFromCreationToExpiration < 0) {
284            throw new IllegalArgumentException("Seconds from key creation to expiration cannot be less than 0.");
285        }
286        return setKeyExpirationTime(new KeyExpirationTime(isCritical, secondsFromCreationToExpiration));
287    }
288
289    @Override
290    public SignatureSubpackets setKeyExpirationTime(@Nullable KeyExpirationTime keyExpirationTime) {
291        this.keyExpirationTime = keyExpirationTime;
292        return this;
293    }
294
295    public KeyExpirationTime getKeyExpirationTimeSubpacket() {
296        return keyExpirationTime;
297    }
298
299    @Override
300    public SignatureSubpackets setPreferredCompressionAlgorithms(CompressionAlgorithm... algorithms) {
301        return setPreferredCompressionAlgorithms(new LinkedHashSet<>(Arrays.asList(algorithms)));
302    }
303
304    @Override
305    public SignatureSubpackets setPreferredCompressionAlgorithms(Set<CompressionAlgorithm> algorithms) {
306        return setPreferredCompressionAlgorithms(true, algorithms);
307    }
308
309    @Override
310    public SignatureSubpackets setPreferredCompressionAlgorithms(boolean isCritical, Set<CompressionAlgorithm> algorithms) {
311        int[] ids = new int[algorithms.size()];
312        Iterator<CompressionAlgorithm> iterator = algorithms.iterator();
313        for (int i = 0; i < algorithms.size(); i++) {
314            ids[i] = iterator.next().getAlgorithmId();
315        }
316        return setPreferredCompressionAlgorithms(new PreferredAlgorithms(
317                SignatureSubpacketTags.PREFERRED_COMP_ALGS, isCritical, ids));
318    }
319
320    @Override
321    public SignatureSubpackets setPreferredCompressionAlgorithms(@Nullable PreferredAlgorithms algorithms) {
322        if (algorithms == null) {
323            this.preferredCompressionAlgorithms = null;
324            return this;
325        }
326
327        if (algorithms.getType() != SignatureSubpacketTags.PREFERRED_COMP_ALGS) {
328            throw new IllegalArgumentException("Invalid preferred compression algorithms type.");
329        }
330        this.preferredCompressionAlgorithms = algorithms;
331        return this;
332    }
333
334    public PreferredAlgorithms getPreferredCompressionAlgorithmsSubpacket() {
335        return preferredCompressionAlgorithms;
336    }
337
338    @Override
339    public SignatureSubpackets setPreferredSymmetricKeyAlgorithms(SymmetricKeyAlgorithm... algorithms) {
340        return setPreferredSymmetricKeyAlgorithms(new LinkedHashSet<>(Arrays.asList(algorithms)));
341    }
342
343    @Override
344    public SignatureSubpackets setPreferredSymmetricKeyAlgorithms(Set<SymmetricKeyAlgorithm> algorithms) {
345        return setPreferredSymmetricKeyAlgorithms(true, algorithms);
346    }
347
348    @Override
349    public SignatureSubpackets setPreferredSymmetricKeyAlgorithms(boolean isCritical, Set<SymmetricKeyAlgorithm> algorithms) {
350        int[] ids = new int[algorithms.size()];
351        Iterator<SymmetricKeyAlgorithm> iterator = algorithms.iterator();
352        for (int i = 0; i < algorithms.size(); i++) {
353            ids[i] = iterator.next().getAlgorithmId();
354        }
355        return setPreferredSymmetricKeyAlgorithms(new PreferredAlgorithms(
356                SignatureSubpacketTags.PREFERRED_SYM_ALGS, isCritical, ids));
357    }
358
359    @Override
360    public SignatureSubpackets setPreferredSymmetricKeyAlgorithms(@Nullable PreferredAlgorithms algorithms) {
361        if (algorithms == null) {
362            this.preferredSymmetricKeyAlgorithms = null;
363            return this;
364        }
365
366        if (algorithms.getType() != SignatureSubpacketTags.PREFERRED_SYM_ALGS) {
367            throw new IllegalArgumentException("Invalid preferred symmetric key algorithms type.");
368        }
369        this.preferredSymmetricKeyAlgorithms = algorithms;
370        return this;
371    }
372
373    public PreferredAlgorithms getPreferredSymmetricKeyAlgorithmsSubpacket() {
374        return preferredSymmetricKeyAlgorithms;
375    }
376
377    @Override
378    public SignatureSubpackets setPreferredHashAlgorithms(HashAlgorithm... algorithms) {
379        return setPreferredHashAlgorithms(new LinkedHashSet<>(Arrays.asList(algorithms)));
380    }
381
382    @Override
383    public SignatureSubpackets setPreferredHashAlgorithms(Set<HashAlgorithm> algorithms) {
384        return setPreferredHashAlgorithms(true, algorithms);
385    }
386
387    @Override
388    public SignatureSubpackets setPreferredHashAlgorithms(boolean isCritical, Set<HashAlgorithm> algorithms) {
389        int[] ids = new int[algorithms.size()];
390        Iterator<HashAlgorithm> iterator = algorithms.iterator();
391        for (int i = 0; i < ids.length; i++) {
392            ids[i] = iterator.next().getAlgorithmId();
393        }
394        return setPreferredHashAlgorithms(new PreferredAlgorithms(
395                SignatureSubpacketTags.PREFERRED_HASH_ALGS, isCritical, ids));
396    }
397
398    @Override
399    public SignatureSubpackets setPreferredHashAlgorithms(@Nullable PreferredAlgorithms algorithms) {
400        if (algorithms == null) {
401            preferredHashAlgorithms = null;
402            return this;
403        }
404
405        if (algorithms.getType() != SignatureSubpacketTags.PREFERRED_HASH_ALGS) {
406            throw new IllegalArgumentException("Invalid preferred hash algorithms type.");
407        }
408        this.preferredHashAlgorithms = algorithms;
409        return this;
410    }
411
412    public PreferredAlgorithms getPreferredHashAlgorithmsSubpacket() {
413        return preferredHashAlgorithms;
414    }
415
416    @Override
417    public SignatureSubpackets addNotationData(boolean isCritical, @Nonnull String notationName, @Nonnull String notationValue) {
418        return addNotationData(isCritical, true, notationName, notationValue);
419    }
420
421    @Override
422    public SignatureSubpackets addNotationData(boolean isCritical, boolean isHumanReadable, @Nonnull String notationName, @Nonnull String notationValue) {
423        return addNotationData(new NotationData(isCritical, isHumanReadable, notationName, notationValue));
424    }
425
426    @Override
427    public SignatureSubpackets addNotationData(@Nonnull NotationData notationData) {
428        notationDataList.add(notationData);
429        return this;
430    }
431
432    @Override
433    public SignatureSubpackets clearNotationData() {
434        notationDataList.clear();
435        return this;
436    }
437
438    public List<NotationData> getNotationDataSubpackets() {
439        return new ArrayList<>(notationDataList);
440    }
441
442    @Override
443    public SignatureSubpackets addIntendedRecipientFingerprint(@Nonnull PGPPublicKey recipient) {
444        return addIntendedRecipientFingerprint(false, recipient);
445    }
446
447    @Override
448    public SignatureSubpackets addIntendedRecipientFingerprint(boolean isCritical, @Nonnull PGPPublicKey recipient) {
449        return addIntendedRecipientFingerprint(new IntendedRecipientFingerprint(isCritical, recipient.getVersion(), recipient.getFingerprint()));
450    }
451
452    @Override
453    public SignatureSubpackets addIntendedRecipientFingerprint(IntendedRecipientFingerprint intendedRecipientFingerprint) {
454        this.intendedRecipientFingerprintList.add(intendedRecipientFingerprint);
455        return this;
456    }
457
458    @Override
459    public SignatureSubpackets clearIntendedRecipientFingerprints() {
460        intendedRecipientFingerprintList.clear();
461        return this;
462    }
463
464    public List<IntendedRecipientFingerprint> getIntendedRecipientFingerprintSubpackets() {
465        return new ArrayList<>(intendedRecipientFingerprintList);
466    }
467
468    @Override
469    public SignatureSubpackets setExportable(boolean isCritical, boolean isExportable) {
470        return setExportable(new Exportable(isCritical, isExportable));
471    }
472
473    @Override
474    public SignatureSubpackets setExportable(@Nullable Exportable exportable) {
475        this.exportable = exportable;
476        return this;
477    }
478
479    public Exportable getExportableSubpacket() {
480        return exportable;
481    }
482
483    @Override
484    public SignatureSubpackets setRevocable(boolean isCritical, boolean isRevocable) {
485        return setRevocable(new Revocable(isCritical, isRevocable));
486    }
487
488    @Override
489    public SignatureSubpackets setRevocable(@Nullable Revocable revocable) {
490        this.revocable = revocable;
491        return this;
492    }
493
494    public Revocable getRevocableSubpacket() {
495        return revocable;
496    }
497
498    @Override
499    public SignatureSubpackets addRevocationKey(@Nonnull PGPPublicKey revocationKey) {
500        return addRevocationKey(true, revocationKey);
501    }
502
503    @Override
504    public SignatureSubpackets addRevocationKey(boolean isCritical, @Nonnull PGPPublicKey revocationKey) {
505        return addRevocationKey(isCritical, false, revocationKey);
506    }
507
508    @Override
509    public SignatureSubpackets addRevocationKey(boolean isCritical, boolean isSensitive, @Nonnull PGPPublicKey revocationKey) {
510        byte clazz = (byte) 0x80;
511        clazz |= (isSensitive ? 0x40 : 0x00);
512        return addRevocationKey(new RevocationKey(isCritical, clazz, revocationKey.getAlgorithm(), revocationKey.getFingerprint()));
513    }
514
515    @Override
516    public SignatureSubpackets addRevocationKey(@Nonnull RevocationKey revocationKey) {
517        this.revocationKeyList.add(revocationKey);
518        return this;
519    }
520
521    @Override
522    public SignatureSubpackets clearRevocationKeys() {
523        revocationKeyList.clear();
524        return this;
525    }
526
527    public List<RevocationKey> getRevocationKeySubpackets() {
528        return new ArrayList<>(revocationKeyList);
529    }
530
531    @Override
532    public SignatureSubpackets setRevocationReason(RevocationAttributes revocationAttributes) {
533        return setRevocationReason(true, revocationAttributes);
534    }
535
536    @Override
537    public SignatureSubpackets setRevocationReason(boolean isCritical, RevocationAttributes revocationAttributes) {
538        return setRevocationReason(isCritical, revocationAttributes.getReason(), revocationAttributes.getDescription());
539    }
540
541    @Override
542    public SignatureSubpackets setRevocationReason(boolean isCritical, RevocationAttributes.Reason reason, @Nonnull String description) {
543        return setRevocationReason(new RevocationReason(isCritical, reason.code(), description));
544    }
545
546    @Override
547    public SignatureSubpackets setRevocationReason(@Nullable RevocationReason reason) {
548        this.revocationReason = reason;
549        return this;
550    }
551
552    public RevocationReason getRevocationReasonSubpacket() {
553        return revocationReason;
554    }
555
556    @Override
557    public SignatureSubpackets setSignatureTarget(@Nonnull PublicKeyAlgorithm keyAlgorithm, @Nonnull HashAlgorithm hashAlgorithm, @Nonnull byte[] hashData) {
558        return setSignatureTarget(true, keyAlgorithm, hashAlgorithm, hashData);
559    }
560
561    @Override
562    public SignatureSubpackets setSignatureTarget(boolean isCritical, @Nonnull PublicKeyAlgorithm keyAlgorithm, @Nonnull HashAlgorithm hashAlgorithm, @Nonnull byte[] hashData) {
563        return setSignatureTarget(new SignatureTarget(isCritical, keyAlgorithm.getAlgorithmId(), hashAlgorithm.getAlgorithmId(), hashData));
564    }
565
566    @Override
567    public SignatureSubpackets setSignatureTarget(@Nullable SignatureTarget signatureTarget) {
568        this.signatureTarget = signatureTarget;
569        return this;
570    }
571
572    public SignatureTarget getSignatureTargetSubpacket() {
573        return signatureTarget;
574    }
575
576    @Override
577    public SignatureSubpackets setFeatures(Feature... features) {
578        return setFeatures(true, features);
579    }
580
581    @Override
582    public SignatureSubpackets setFeatures(boolean isCritical, Feature... features) {
583        byte bitmask = Feature.toBitmask(features);
584        return setFeatures(new Features(isCritical, bitmask));
585    }
586
587    @Override
588    public SignatureSubpackets setFeatures(@Nullable Features features) {
589        this.features = features;
590        return this;
591    }
592
593    public Features getFeaturesSubpacket() {
594        return features;
595    }
596
597    @Override
598    public SignatureSubpackets setTrust(int depth, int amount) {
599        return setTrust(true, depth, amount);
600    }
601
602    @Override
603    public SignatureSubpackets setTrust(boolean isCritical, int depth, int amount) {
604        return setTrust(new TrustSignature(isCritical, depth, amount));
605    }
606
607    @Override
608    public SignatureSubpackets setTrust(@Nullable TrustSignature trust) {
609        this.trust = trust;
610        return this;
611    }
612
613    public TrustSignature getTrustSubpacket() {
614        return trust;
615    }
616
617    @Override
618    public SignatureSubpackets addEmbeddedSignature(@Nonnull PGPSignature signature) throws IOException {
619        return addEmbeddedSignature(true, signature);
620    }
621
622    @Override
623    public SignatureSubpackets addEmbeddedSignature(boolean isCritical, @Nonnull PGPSignature signature) throws IOException {
624        byte[] sig = signature.getEncoded();
625        byte[] data;
626
627        if (sig.length - 1 > 256) {
628            data = new byte[sig.length - 3];
629        }
630        else {
631            data = new byte[sig.length - 2];
632        }
633
634        System.arraycopy(sig, sig.length - data.length, data, 0, data.length);
635
636        return addEmbeddedSignature(new EmbeddedSignature(isCritical, false, data));
637    }
638
639    @Override
640    public SignatureSubpackets addEmbeddedSignature(@Nonnull EmbeddedSignature embeddedSignature) {
641        this.embeddedSignatureList.add(embeddedSignature);
642        return this;
643    }
644
645    @Override
646    public SignatureSubpackets clearEmbeddedSignatures() {
647        this.embeddedSignatureList.clear();
648        return this;
649    }
650
651    public List<EmbeddedSignature> getEmbeddedSignatureSubpackets() {
652        return new ArrayList<>(embeddedSignatureList);
653    }
654
655    public SignatureSubpackets addResidualSubpacket(SignatureSubpacket subpacket) {
656        this.residualSubpackets.add(subpacket);
657        return this;
658    }
659
660    public List<SignatureSubpacket> getResidualSubpackets() {
661        return new ArrayList<>(residualSubpackets);
662    }
663
664}