mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-26 22:32:07 +01:00
Make SignatureSubpackets more procedural
This commit is contained in:
parent
3f09fa0cc7
commit
3d5a005ec7
9 changed files with 916 additions and 792 deletions
|
@ -19,6 +19,7 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import org.bouncycastle.bcpg.sig.KeyFlags;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPKeyPair;
|
import org.bouncycastle.openpgp.PGPKeyPair;
|
||||||
import org.bouncycastle.openpgp.PGPKeyRingGenerator;
|
import org.bouncycastle.openpgp.PGPKeyRingGenerator;
|
||||||
|
@ -44,8 +45,8 @@ import org.pgpainless.key.generation.type.KeyType;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||||
import org.pgpainless.provider.ProviderFactory;
|
import org.pgpainless.provider.ProviderFactory;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorUtil;
|
import org.pgpainless.signature.subpackets.SignatureSubpackets;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorWrapper;
|
import org.pgpainless.signature.subpackets.SignatureSubpacketsHelper;
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
|
|
||||||
public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
||||||
|
@ -112,9 +113,8 @@ public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasCertifyOthersFlag(KeySpec keySpec) {
|
private boolean hasCertifyOthersFlag(KeySpec keySpec) {
|
||||||
return SignatureSubpacketGeneratorUtil.hasKeyFlag(KeyFlag.CERTIFY_OTHER,
|
KeyFlags keyFlags = keySpec.getSubpacketGenerator().getKeyFlagsSubpacket();
|
||||||
keySpec.getSubpacketGenerator() == null ? null :
|
return keyFlags != null && KeyFlag.hasKeyFlag(keyFlags.getFlags(), KeyFlag.CERTIFY_OTHER);
|
||||||
keySpec.getSubpacketGenerator().getGenerator());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean keyIsCertificationCapable(KeySpec keySpec) {
|
private boolean keyIsCertificationCapable(KeySpec keySpec) {
|
||||||
|
@ -137,12 +137,14 @@ public class KeyRingBuilder implements KeyRingBuilderInterface<KeyRingBuilder> {
|
||||||
PGPKeyPair certKey = generateKeyPair(primaryKeySpec);
|
PGPKeyPair certKey = generateKeyPair(primaryKeySpec);
|
||||||
PGPContentSignerBuilder signer = buildContentSigner(certKey);
|
PGPContentSignerBuilder signer = buildContentSigner(certKey);
|
||||||
signatureGenerator = new PGPSignatureGenerator(signer);
|
signatureGenerator = new PGPSignatureGenerator(signer);
|
||||||
SignatureSubpacketGeneratorWrapper hashedSubPacketGenerator = primaryKeySpec.getSubpacketGenerator();
|
SignatureSubpackets hashedSubPacketGenerator = primaryKeySpec.getSubpacketGenerator();
|
||||||
hashedSubPacketGenerator.setPrimaryUserId();
|
hashedSubPacketGenerator.setPrimaryUserId();
|
||||||
if (expirationDate != null) {
|
if (expirationDate != null) {
|
||||||
hashedSubPacketGenerator.setKeyExpirationTime(certKey.getPublicKey(), expirationDate);
|
hashedSubPacketGenerator.setKeyExpirationTime(certKey.getPublicKey(), expirationDate);
|
||||||
}
|
}
|
||||||
PGPSignatureSubpacketVector hashedSubPackets = hashedSubPacketGenerator.getGenerator().generate();
|
PGPSignatureSubpacketGenerator generator = new PGPSignatureSubpacketGenerator();
|
||||||
|
SignatureSubpacketsHelper.applyTo(hashedSubPacketGenerator, generator);
|
||||||
|
PGPSignatureSubpacketVector hashedSubPackets = generator.generate();
|
||||||
|
|
||||||
// Generator which the user can get the key pair from
|
// Generator which the user can get the key pair from
|
||||||
PGPKeyRingGenerator ringGenerator = buildRingGenerator(certKey, signer, hashedSubPackets);
|
PGPKeyRingGenerator ringGenerator = buildRingGenerator(certKey, signer, hashedSubPackets);
|
||||||
|
|
|
@ -10,12 +10,13 @@ import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
import org.pgpainless.algorithm.KeyFlag;
|
import org.pgpainless.algorithm.KeyFlag;
|
||||||
import org.pgpainless.key.generation.type.KeyType;
|
import org.pgpainless.key.generation.type.KeyType;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorWrapper;
|
import org.pgpainless.signature.subpackets.SignatureSubpackets;
|
||||||
|
import org.pgpainless.signature.subpackets.SignatureSubpacketsHelper;
|
||||||
|
|
||||||
public class KeySpec {
|
public class KeySpec {
|
||||||
|
|
||||||
private final KeyType keyType;
|
private final KeyType keyType;
|
||||||
private final SignatureSubpacketGeneratorWrapper subpacketGenerator;
|
private final SignatureSubpackets subpacketGenerator;
|
||||||
private final boolean inheritedSubPackets;
|
private final boolean inheritedSubPackets;
|
||||||
|
|
||||||
KeySpec(@Nonnull KeyType type,
|
KeySpec(@Nonnull KeyType type,
|
||||||
|
@ -23,12 +24,12 @@ public class KeySpec {
|
||||||
boolean inheritedSubPackets) {
|
boolean inheritedSubPackets) {
|
||||||
this(
|
this(
|
||||||
type,
|
type,
|
||||||
SignatureSubpacketGeneratorWrapper.createSubpacketsFrom(subpacketGenerator.generate()),
|
SignatureSubpackets.createSubpacketsFrom(subpacketGenerator.generate()),
|
||||||
inheritedSubPackets);
|
inheritedSubPackets);
|
||||||
}
|
}
|
||||||
|
|
||||||
KeySpec(@Nonnull KeyType type,
|
KeySpec(@Nonnull KeyType type,
|
||||||
@Nonnull SignatureSubpacketGeneratorWrapper subpacketGenerator,
|
@Nonnull SignatureSubpackets subpacketGenerator,
|
||||||
boolean inheritedSubPackets) {
|
boolean inheritedSubPackets) {
|
||||||
this.keyType = type;
|
this.keyType = type;
|
||||||
this.subpacketGenerator = subpacketGenerator;
|
this.subpacketGenerator = subpacketGenerator;
|
||||||
|
@ -42,11 +43,11 @@ public class KeySpec {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public PGPSignatureSubpacketVector getSubpackets() {
|
public PGPSignatureSubpacketVector getSubpackets() {
|
||||||
return subpacketGenerator.getGenerator().generate();
|
return SignatureSubpacketsHelper.toVector(subpacketGenerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
SignatureSubpacketGeneratorWrapper getSubpacketGenerator() {
|
SignatureSubpackets getSubpacketGenerator() {
|
||||||
return subpacketGenerator;
|
return subpacketGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,8 @@ import org.pgpainless.implementation.ImplementationFactory;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||||
import org.pgpainless.key.util.OpenPgpKeyAttributeUtil;
|
import org.pgpainless.key.util.OpenPgpKeyAttributeUtil;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorWrapper;
|
import org.pgpainless.signature.subpackets.SignatureSubpackets;
|
||||||
|
import org.pgpainless.signature.subpackets.SignatureSubpacketsHelper;
|
||||||
|
|
||||||
public abstract class AbstractSignatureBuilder<B extends AbstractSignatureBuilder<B>> {
|
public abstract class AbstractSignatureBuilder<B extends AbstractSignatureBuilder<B>> {
|
||||||
protected final PGPPrivateKey privateSigningKey;
|
protected final PGPPrivateKey privateSigningKey;
|
||||||
|
@ -30,8 +31,8 @@ public abstract class AbstractSignatureBuilder<B extends AbstractSignatureBuilde
|
||||||
protected HashAlgorithm hashAlgorithm;
|
protected HashAlgorithm hashAlgorithm;
|
||||||
protected SignatureType signatureType;
|
protected SignatureType signatureType;
|
||||||
|
|
||||||
protected SignatureSubpacketGeneratorWrapper unhashedSubpackets;
|
protected SignatureSubpackets unhashedSubpackets;
|
||||||
protected SignatureSubpacketGeneratorWrapper hashedSubpackets;
|
protected SignatureSubpackets hashedSubpackets;
|
||||||
|
|
||||||
public AbstractSignatureBuilder(SignatureType signatureType, PGPSecretKey signingKey, SecretKeyRingProtector protector)
|
public AbstractSignatureBuilder(SignatureType signatureType, PGPSecretKey signingKey, SecretKeyRingProtector protector)
|
||||||
throws WrongPassphraseException {
|
throws WrongPassphraseException {
|
||||||
|
@ -43,9 +44,9 @@ public abstract class AbstractSignatureBuilder<B extends AbstractSignatureBuilde
|
||||||
this.publicSigningKey = signingKey.getPublicKey();
|
this.publicSigningKey = signingKey.getPublicKey();
|
||||||
this.hashAlgorithm = negotiateHashAlgorithm(publicSigningKey);
|
this.hashAlgorithm = negotiateHashAlgorithm(publicSigningKey);
|
||||||
|
|
||||||
unhashedSubpackets = SignatureSubpacketGeneratorWrapper.createEmptySubpackets();
|
unhashedSubpackets = new SignatureSubpackets();
|
||||||
// Prepopulate hashed subpackets with default values (key-id etc.)
|
// Prepopulate hashed subpackets with default values (key-id etc.)
|
||||||
hashedSubpackets = SignatureSubpacketGeneratorWrapper.createHashedSubpackets(publicSigningKey);
|
hashedSubpackets = SignatureSubpackets.createHashedSubpackets(publicSigningKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractSignatureBuilder(PGPSecretKey certificationKey, SecretKeyRingProtector protector, PGPSignature archetypeSignature)
|
public AbstractSignatureBuilder(PGPSecretKey certificationKey, SecretKeyRingProtector protector, PGPSignature archetypeSignature)
|
||||||
|
@ -59,8 +60,8 @@ public abstract class AbstractSignatureBuilder<B extends AbstractSignatureBuilde
|
||||||
this.publicSigningKey = certificationKey.getPublicKey();
|
this.publicSigningKey = certificationKey.getPublicKey();
|
||||||
this.hashAlgorithm = negotiateHashAlgorithm(publicSigningKey);
|
this.hashAlgorithm = negotiateHashAlgorithm(publicSigningKey);
|
||||||
|
|
||||||
unhashedSubpackets = SignatureSubpacketGeneratorWrapper.refreshUnhashedSubpackets(archetypeSignature);
|
unhashedSubpackets = SignatureSubpackets.refreshUnhashedSubpackets(archetypeSignature);
|
||||||
hashedSubpackets = SignatureSubpacketGeneratorWrapper.refreshHashedSubpackets(publicSigningKey, archetypeSignature);
|
hashedSubpackets = SignatureSubpackets.refreshHashedSubpackets(publicSigningKey, archetypeSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,8 +105,8 @@ public abstract class AbstractSignatureBuilder<B extends AbstractSignatureBuilde
|
||||||
publicSigningKey.getAlgorithm(), hashAlgorithm.getAlgorithmId()
|
publicSigningKey.getAlgorithm(), hashAlgorithm.getAlgorithmId()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
generator.setUnhashedSubpackets(unhashedSubpackets.getGenerator().generate());
|
generator.setUnhashedSubpackets(SignatureSubpacketsHelper.toVector(unhashedSubpackets));
|
||||||
generator.setHashedSubpackets(hashedSubpackets.getGenerator().generate());
|
generator.setHashedSubpackets(SignatureSubpacketsHelper.toVector(hashedSubpackets));
|
||||||
generator.init(signatureType.getCode(), privateSigningKey);
|
generator.init(signatureType.getCode(), privateSigningKey);
|
||||||
return generator;
|
return generator;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import org.pgpainless.algorithm.SignatureType;
|
||||||
import org.pgpainless.exception.WrongPassphraseException;
|
import org.pgpainless.exception.WrongPassphraseException;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.signature.subpackets.BaseSignatureSubpackets;
|
import org.pgpainless.signature.subpackets.BaseSignatureSubpackets;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorWrapper;
|
import org.pgpainless.signature.subpackets.SignatureSubpackets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature builder without restrictions on subpacket contents.
|
* Signature builder without restrictions on subpacket contents.
|
||||||
|
@ -36,11 +36,11 @@ public class UniversalSignatureBuilder extends AbstractSignatureBuilder<Universa
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignatureSubpacketGeneratorWrapper getHashedSubpackets() {
|
public SignatureSubpackets getHashedSubpackets() {
|
||||||
return hashedSubpackets;
|
return hashedSubpackets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignatureSubpacketGeneratorWrapper getUnhashedSubpackets() {
|
public SignatureSubpackets getUnhashedSubpackets() {
|
||||||
return unhashedSubpackets;
|
return unhashedSubpackets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
||||||
|
|
||||||
public interface BaseSignatureSubpackets {
|
public interface BaseSignatureSubpackets {
|
||||||
|
|
||||||
interface Callback extends SignatureSubpacketCallback<SignatureSubpacketGeneratorWrapper> {
|
interface Callback extends SignatureSubpacketCallback<SignatureSubpackets> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,719 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package org.pgpainless.signature.subpackets;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.SignatureSubpacket;
|
|
||||||
import org.bouncycastle.bcpg.SignatureSubpacketTags;
|
|
||||||
import org.bouncycastle.bcpg.sig.EmbeddedSignature;
|
|
||||||
import org.bouncycastle.bcpg.sig.Exportable;
|
|
||||||
import org.bouncycastle.bcpg.sig.Features;
|
|
||||||
import org.bouncycastle.bcpg.sig.IntendedRecipientFingerprint;
|
|
||||||
import org.bouncycastle.bcpg.sig.IssuerFingerprint;
|
|
||||||
import org.bouncycastle.bcpg.sig.IssuerKeyID;
|
|
||||||
import org.bouncycastle.bcpg.sig.KeyExpirationTime;
|
|
||||||
import org.bouncycastle.bcpg.sig.KeyFlags;
|
|
||||||
import org.bouncycastle.bcpg.sig.NotationData;
|
|
||||||
import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
|
|
||||||
import org.bouncycastle.bcpg.sig.PrimaryUserID;
|
|
||||||
import org.bouncycastle.bcpg.sig.Revocable;
|
|
||||||
import org.bouncycastle.bcpg.sig.RevocationKey;
|
|
||||||
import org.bouncycastle.bcpg.sig.RevocationReason;
|
|
||||||
import org.bouncycastle.bcpg.sig.SignatureCreationTime;
|
|
||||||
import org.bouncycastle.bcpg.sig.SignatureExpirationTime;
|
|
||||||
import org.bouncycastle.bcpg.sig.SignatureTarget;
|
|
||||||
import org.bouncycastle.bcpg.sig.SignerUserID;
|
|
||||||
import org.bouncycastle.bcpg.sig.TrustSignature;
|
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
|
||||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
|
||||||
import org.pgpainless.algorithm.Feature;
|
|
||||||
import org.pgpainless.algorithm.HashAlgorithm;
|
|
||||||
import org.pgpainless.algorithm.KeyFlag;
|
|
||||||
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
|
||||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
|
||||||
import org.pgpainless.key.util.RevocationAttributes;
|
|
||||||
|
|
||||||
public class SignatureSubpacketGeneratorWrapper
|
|
||||||
implements BaseSignatureSubpackets, SelfSignatureSubpackets, CertificationSubpackets, RevocationSignatureSubpackets {
|
|
||||||
|
|
||||||
private SignatureCreationTime signatureCreationTime;
|
|
||||||
private SignatureExpirationTime signatureExpirationTime;
|
|
||||||
private IssuerKeyID issuerKeyID;
|
|
||||||
private IssuerFingerprint issuerFingerprint;
|
|
||||||
private final List<NotationData> notationDataList = new ArrayList<>();
|
|
||||||
private final List<IntendedRecipientFingerprint> intendedRecipientFingerprintList = new ArrayList<>();
|
|
||||||
private final List<RevocationKey> revocationKeyList = new ArrayList<>();
|
|
||||||
private Exportable exportable;
|
|
||||||
private SignatureTarget signatureTarget;
|
|
||||||
private Features features;
|
|
||||||
private KeyFlags keyFlags;
|
|
||||||
private TrustSignature trust;
|
|
||||||
private PreferredAlgorithms preferredCompressionAlgorithms;
|
|
||||||
private PreferredAlgorithms preferredSymmetricKeyAlgorithms;
|
|
||||||
private PreferredAlgorithms preferredHashAlgorithms;
|
|
||||||
private final List<EmbeddedSignature> embeddedSignatureList = new ArrayList<>();
|
|
||||||
private SignerUserID signerUserId;
|
|
||||||
private KeyExpirationTime keyExpirationTime;
|
|
||||||
private PrimaryUserID primaryUserId;
|
|
||||||
private Revocable revocable;
|
|
||||||
private RevocationReason revocationReason;
|
|
||||||
private final List<SignatureSubpacket> unsupportedSubpackets = new ArrayList<>();
|
|
||||||
|
|
||||||
public SignatureSubpacketGeneratorWrapper() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SignatureSubpacketGeneratorWrapper refreshHashedSubpackets(PGPPublicKey issuer, PGPSignature oldSignature) {
|
|
||||||
return createHashedSubpacketsFrom(issuer, oldSignature.getHashedSubPackets());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SignatureSubpacketGeneratorWrapper refreshUnhashedSubpackets(PGPSignature oldSignature) {
|
|
||||||
return createSubpacketsFrom(oldSignature.getUnhashedSubPackets());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SignatureSubpacketGeneratorWrapper createHashedSubpacketsFrom(PGPPublicKey issuer, PGPSignatureSubpacketVector base) {
|
|
||||||
SignatureSubpacketGeneratorWrapper wrapper = createSubpacketsFrom(base);
|
|
||||||
wrapper.setIssuerFingerprintAndKeyId(issuer);
|
|
||||||
return wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SignatureSubpacketGeneratorWrapper createSubpacketsFrom(PGPSignatureSubpacketVector base) {
|
|
||||||
SignatureSubpacketGeneratorWrapper wrapper = new SignatureSubpacketGeneratorWrapper();
|
|
||||||
wrapper.extractSubpacketsFromVector(base);
|
|
||||||
return wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SignatureSubpacketGeneratorWrapper createEmptySubpackets() {
|
|
||||||
return new SignatureSubpacketGeneratorWrapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SignatureSubpacketGeneratorWrapper createHashedSubpackets() {
|
|
||||||
SignatureSubpacketGeneratorWrapper wrapper = new SignatureSubpacketGeneratorWrapper();
|
|
||||||
wrapper.setSignatureCreationTime(new Date());
|
|
||||||
return wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SignatureSubpacketGeneratorWrapper createHashedSubpackets(PGPPublicKey issuer) {
|
|
||||||
SignatureSubpacketGeneratorWrapper wrapper = createHashedSubpackets();
|
|
||||||
wrapper.setIssuerFingerprintAndKeyId(issuer);
|
|
||||||
return wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void extractSubpacketsFromVector(PGPSignatureSubpacketVector base) {
|
|
||||||
for (SignatureSubpacket subpacket : base.toArray()) {
|
|
||||||
org.pgpainless.algorithm.SignatureSubpacket type = org.pgpainless.algorithm.SignatureSubpacket.fromCode(subpacket.getType());
|
|
||||||
switch (type) {
|
|
||||||
case signatureCreationTime:
|
|
||||||
case issuerKeyId:
|
|
||||||
case issuerFingerprint:
|
|
||||||
// ignore, we override this anyways
|
|
||||||
break;
|
|
||||||
case signatureExpirationTime:
|
|
||||||
SignatureExpirationTime sigExpTime = (SignatureExpirationTime) subpacket;
|
|
||||||
setSignatureExpirationTime(sigExpTime.isCritical(), sigExpTime.getTime());
|
|
||||||
break;
|
|
||||||
case exportableCertification:
|
|
||||||
Exportable exp = (Exportable) subpacket;
|
|
||||||
setExportable(exp.isCritical(), exp.isExportable());
|
|
||||||
break;
|
|
||||||
case trustSignature:
|
|
||||||
TrustSignature trustSignature = (TrustSignature) subpacket;
|
|
||||||
setTrust(trustSignature.isCritical(), trustSignature.getDepth(), trustSignature.getTrustAmount());
|
|
||||||
break;
|
|
||||||
case revocable:
|
|
||||||
Revocable rev = (Revocable) subpacket;
|
|
||||||
setRevocable(rev.isCritical(), rev.isRevocable());
|
|
||||||
break;
|
|
||||||
case keyExpirationTime:
|
|
||||||
KeyExpirationTime keyExpTime = (KeyExpirationTime) subpacket;
|
|
||||||
setKeyExpirationTime(keyExpTime.isCritical(), keyExpTime.getTime());
|
|
||||||
break;
|
|
||||||
case preferredSymmetricAlgorithms:
|
|
||||||
setPreferredSymmetricKeyAlgorithms((PreferredAlgorithms) subpacket);
|
|
||||||
break;
|
|
||||||
case revocationKey:
|
|
||||||
RevocationKey revocationKey = (RevocationKey) subpacket;
|
|
||||||
addRevocationKey(revocationKey);
|
|
||||||
break;
|
|
||||||
case notationData:
|
|
||||||
NotationData notationData = (NotationData) subpacket;
|
|
||||||
addNotationData(notationData.isCritical(), notationData.getNotationName(), notationData.getNotationValue());
|
|
||||||
break;
|
|
||||||
case preferredHashAlgorithms:
|
|
||||||
setPreferredHashAlgorithms((PreferredAlgorithms) subpacket);
|
|
||||||
break;
|
|
||||||
case preferredCompressionAlgorithms:
|
|
||||||
setPreferredCompressionAlgorithms((PreferredAlgorithms) subpacket);
|
|
||||||
break;
|
|
||||||
case primaryUserId:
|
|
||||||
PrimaryUserID primaryUserID = (PrimaryUserID) subpacket;
|
|
||||||
setPrimaryUserId(primaryUserID);
|
|
||||||
break;
|
|
||||||
case keyFlags:
|
|
||||||
KeyFlags flags = (KeyFlags) subpacket;
|
|
||||||
setKeyFlags(flags.isCritical(), KeyFlag.fromBitmask(flags.getFlags()).toArray(new KeyFlag[0]));
|
|
||||||
break;
|
|
||||||
case signerUserId:
|
|
||||||
SignerUserID signerUserID = (SignerUserID) subpacket;
|
|
||||||
setSignerUserId(signerUserID.isCritical(), signerUserID.getID());
|
|
||||||
break;
|
|
||||||
case revocationReason:
|
|
||||||
RevocationReason reason = (RevocationReason) subpacket;
|
|
||||||
setRevocationReason(reason.isCritical(),
|
|
||||||
RevocationAttributes.Reason.fromCode(reason.getRevocationReason()),
|
|
||||||
reason.getRevocationDescription());
|
|
||||||
break;
|
|
||||||
case features:
|
|
||||||
Features f = (Features) subpacket;
|
|
||||||
setFeatures(f.isCritical(), Feature.fromBitmask(f.getData()[0]).toArray(new Feature[0]));
|
|
||||||
break;
|
|
||||||
case signatureTarget:
|
|
||||||
SignatureTarget target = (SignatureTarget) subpacket;
|
|
||||||
setSignatureTarget(target.isCritical(),
|
|
||||||
PublicKeyAlgorithm.fromId(target.getPublicKeyAlgorithm()),
|
|
||||||
HashAlgorithm.fromId(target.getHashAlgorithm()),
|
|
||||||
target.getHashData());
|
|
||||||
break;
|
|
||||||
case embeddedSignature:
|
|
||||||
EmbeddedSignature embeddedSignature = (EmbeddedSignature) subpacket;
|
|
||||||
addEmbeddedSignature(embeddedSignature);
|
|
||||||
break;
|
|
||||||
case intendedRecipientFingerprint:
|
|
||||||
IntendedRecipientFingerprint intendedRecipientFingerprint = (IntendedRecipientFingerprint) subpacket;
|
|
||||||
addIntendedRecipientFingerprint(intendedRecipientFingerprint);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case regularExpression:
|
|
||||||
case keyServerPreferences:
|
|
||||||
case preferredKeyServers:
|
|
||||||
case policyUrl:
|
|
||||||
case placeholder:
|
|
||||||
case preferredAEADAlgorithms:
|
|
||||||
case attestedCertification:
|
|
||||||
unsupportedSubpackets.add(subpacket);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PGPSignatureSubpacketGenerator getGenerator() {
|
|
||||||
PGPSignatureSubpacketGenerator generator = new PGPSignatureSubpacketGenerator();
|
|
||||||
|
|
||||||
addSubpacket(generator, issuerKeyID);
|
|
||||||
addSubpacket(generator, issuerFingerprint);
|
|
||||||
addSubpacket(generator, signatureCreationTime);
|
|
||||||
addSubpacket(generator, signatureExpirationTime);
|
|
||||||
addSubpacket(generator, exportable);
|
|
||||||
for (NotationData notationData : notationDataList) {
|
|
||||||
addSubpacket(generator, notationData);
|
|
||||||
}
|
|
||||||
for (IntendedRecipientFingerprint intendedRecipientFingerprint : intendedRecipientFingerprintList) {
|
|
||||||
addSubpacket(generator, intendedRecipientFingerprint);
|
|
||||||
}
|
|
||||||
for (RevocationKey revocationKey : revocationKeyList) {
|
|
||||||
addSubpacket(generator, revocationKey);
|
|
||||||
}
|
|
||||||
addSubpacket(generator, signatureTarget);
|
|
||||||
addSubpacket(generator, features);
|
|
||||||
addSubpacket(generator, keyFlags);
|
|
||||||
addSubpacket(generator, trust);
|
|
||||||
addSubpacket(generator, preferredCompressionAlgorithms);
|
|
||||||
addSubpacket(generator, preferredSymmetricKeyAlgorithms);
|
|
||||||
addSubpacket(generator, preferredHashAlgorithms);
|
|
||||||
for (EmbeddedSignature embeddedSignature : embeddedSignatureList) {
|
|
||||||
addSubpacket(generator, embeddedSignature);
|
|
||||||
}
|
|
||||||
addSubpacket(generator, signerUserId);
|
|
||||||
addSubpacket(generator, keyExpirationTime);
|
|
||||||
addSubpacket(generator, primaryUserId);
|
|
||||||
addSubpacket(generator, revocable);
|
|
||||||
addSubpacket(generator, revocationReason);
|
|
||||||
for (SignatureSubpacket subpacket : unsupportedSubpackets) {
|
|
||||||
addSubpacket(generator, subpacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
return generator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setIssuerFingerprintAndKeyId(PGPPublicKey key) {
|
|
||||||
setIssuerKeyId(key.getKeyID());
|
|
||||||
setIssuerFingerprint(key);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setIssuerKeyId(long keyId) {
|
|
||||||
return setIssuerKeyId(true, keyId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setIssuerKeyId(boolean isCritical, long keyId) {
|
|
||||||
return setIssuerKeyId(new IssuerKeyID(isCritical, keyId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setIssuerKeyId(@Nullable IssuerKeyID issuerKeyID) {
|
|
||||||
this.issuerKeyID = issuerKeyID;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setIssuerFingerprint(@Nonnull PGPPublicKey key) {
|
|
||||||
return setIssuerFingerprint(true, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setIssuerFingerprint(boolean isCritical, @Nonnull PGPPublicKey key) {
|
|
||||||
return setIssuerFingerprint(new IssuerFingerprint(isCritical, key.getVersion(), key.getFingerprint()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setIssuerFingerprint(@Nullable IssuerFingerprint fingerprint) {
|
|
||||||
this.issuerFingerprint = fingerprint;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setKeyFlags(KeyFlag... keyFlags) {
|
|
||||||
return setKeyFlags(true, keyFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setKeyFlags(boolean isCritical, KeyFlag... keyFlags) {
|
|
||||||
int bitmask = KeyFlag.toBitmask(keyFlags);
|
|
||||||
return setKeyFlags(new KeyFlags(isCritical, bitmask));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setKeyFlags(@Nullable KeyFlags keyFlags) {
|
|
||||||
this.keyFlags = keyFlags;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignatureCreationTime(@Nonnull Date creationTime) {
|
|
||||||
return setSignatureCreationTime(true, creationTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignatureCreationTime(boolean isCritical, @Nonnull Date creationTime) {
|
|
||||||
return setSignatureCreationTime(new SignatureCreationTime(isCritical, creationTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignatureCreationTime(@Nullable SignatureCreationTime signatureCreationTime) {
|
|
||||||
this.signatureCreationTime = signatureCreationTime;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignatureExpirationTime(@Nonnull Date creationTime, @Nonnull Date expirationTime) {
|
|
||||||
return setSignatureExpirationTime(true, creationTime, expirationTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignatureExpirationTime(boolean isCritical, @Nonnull Date creationTime, @Nonnull Date expirationTime) {
|
|
||||||
return setSignatureExpirationTime(isCritical, (expirationTime.getTime() / 1000) - (creationTime.getTime() / 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignatureExpirationTime(boolean isCritical, long seconds) {
|
|
||||||
if (seconds < 0) {
|
|
||||||
throw new IllegalArgumentException("Expiration time cannot be negative.");
|
|
||||||
}
|
|
||||||
return setSignatureExpirationTime(new SignatureExpirationTime(isCritical, seconds));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignatureExpirationTime(@Nullable SignatureExpirationTime expirationTime) {
|
|
||||||
this.signatureExpirationTime = expirationTime;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignerUserId(@Nonnull String userId) {
|
|
||||||
return setSignerUserId(false, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignerUserId(boolean isCritical, @Nonnull String userId) {
|
|
||||||
return setSignerUserId(new SignerUserID(isCritical, userId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignerUserId(@Nullable SignerUserID signerUserId) {
|
|
||||||
this.signerUserId = signerUserId;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPrimaryUserId() {
|
|
||||||
return setPrimaryUserId(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPrimaryUserId(boolean isCritical) {
|
|
||||||
return setPrimaryUserId(new PrimaryUserID(isCritical, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPrimaryUserId(@Nullable PrimaryUserID primaryUserId) {
|
|
||||||
this.primaryUserId = primaryUserId;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setKeyExpirationTime(@Nonnull PGPPublicKey key, @Nonnull Date keyExpirationTime) {
|
|
||||||
return setKeyExpirationTime(key.getCreationTime(), keyExpirationTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setKeyExpirationTime(@Nonnull Date keyCreationTime, @Nonnull Date keyExpirationTime) {
|
|
||||||
return setKeyExpirationTime(true, keyCreationTime, keyExpirationTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setKeyExpirationTime(boolean isCritical, @Nonnull Date keyCreationTime, @Nonnull Date keyExpirationTime) {
|
|
||||||
return setKeyExpirationTime(isCritical, (keyExpirationTime.getTime() / 1000) - (keyCreationTime.getTime() / 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setKeyExpirationTime(boolean isCritical, long secondsFromCreationToExpiration) {
|
|
||||||
if (secondsFromCreationToExpiration < 0) {
|
|
||||||
throw new IllegalArgumentException("Seconds from key creation to expiration cannot be less than 0.");
|
|
||||||
}
|
|
||||||
return setKeyExpirationTime(new KeyExpirationTime(isCritical, secondsFromCreationToExpiration));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setKeyExpirationTime(@Nullable KeyExpirationTime keyExpirationTime) {
|
|
||||||
this.keyExpirationTime = keyExpirationTime;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredCompressionAlgorithms(CompressionAlgorithm... algorithms) {
|
|
||||||
return setPreferredCompressionAlgorithms(new LinkedHashSet<>(Arrays.asList(algorithms)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredCompressionAlgorithms(Set<CompressionAlgorithm> algorithms) {
|
|
||||||
return setPreferredCompressionAlgorithms(true, algorithms);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredCompressionAlgorithms(boolean isCritical, Set<CompressionAlgorithm> algorithms) {
|
|
||||||
int[] ids = new int[algorithms.size()];
|
|
||||||
Iterator<CompressionAlgorithm> iterator = algorithms.iterator();
|
|
||||||
for (int i = 0; i < algorithms.size(); i++) {
|
|
||||||
ids[i] = iterator.next().getAlgorithmId();
|
|
||||||
}
|
|
||||||
return setPreferredCompressionAlgorithms(new PreferredAlgorithms(
|
|
||||||
SignatureSubpacketTags.PREFERRED_COMP_ALGS, isCritical, ids));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredCompressionAlgorithms(@Nullable PreferredAlgorithms algorithms) {
|
|
||||||
if (algorithms == null) {
|
|
||||||
this.preferredCompressionAlgorithms = null;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (algorithms.getType() != SignatureSubpacketTags.PREFERRED_COMP_ALGS) {
|
|
||||||
throw new IllegalArgumentException("Invalid preferred compression algorithms type.");
|
|
||||||
}
|
|
||||||
this.preferredCompressionAlgorithms = algorithms;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredSymmetricKeyAlgorithms(SymmetricKeyAlgorithm... algorithms) {
|
|
||||||
return setPreferredSymmetricKeyAlgorithms(new LinkedHashSet<>(Arrays.asList(algorithms)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredSymmetricKeyAlgorithms(Set<SymmetricKeyAlgorithm> algorithms) {
|
|
||||||
return setPreferredSymmetricKeyAlgorithms(true, algorithms);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredSymmetricKeyAlgorithms(boolean isCritical, Set<SymmetricKeyAlgorithm> algorithms) {
|
|
||||||
int[] ids = new int[algorithms.size()];
|
|
||||||
Iterator<SymmetricKeyAlgorithm> iterator = algorithms.iterator();
|
|
||||||
for (int i = 0; i < algorithms.size(); i++) {
|
|
||||||
ids[i] = iterator.next().getAlgorithmId();
|
|
||||||
}
|
|
||||||
return setPreferredSymmetricKeyAlgorithms(new PreferredAlgorithms(
|
|
||||||
SignatureSubpacketTags.PREFERRED_SYM_ALGS, isCritical, ids));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredSymmetricKeyAlgorithms(@Nullable PreferredAlgorithms algorithms) {
|
|
||||||
if (algorithms == null) {
|
|
||||||
this.preferredSymmetricKeyAlgorithms = null;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (algorithms.getType() != SignatureSubpacketTags.PREFERRED_SYM_ALGS) {
|
|
||||||
throw new IllegalArgumentException("Invalid preferred symmetric key algorithms type.");
|
|
||||||
}
|
|
||||||
this.preferredSymmetricKeyAlgorithms = algorithms;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredHashAlgorithms(HashAlgorithm... algorithms) {
|
|
||||||
return setPreferredHashAlgorithms(new LinkedHashSet<>(Arrays.asList(algorithms)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredHashAlgorithms(Set<HashAlgorithm> algorithms) {
|
|
||||||
return setPreferredHashAlgorithms(true, algorithms);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredHashAlgorithms(boolean isCritical, Set<HashAlgorithm> algorithms) {
|
|
||||||
int[] ids = new int[algorithms.size()];
|
|
||||||
Iterator<HashAlgorithm> iterator = algorithms.iterator();
|
|
||||||
for (int i = 0; i < ids.length; i++) {
|
|
||||||
ids[i] = iterator.next().getAlgorithmId();
|
|
||||||
}
|
|
||||||
return setPreferredHashAlgorithms(new PreferredAlgorithms(
|
|
||||||
SignatureSubpacketTags.PREFERRED_HASH_ALGS, isCritical, ids));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setPreferredHashAlgorithms(@Nullable PreferredAlgorithms algorithms) {
|
|
||||||
if (algorithms == null) {
|
|
||||||
preferredHashAlgorithms = null;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (algorithms.getType() != SignatureSubpacketTags.PREFERRED_HASH_ALGS) {
|
|
||||||
throw new IllegalArgumentException("Invalid preferred hash algorithms type.");
|
|
||||||
}
|
|
||||||
this.preferredHashAlgorithms = algorithms;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addNotationData(boolean isCritical, @Nonnull String notationName, @Nonnull String notationValue) {
|
|
||||||
return addNotationData(isCritical, true, notationName, notationValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addNotationData(boolean isCritical, boolean isHumanReadable, @Nonnull String notationName, @Nonnull String notationValue) {
|
|
||||||
return addNotationData(new NotationData(isCritical, isHumanReadable, notationName, notationValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addNotationData(@Nonnull NotationData notationData) {
|
|
||||||
notationDataList.add(notationData);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper clearNotationData() {
|
|
||||||
notationDataList.clear();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addIntendedRecipientFingerprint(@Nonnull PGPPublicKey recipient) {
|
|
||||||
return addIntendedRecipientFingerprint(false, recipient);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addIntendedRecipientFingerprint(boolean isCritical, @Nonnull PGPPublicKey recipient) {
|
|
||||||
return addIntendedRecipientFingerprint(new IntendedRecipientFingerprint(isCritical, recipient.getVersion(), recipient.getFingerprint()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addIntendedRecipientFingerprint(IntendedRecipientFingerprint intendedRecipientFingerprint) {
|
|
||||||
this.intendedRecipientFingerprintList.add(intendedRecipientFingerprint);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper clearIntendedRecipientFingerprints() {
|
|
||||||
intendedRecipientFingerprintList.clear();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setExportable(boolean isCritical, boolean isExportable) {
|
|
||||||
return setExportable(new Exportable(isCritical, isExportable));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setExportable(@Nullable Exportable exportable) {
|
|
||||||
this.exportable = exportable;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setRevocable(boolean isCritical, boolean isRevocable) {
|
|
||||||
return setRevocable(new Revocable(isCritical, isRevocable));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setRevocable(@Nullable Revocable revocable) {
|
|
||||||
this.revocable = revocable;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addRevocationKey(@Nonnull PGPPublicKey revocationKey) {
|
|
||||||
return addRevocationKey(true, revocationKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addRevocationKey(boolean isCritical, @Nonnull PGPPublicKey revocationKey) {
|
|
||||||
return addRevocationKey(isCritical, false, revocationKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addRevocationKey(boolean isCritical, boolean isSensitive, @Nonnull PGPPublicKey revocationKey) {
|
|
||||||
byte clazz = (byte) 0x80;
|
|
||||||
clazz |= (isSensitive ? 0x40 : 0x00);
|
|
||||||
return addRevocationKey(new RevocationKey(isCritical, clazz, revocationKey.getAlgorithm(), revocationKey.getFingerprint()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addRevocationKey(@Nonnull RevocationKey revocationKey) {
|
|
||||||
this.revocationKeyList.add(revocationKey);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper clearRevocationKeys() {
|
|
||||||
revocationKeyList.clear();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setRevocationReason(RevocationAttributes revocationAttributes) {
|
|
||||||
return setRevocationReason(true, revocationAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setRevocationReason(boolean isCritical, RevocationAttributes revocationAttributes) {
|
|
||||||
return setRevocationReason(isCritical, revocationAttributes.getReason(), revocationAttributes.getDescription());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setRevocationReason(boolean isCritical, RevocationAttributes.Reason reason, @Nonnull String description) {
|
|
||||||
return setRevocationReason(new RevocationReason(isCritical, reason.code(), description));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setRevocationReason(@Nullable RevocationReason reason) {
|
|
||||||
this.revocationReason = reason;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignatureTarget(@Nonnull PublicKeyAlgorithm keyAlgorithm, @Nonnull HashAlgorithm hashAlgorithm, @Nonnull byte[] hashData) {
|
|
||||||
return setSignatureTarget(true, keyAlgorithm, hashAlgorithm, hashData);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignatureTarget(boolean isCritical, @Nonnull PublicKeyAlgorithm keyAlgorithm, @Nonnull HashAlgorithm hashAlgorithm, @Nonnull byte[] hashData) {
|
|
||||||
return setSignatureTarget(new SignatureTarget(isCritical, keyAlgorithm.getAlgorithmId(), hashAlgorithm.getAlgorithmId(), hashData));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setSignatureTarget(@Nullable SignatureTarget signatureTarget) {
|
|
||||||
this.signatureTarget = signatureTarget;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setFeatures(Feature... features) {
|
|
||||||
return setFeatures(true, features);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setFeatures(boolean isCritical, Feature... features) {
|
|
||||||
byte bitmask = Feature.toBitmask(features);
|
|
||||||
return setFeatures(new Features(isCritical, bitmask));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setFeatures(@Nullable Features features) {
|
|
||||||
this.features = features;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setTrust(int depth, int amount) {
|
|
||||||
return setTrust(true, depth, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setTrust(boolean isCritical, int depth, int amount) {
|
|
||||||
return setTrust(new TrustSignature(isCritical, depth, amount));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper setTrust(@Nullable TrustSignature trust) {
|
|
||||||
this.trust = trust;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addEmbeddedSignature(@Nonnull PGPSignature signature) throws IOException {
|
|
||||||
return addEmbeddedSignature(true, signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addEmbeddedSignature(boolean isCritical, @Nonnull PGPSignature signature) throws IOException {
|
|
||||||
byte[] sig = signature.getEncoded();
|
|
||||||
byte[] data;
|
|
||||||
|
|
||||||
if (sig.length - 1 > 256) {
|
|
||||||
data = new byte[sig.length - 3];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data = new byte[sig.length - 2];
|
|
||||||
}
|
|
||||||
|
|
||||||
System.arraycopy(sig, sig.length - data.length, data, 0, data.length);
|
|
||||||
|
|
||||||
return addEmbeddedSignature(new EmbeddedSignature(isCritical, false, data));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper addEmbeddedSignature(@Nonnull EmbeddedSignature embeddedSignature) {
|
|
||||||
this.embeddedSignatureList.add(embeddedSignature);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SignatureSubpacketGeneratorWrapper clearEmbeddedSignatures() {
|
|
||||||
this.embeddedSignatureList.clear();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addSubpacket(PGPSignatureSubpacketGenerator generator, SignatureSubpacket subpacket) {
|
|
||||||
if (subpacket != null) {
|
|
||||||
generator.addCustomSubpacket(subpacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,660 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.signature.subpackets;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.bouncycastle.bcpg.SignatureSubpacket;
|
||||||
|
import org.bouncycastle.bcpg.SignatureSubpacketTags;
|
||||||
|
import org.bouncycastle.bcpg.sig.EmbeddedSignature;
|
||||||
|
import org.bouncycastle.bcpg.sig.Exportable;
|
||||||
|
import org.bouncycastle.bcpg.sig.Features;
|
||||||
|
import org.bouncycastle.bcpg.sig.IntendedRecipientFingerprint;
|
||||||
|
import org.bouncycastle.bcpg.sig.IssuerFingerprint;
|
||||||
|
import org.bouncycastle.bcpg.sig.IssuerKeyID;
|
||||||
|
import org.bouncycastle.bcpg.sig.KeyExpirationTime;
|
||||||
|
import org.bouncycastle.bcpg.sig.KeyFlags;
|
||||||
|
import org.bouncycastle.bcpg.sig.NotationData;
|
||||||
|
import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
|
||||||
|
import org.bouncycastle.bcpg.sig.PrimaryUserID;
|
||||||
|
import org.bouncycastle.bcpg.sig.Revocable;
|
||||||
|
import org.bouncycastle.bcpg.sig.RevocationKey;
|
||||||
|
import org.bouncycastle.bcpg.sig.RevocationReason;
|
||||||
|
import org.bouncycastle.bcpg.sig.SignatureCreationTime;
|
||||||
|
import org.bouncycastle.bcpg.sig.SignatureExpirationTime;
|
||||||
|
import org.bouncycastle.bcpg.sig.SignatureTarget;
|
||||||
|
import org.bouncycastle.bcpg.sig.SignerUserID;
|
||||||
|
import org.bouncycastle.bcpg.sig.TrustSignature;
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
|
import org.pgpainless.algorithm.CompressionAlgorithm;
|
||||||
|
import org.pgpainless.algorithm.Feature;
|
||||||
|
import org.pgpainless.algorithm.HashAlgorithm;
|
||||||
|
import org.pgpainless.algorithm.KeyFlag;
|
||||||
|
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
||||||
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
|
import org.pgpainless.key.util.RevocationAttributes;
|
||||||
|
|
||||||
|
public class SignatureSubpackets
|
||||||
|
implements BaseSignatureSubpackets, SelfSignatureSubpackets, CertificationSubpackets, RevocationSignatureSubpackets {
|
||||||
|
|
||||||
|
private SignatureCreationTime signatureCreationTime;
|
||||||
|
private SignatureExpirationTime signatureExpirationTime;
|
||||||
|
private IssuerKeyID issuerKeyID;
|
||||||
|
private IssuerFingerprint issuerFingerprint;
|
||||||
|
private final List<NotationData> notationDataList = new ArrayList<>();
|
||||||
|
private final List<IntendedRecipientFingerprint> intendedRecipientFingerprintList = new ArrayList<>();
|
||||||
|
private final List<RevocationKey> revocationKeyList = new ArrayList<>();
|
||||||
|
private Exportable exportable;
|
||||||
|
private SignatureTarget signatureTarget;
|
||||||
|
private Features features;
|
||||||
|
private KeyFlags keyFlags;
|
||||||
|
private TrustSignature trust;
|
||||||
|
private PreferredAlgorithms preferredCompressionAlgorithms;
|
||||||
|
private PreferredAlgorithms preferredSymmetricKeyAlgorithms;
|
||||||
|
private PreferredAlgorithms preferredHashAlgorithms;
|
||||||
|
private final List<EmbeddedSignature> embeddedSignatureList = new ArrayList<>();
|
||||||
|
private SignerUserID signerUserId;
|
||||||
|
private KeyExpirationTime keyExpirationTime;
|
||||||
|
private PrimaryUserID primaryUserId;
|
||||||
|
private Revocable revocable;
|
||||||
|
private RevocationReason revocationReason;
|
||||||
|
private final List<SignatureSubpacket> residualSubpackets = new ArrayList<>();
|
||||||
|
|
||||||
|
public SignatureSubpackets() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SignatureSubpackets refreshHashedSubpackets(PGPPublicKey issuer, PGPSignature oldSignature) {
|
||||||
|
return createHashedSubpacketsFrom(issuer, oldSignature.getHashedSubPackets());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SignatureSubpackets refreshUnhashedSubpackets(PGPSignature oldSignature) {
|
||||||
|
return createSubpacketsFrom(oldSignature.getUnhashedSubPackets());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SignatureSubpackets createHashedSubpacketsFrom(PGPPublicKey issuer, PGPSignatureSubpacketVector base) {
|
||||||
|
SignatureSubpackets wrapper = createSubpacketsFrom(base);
|
||||||
|
wrapper.setIssuerFingerprintAndKeyId(issuer);
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SignatureSubpackets createSubpacketsFrom(PGPSignatureSubpacketVector base) {
|
||||||
|
SignatureSubpackets wrapper = new SignatureSubpackets();
|
||||||
|
SignatureSubpacketsHelper.applyFrom(base, wrapper);
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SignatureSubpackets createHashedSubpackets(PGPPublicKey issuer) {
|
||||||
|
SignatureSubpackets wrapper = new SignatureSubpackets();
|
||||||
|
wrapper.setIssuerFingerprintAndKeyId(issuer);
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setIssuerFingerprintAndKeyId(PGPPublicKey key) {
|
||||||
|
setIssuerKeyId(key.getKeyID());
|
||||||
|
setIssuerFingerprint(key);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setIssuerKeyId(long keyId) {
|
||||||
|
return setIssuerKeyId(true, keyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setIssuerKeyId(boolean isCritical, long keyId) {
|
||||||
|
return setIssuerKeyId(new IssuerKeyID(isCritical, keyId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setIssuerKeyId(@Nullable IssuerKeyID issuerKeyID) {
|
||||||
|
this.issuerKeyID = issuerKeyID;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IssuerKeyID getIssuerKeyIdSubpacket() {
|
||||||
|
return issuerKeyID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setIssuerFingerprint(@Nonnull PGPPublicKey key) {
|
||||||
|
return setIssuerFingerprint(true, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setIssuerFingerprint(boolean isCritical, @Nonnull PGPPublicKey key) {
|
||||||
|
return setIssuerFingerprint(new IssuerFingerprint(isCritical, key.getVersion(), key.getFingerprint()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setIssuerFingerprint(@Nullable IssuerFingerprint fingerprint) {
|
||||||
|
this.issuerFingerprint = fingerprint;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IssuerFingerprint getIssuerFingerprintSubpacket() {
|
||||||
|
return issuerFingerprint;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setKeyFlags(KeyFlag... keyFlags) {
|
||||||
|
return setKeyFlags(true, keyFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setKeyFlags(boolean isCritical, KeyFlag... keyFlags) {
|
||||||
|
int bitmask = KeyFlag.toBitmask(keyFlags);
|
||||||
|
return setKeyFlags(new KeyFlags(isCritical, bitmask));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setKeyFlags(@Nullable KeyFlags keyFlags) {
|
||||||
|
this.keyFlags = keyFlags;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyFlags getKeyFlagsSubpacket() {
|
||||||
|
return keyFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignatureCreationTime(@Nonnull Date creationTime) {
|
||||||
|
return setSignatureCreationTime(true, creationTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignatureCreationTime(boolean isCritical, @Nonnull Date creationTime) {
|
||||||
|
return setSignatureCreationTime(new SignatureCreationTime(isCritical, creationTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignatureCreationTime(@Nullable SignatureCreationTime signatureCreationTime) {
|
||||||
|
this.signatureCreationTime = signatureCreationTime;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignatureCreationTime getSignatureCreationTimeSubpacket() {
|
||||||
|
return signatureCreationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignatureExpirationTime(@Nonnull Date creationTime, @Nonnull Date expirationTime) {
|
||||||
|
return setSignatureExpirationTime(true, creationTime, expirationTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignatureExpirationTime(boolean isCritical, @Nonnull Date creationTime, @Nonnull Date expirationTime) {
|
||||||
|
return setSignatureExpirationTime(isCritical, (expirationTime.getTime() / 1000) - (creationTime.getTime() / 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignatureExpirationTime(boolean isCritical, long seconds) {
|
||||||
|
if (seconds < 0) {
|
||||||
|
throw new IllegalArgumentException("Expiration time cannot be negative.");
|
||||||
|
}
|
||||||
|
return setSignatureExpirationTime(new SignatureExpirationTime(isCritical, seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignatureExpirationTime(@Nullable SignatureExpirationTime expirationTime) {
|
||||||
|
this.signatureExpirationTime = expirationTime;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignatureExpirationTime getSignatureExpirationTimeSubpacket() {
|
||||||
|
return signatureExpirationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignerUserId(@Nonnull String userId) {
|
||||||
|
return setSignerUserId(false, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignerUserId(boolean isCritical, @Nonnull String userId) {
|
||||||
|
return setSignerUserId(new SignerUserID(isCritical, userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignerUserId(@Nullable SignerUserID signerUserId) {
|
||||||
|
this.signerUserId = signerUserId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignerUserID getSignerUserIdSubpacket() {
|
||||||
|
return signerUserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPrimaryUserId() {
|
||||||
|
return setPrimaryUserId(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPrimaryUserId(boolean isCritical) {
|
||||||
|
return setPrimaryUserId(new PrimaryUserID(isCritical, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPrimaryUserId(@Nullable PrimaryUserID primaryUserId) {
|
||||||
|
this.primaryUserId = primaryUserId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrimaryUserID getPrimaryUserIdSubpacket() {
|
||||||
|
return primaryUserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setKeyExpirationTime(@Nonnull PGPPublicKey key, @Nonnull Date keyExpirationTime) {
|
||||||
|
return setKeyExpirationTime(key.getCreationTime(), keyExpirationTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setKeyExpirationTime(@Nonnull Date keyCreationTime, @Nonnull Date keyExpirationTime) {
|
||||||
|
return setKeyExpirationTime(true, keyCreationTime, keyExpirationTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setKeyExpirationTime(boolean isCritical, @Nonnull Date keyCreationTime, @Nonnull Date keyExpirationTime) {
|
||||||
|
return setKeyExpirationTime(isCritical, (keyExpirationTime.getTime() / 1000) - (keyCreationTime.getTime() / 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setKeyExpirationTime(boolean isCritical, long secondsFromCreationToExpiration) {
|
||||||
|
if (secondsFromCreationToExpiration < 0) {
|
||||||
|
throw new IllegalArgumentException("Seconds from key creation to expiration cannot be less than 0.");
|
||||||
|
}
|
||||||
|
return setKeyExpirationTime(new KeyExpirationTime(isCritical, secondsFromCreationToExpiration));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setKeyExpirationTime(@Nullable KeyExpirationTime keyExpirationTime) {
|
||||||
|
this.keyExpirationTime = keyExpirationTime;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyExpirationTime getKeyExpirationTimeSubpacket() {
|
||||||
|
return keyExpirationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredCompressionAlgorithms(CompressionAlgorithm... algorithms) {
|
||||||
|
return setPreferredCompressionAlgorithms(new LinkedHashSet<>(Arrays.asList(algorithms)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredCompressionAlgorithms(Set<CompressionAlgorithm> algorithms) {
|
||||||
|
return setPreferredCompressionAlgorithms(true, algorithms);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredCompressionAlgorithms(boolean isCritical, Set<CompressionAlgorithm> algorithms) {
|
||||||
|
int[] ids = new int[algorithms.size()];
|
||||||
|
Iterator<CompressionAlgorithm> iterator = algorithms.iterator();
|
||||||
|
for (int i = 0; i < algorithms.size(); i++) {
|
||||||
|
ids[i] = iterator.next().getAlgorithmId();
|
||||||
|
}
|
||||||
|
return setPreferredCompressionAlgorithms(new PreferredAlgorithms(
|
||||||
|
SignatureSubpacketTags.PREFERRED_COMP_ALGS, isCritical, ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredCompressionAlgorithms(@Nullable PreferredAlgorithms algorithms) {
|
||||||
|
if (algorithms == null) {
|
||||||
|
this.preferredCompressionAlgorithms = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (algorithms.getType() != SignatureSubpacketTags.PREFERRED_COMP_ALGS) {
|
||||||
|
throw new IllegalArgumentException("Invalid preferred compression algorithms type.");
|
||||||
|
}
|
||||||
|
this.preferredCompressionAlgorithms = algorithms;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PreferredAlgorithms getPreferredCompressionAlgorithmsSubpacket() {
|
||||||
|
return preferredCompressionAlgorithms;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredSymmetricKeyAlgorithms(SymmetricKeyAlgorithm... algorithms) {
|
||||||
|
return setPreferredSymmetricKeyAlgorithms(new LinkedHashSet<>(Arrays.asList(algorithms)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredSymmetricKeyAlgorithms(Set<SymmetricKeyAlgorithm> algorithms) {
|
||||||
|
return setPreferredSymmetricKeyAlgorithms(true, algorithms);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredSymmetricKeyAlgorithms(boolean isCritical, Set<SymmetricKeyAlgorithm> algorithms) {
|
||||||
|
int[] ids = new int[algorithms.size()];
|
||||||
|
Iterator<SymmetricKeyAlgorithm> iterator = algorithms.iterator();
|
||||||
|
for (int i = 0; i < algorithms.size(); i++) {
|
||||||
|
ids[i] = iterator.next().getAlgorithmId();
|
||||||
|
}
|
||||||
|
return setPreferredSymmetricKeyAlgorithms(new PreferredAlgorithms(
|
||||||
|
SignatureSubpacketTags.PREFERRED_SYM_ALGS, isCritical, ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredSymmetricKeyAlgorithms(@Nullable PreferredAlgorithms algorithms) {
|
||||||
|
if (algorithms == null) {
|
||||||
|
this.preferredSymmetricKeyAlgorithms = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (algorithms.getType() != SignatureSubpacketTags.PREFERRED_SYM_ALGS) {
|
||||||
|
throw new IllegalArgumentException("Invalid preferred symmetric key algorithms type.");
|
||||||
|
}
|
||||||
|
this.preferredSymmetricKeyAlgorithms = algorithms;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PreferredAlgorithms getPreferredSymmetricKeyAlgorithmsSubpacket() {
|
||||||
|
return preferredSymmetricKeyAlgorithms;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredHashAlgorithms(HashAlgorithm... algorithms) {
|
||||||
|
return setPreferredHashAlgorithms(new LinkedHashSet<>(Arrays.asList(algorithms)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredHashAlgorithms(Set<HashAlgorithm> algorithms) {
|
||||||
|
return setPreferredHashAlgorithms(true, algorithms);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredHashAlgorithms(boolean isCritical, Set<HashAlgorithm> algorithms) {
|
||||||
|
int[] ids = new int[algorithms.size()];
|
||||||
|
Iterator<HashAlgorithm> iterator = algorithms.iterator();
|
||||||
|
for (int i = 0; i < ids.length; i++) {
|
||||||
|
ids[i] = iterator.next().getAlgorithmId();
|
||||||
|
}
|
||||||
|
return setPreferredHashAlgorithms(new PreferredAlgorithms(
|
||||||
|
SignatureSubpacketTags.PREFERRED_HASH_ALGS, isCritical, ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setPreferredHashAlgorithms(@Nullable PreferredAlgorithms algorithms) {
|
||||||
|
if (algorithms == null) {
|
||||||
|
preferredHashAlgorithms = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (algorithms.getType() != SignatureSubpacketTags.PREFERRED_HASH_ALGS) {
|
||||||
|
throw new IllegalArgumentException("Invalid preferred hash algorithms type.");
|
||||||
|
}
|
||||||
|
this.preferredHashAlgorithms = algorithms;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PreferredAlgorithms getPreferredHashAlgorithmsSubpacket() {
|
||||||
|
return preferredHashAlgorithms;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addNotationData(boolean isCritical, @Nonnull String notationName, @Nonnull String notationValue) {
|
||||||
|
return addNotationData(isCritical, true, notationName, notationValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addNotationData(boolean isCritical, boolean isHumanReadable, @Nonnull String notationName, @Nonnull String notationValue) {
|
||||||
|
return addNotationData(new NotationData(isCritical, isHumanReadable, notationName, notationValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addNotationData(@Nonnull NotationData notationData) {
|
||||||
|
notationDataList.add(notationData);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets clearNotationData() {
|
||||||
|
notationDataList.clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<NotationData> getNotationDataSubpackets() {
|
||||||
|
return new ArrayList<>(notationDataList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addIntendedRecipientFingerprint(@Nonnull PGPPublicKey recipient) {
|
||||||
|
return addIntendedRecipientFingerprint(false, recipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addIntendedRecipientFingerprint(boolean isCritical, @Nonnull PGPPublicKey recipient) {
|
||||||
|
return addIntendedRecipientFingerprint(new IntendedRecipientFingerprint(isCritical, recipient.getVersion(), recipient.getFingerprint()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addIntendedRecipientFingerprint(IntendedRecipientFingerprint intendedRecipientFingerprint) {
|
||||||
|
this.intendedRecipientFingerprintList.add(intendedRecipientFingerprint);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets clearIntendedRecipientFingerprints() {
|
||||||
|
intendedRecipientFingerprintList.clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IntendedRecipientFingerprint> getIntendedRecipientFingerprintSubpackets() {
|
||||||
|
return new ArrayList<>(intendedRecipientFingerprintList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setExportable(boolean isCritical, boolean isExportable) {
|
||||||
|
return setExportable(new Exportable(isCritical, isExportable));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setExportable(@Nullable Exportable exportable) {
|
||||||
|
this.exportable = exportable;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exportable getExportableSubpacket() {
|
||||||
|
return exportable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setRevocable(boolean isCritical, boolean isRevocable) {
|
||||||
|
return setRevocable(new Revocable(isCritical, isRevocable));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setRevocable(@Nullable Revocable revocable) {
|
||||||
|
this.revocable = revocable;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Revocable getRevocableSubpacket() {
|
||||||
|
return revocable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addRevocationKey(@Nonnull PGPPublicKey revocationKey) {
|
||||||
|
return addRevocationKey(true, revocationKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addRevocationKey(boolean isCritical, @Nonnull PGPPublicKey revocationKey) {
|
||||||
|
return addRevocationKey(isCritical, false, revocationKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addRevocationKey(boolean isCritical, boolean isSensitive, @Nonnull PGPPublicKey revocationKey) {
|
||||||
|
byte clazz = (byte) 0x80;
|
||||||
|
clazz |= (isSensitive ? 0x40 : 0x00);
|
||||||
|
return addRevocationKey(new RevocationKey(isCritical, clazz, revocationKey.getAlgorithm(), revocationKey.getFingerprint()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addRevocationKey(@Nonnull RevocationKey revocationKey) {
|
||||||
|
this.revocationKeyList.add(revocationKey);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets clearRevocationKeys() {
|
||||||
|
revocationKeyList.clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RevocationKey> getRevocationKeySubpackets() {
|
||||||
|
return new ArrayList<>(revocationKeyList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setRevocationReason(RevocationAttributes revocationAttributes) {
|
||||||
|
return setRevocationReason(true, revocationAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setRevocationReason(boolean isCritical, RevocationAttributes revocationAttributes) {
|
||||||
|
return setRevocationReason(isCritical, revocationAttributes.getReason(), revocationAttributes.getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setRevocationReason(boolean isCritical, RevocationAttributes.Reason reason, @Nonnull String description) {
|
||||||
|
return setRevocationReason(new RevocationReason(isCritical, reason.code(), description));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setRevocationReason(@Nullable RevocationReason reason) {
|
||||||
|
this.revocationReason = reason;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RevocationReason getRevocationReasonSubpacket() {
|
||||||
|
return revocationReason;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignatureTarget(@Nonnull PublicKeyAlgorithm keyAlgorithm, @Nonnull HashAlgorithm hashAlgorithm, @Nonnull byte[] hashData) {
|
||||||
|
return setSignatureTarget(true, keyAlgorithm, hashAlgorithm, hashData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignatureTarget(boolean isCritical, @Nonnull PublicKeyAlgorithm keyAlgorithm, @Nonnull HashAlgorithm hashAlgorithm, @Nonnull byte[] hashData) {
|
||||||
|
return setSignatureTarget(new SignatureTarget(isCritical, keyAlgorithm.getAlgorithmId(), hashAlgorithm.getAlgorithmId(), hashData));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setSignatureTarget(@Nullable SignatureTarget signatureTarget) {
|
||||||
|
this.signatureTarget = signatureTarget;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignatureTarget getSignatureTargetSubpacket() {
|
||||||
|
return signatureTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setFeatures(Feature... features) {
|
||||||
|
return setFeatures(true, features);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setFeatures(boolean isCritical, Feature... features) {
|
||||||
|
byte bitmask = Feature.toBitmask(features);
|
||||||
|
return setFeatures(new Features(isCritical, bitmask));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setFeatures(@Nullable Features features) {
|
||||||
|
this.features = features;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Features getFeaturesSubpacket() {
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setTrust(int depth, int amount) {
|
||||||
|
return setTrust(true, depth, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setTrust(boolean isCritical, int depth, int amount) {
|
||||||
|
return setTrust(new TrustSignature(isCritical, depth, amount));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets setTrust(@Nullable TrustSignature trust) {
|
||||||
|
this.trust = trust;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrustSignature getTrustSubpacket() {
|
||||||
|
return trust;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addEmbeddedSignature(@Nonnull PGPSignature signature) throws IOException {
|
||||||
|
return addEmbeddedSignature(true, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addEmbeddedSignature(boolean isCritical, @Nonnull PGPSignature signature) throws IOException {
|
||||||
|
byte[] sig = signature.getEncoded();
|
||||||
|
byte[] data;
|
||||||
|
|
||||||
|
if (sig.length - 1 > 256) {
|
||||||
|
data = new byte[sig.length - 3];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data = new byte[sig.length - 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(sig, sig.length - data.length, data, 0, data.length);
|
||||||
|
|
||||||
|
return addEmbeddedSignature(new EmbeddedSignature(isCritical, false, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets addEmbeddedSignature(@Nonnull EmbeddedSignature embeddedSignature) {
|
||||||
|
this.embeddedSignatureList.add(embeddedSignature);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SignatureSubpackets clearEmbeddedSignatures() {
|
||||||
|
this.embeddedSignatureList.clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EmbeddedSignature> getEmbeddedSignatureSubpackets() {
|
||||||
|
return new ArrayList<>(embeddedSignatureList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignatureSubpackets addResidualSubpacket(SignatureSubpacket subpacket) {
|
||||||
|
this.residualSubpackets.add(subpacket);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SignatureSubpacket> getResidualSubpackets() {
|
||||||
|
return new ArrayList<>(residualSubpackets);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,180 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.signature.subpackets;
|
||||||
|
|
||||||
|
import org.bouncycastle.bcpg.SignatureSubpacket;
|
||||||
|
import org.bouncycastle.bcpg.sig.EmbeddedSignature;
|
||||||
|
import org.bouncycastle.bcpg.sig.Exportable;
|
||||||
|
import org.bouncycastle.bcpg.sig.Features;
|
||||||
|
import org.bouncycastle.bcpg.sig.IntendedRecipientFingerprint;
|
||||||
|
import org.bouncycastle.bcpg.sig.KeyExpirationTime;
|
||||||
|
import org.bouncycastle.bcpg.sig.KeyFlags;
|
||||||
|
import org.bouncycastle.bcpg.sig.NotationData;
|
||||||
|
import org.bouncycastle.bcpg.sig.PreferredAlgorithms;
|
||||||
|
import org.bouncycastle.bcpg.sig.PrimaryUserID;
|
||||||
|
import org.bouncycastle.bcpg.sig.Revocable;
|
||||||
|
import org.bouncycastle.bcpg.sig.RevocationKey;
|
||||||
|
import org.bouncycastle.bcpg.sig.RevocationReason;
|
||||||
|
import org.bouncycastle.bcpg.sig.SignatureExpirationTime;
|
||||||
|
import org.bouncycastle.bcpg.sig.SignatureTarget;
|
||||||
|
import org.bouncycastle.bcpg.sig.SignerUserID;
|
||||||
|
import org.bouncycastle.bcpg.sig.TrustSignature;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
|
import org.pgpainless.algorithm.Feature;
|
||||||
|
import org.pgpainless.algorithm.HashAlgorithm;
|
||||||
|
import org.pgpainless.algorithm.KeyFlag;
|
||||||
|
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
||||||
|
import org.pgpainless.key.util.RevocationAttributes;
|
||||||
|
|
||||||
|
public class SignatureSubpacketsHelper {
|
||||||
|
|
||||||
|
public static SignatureSubpackets applyFrom(PGPSignatureSubpacketVector vector, SignatureSubpackets subpackets) {
|
||||||
|
for (SignatureSubpacket subpacket : vector.toArray()) {
|
||||||
|
org.pgpainless.algorithm.SignatureSubpacket type = org.pgpainless.algorithm.SignatureSubpacket.fromCode(subpacket.getType());
|
||||||
|
switch (type) {
|
||||||
|
case signatureCreationTime:
|
||||||
|
case issuerKeyId:
|
||||||
|
case issuerFingerprint:
|
||||||
|
// ignore, we override this anyways
|
||||||
|
break;
|
||||||
|
case signatureExpirationTime:
|
||||||
|
SignatureExpirationTime sigExpTime = (SignatureExpirationTime) subpacket;
|
||||||
|
subpackets.setSignatureExpirationTime(sigExpTime.isCritical(), sigExpTime.getTime());
|
||||||
|
break;
|
||||||
|
case exportableCertification:
|
||||||
|
Exportable exp = (Exportable) subpacket;
|
||||||
|
subpackets.setExportable(exp.isCritical(), exp.isExportable());
|
||||||
|
break;
|
||||||
|
case trustSignature:
|
||||||
|
TrustSignature trustSignature = (TrustSignature) subpacket;
|
||||||
|
subpackets.setTrust(trustSignature.isCritical(), trustSignature.getDepth(), trustSignature.getTrustAmount());
|
||||||
|
break;
|
||||||
|
case revocable:
|
||||||
|
Revocable rev = (Revocable) subpacket;
|
||||||
|
subpackets.setRevocable(rev.isCritical(), rev.isRevocable());
|
||||||
|
break;
|
||||||
|
case keyExpirationTime:
|
||||||
|
KeyExpirationTime keyExpTime = (KeyExpirationTime) subpacket;
|
||||||
|
subpackets.setKeyExpirationTime(keyExpTime.isCritical(), keyExpTime.getTime());
|
||||||
|
break;
|
||||||
|
case preferredSymmetricAlgorithms:
|
||||||
|
subpackets.setPreferredSymmetricKeyAlgorithms((PreferredAlgorithms) subpacket);
|
||||||
|
break;
|
||||||
|
case revocationKey:
|
||||||
|
RevocationKey revocationKey = (RevocationKey) subpacket;
|
||||||
|
subpackets.addRevocationKey(revocationKey);
|
||||||
|
break;
|
||||||
|
case notationData:
|
||||||
|
NotationData notationData = (NotationData) subpacket;
|
||||||
|
subpackets.addNotationData(notationData.isCritical(), notationData.getNotationName(), notationData.getNotationValue());
|
||||||
|
break;
|
||||||
|
case preferredHashAlgorithms:
|
||||||
|
subpackets.setPreferredHashAlgorithms((PreferredAlgorithms) subpacket);
|
||||||
|
break;
|
||||||
|
case preferredCompressionAlgorithms:
|
||||||
|
subpackets.setPreferredCompressionAlgorithms((PreferredAlgorithms) subpacket);
|
||||||
|
break;
|
||||||
|
case primaryUserId:
|
||||||
|
PrimaryUserID primaryUserID = (PrimaryUserID) subpacket;
|
||||||
|
subpackets.setPrimaryUserId(primaryUserID);
|
||||||
|
break;
|
||||||
|
case keyFlags:
|
||||||
|
KeyFlags flags = (KeyFlags) subpacket;
|
||||||
|
subpackets.setKeyFlags(flags.isCritical(), KeyFlag.fromBitmask(flags.getFlags()).toArray(new KeyFlag[0]));
|
||||||
|
break;
|
||||||
|
case signerUserId:
|
||||||
|
SignerUserID signerUserID = (SignerUserID) subpacket;
|
||||||
|
subpackets.setSignerUserId(signerUserID.isCritical(), signerUserID.getID());
|
||||||
|
break;
|
||||||
|
case revocationReason:
|
||||||
|
RevocationReason reason = (RevocationReason) subpacket;
|
||||||
|
subpackets.setRevocationReason(reason.isCritical(),
|
||||||
|
RevocationAttributes.Reason.fromCode(reason.getRevocationReason()),
|
||||||
|
reason.getRevocationDescription());
|
||||||
|
break;
|
||||||
|
case features:
|
||||||
|
Features f = (Features) subpacket;
|
||||||
|
subpackets.setFeatures(f.isCritical(), Feature.fromBitmask(f.getData()[0]).toArray(new Feature[0]));
|
||||||
|
break;
|
||||||
|
case signatureTarget:
|
||||||
|
SignatureTarget target = (SignatureTarget) subpacket;
|
||||||
|
subpackets.setSignatureTarget(target.isCritical(),
|
||||||
|
PublicKeyAlgorithm.fromId(target.getPublicKeyAlgorithm()),
|
||||||
|
HashAlgorithm.fromId(target.getHashAlgorithm()),
|
||||||
|
target.getHashData());
|
||||||
|
break;
|
||||||
|
case embeddedSignature:
|
||||||
|
EmbeddedSignature embeddedSignature = (EmbeddedSignature) subpacket;
|
||||||
|
subpackets.addEmbeddedSignature(embeddedSignature);
|
||||||
|
break;
|
||||||
|
case intendedRecipientFingerprint:
|
||||||
|
IntendedRecipientFingerprint intendedRecipientFingerprint = (IntendedRecipientFingerprint) subpacket;
|
||||||
|
subpackets.addIntendedRecipientFingerprint(intendedRecipientFingerprint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case regularExpression:
|
||||||
|
case keyServerPreferences:
|
||||||
|
case preferredKeyServers:
|
||||||
|
case policyUrl:
|
||||||
|
case placeholder:
|
||||||
|
case preferredAEADAlgorithms:
|
||||||
|
case attestedCertification:
|
||||||
|
subpackets.addResidualSubpacket(subpacket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return subpackets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PGPSignatureSubpacketGenerator applyTo(SignatureSubpackets subpackets, PGPSignatureSubpacketGenerator generator) {
|
||||||
|
addSubpacket(generator, subpackets.getIssuerKeyIdSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getIssuerFingerprintSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getSignatureCreationTimeSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getSignatureExpirationTimeSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getExportableSubpacket());
|
||||||
|
for (NotationData notationData : subpackets.getNotationDataSubpackets()) {
|
||||||
|
addSubpacket(generator, notationData);
|
||||||
|
}
|
||||||
|
for (IntendedRecipientFingerprint intendedRecipientFingerprint : subpackets.getIntendedRecipientFingerprintSubpackets()) {
|
||||||
|
addSubpacket(generator, intendedRecipientFingerprint);
|
||||||
|
}
|
||||||
|
for (RevocationKey revocationKey : subpackets.getRevocationKeySubpackets()) {
|
||||||
|
addSubpacket(generator, revocationKey);
|
||||||
|
}
|
||||||
|
addSubpacket(generator, subpackets.getSignatureTargetSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getFeaturesSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getKeyFlagsSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getTrustSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getPreferredCompressionAlgorithmsSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getPreferredSymmetricKeyAlgorithmsSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getPreferredHashAlgorithmsSubpacket());
|
||||||
|
for (EmbeddedSignature embeddedSignature : subpackets.getEmbeddedSignatureSubpackets()) {
|
||||||
|
addSubpacket(generator, embeddedSignature);
|
||||||
|
}
|
||||||
|
addSubpacket(generator, subpackets.getSignerUserIdSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getKeyExpirationTimeSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getPrimaryUserIdSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getRevocableSubpacket());
|
||||||
|
addSubpacket(generator, subpackets.getRevocationReasonSubpacket());
|
||||||
|
for (SignatureSubpacket subpacket : subpackets.getResidualSubpackets()) {
|
||||||
|
addSubpacket(generator, subpacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addSubpacket(PGPSignatureSubpacketGenerator generator, SignatureSubpacket subpacket) {
|
||||||
|
if (subpacket != null) {
|
||||||
|
generator.addCustomSubpacket(subpacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PGPSignatureSubpacketVector toVector(SignatureSubpackets subpackets) {
|
||||||
|
PGPSignatureSubpacketGenerator generator = new PGPSignatureSubpacketGenerator();
|
||||||
|
applyTo(subpackets, generator);
|
||||||
|
return generator.generate();
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,12 +57,12 @@ import org.pgpainless.key.util.RevocationAttributes;
|
||||||
import org.pgpainless.util.DateUtil;
|
import org.pgpainless.util.DateUtil;
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
|
|
||||||
public class SignatureSubpacketGeneratorWrapperTest {
|
public class SignatureSubpacketsTest {
|
||||||
|
|
||||||
private static PGPPublicKeyRing keys;
|
private static PGPPublicKeyRing keys;
|
||||||
private static PGPPublicKey key;
|
private static PGPPublicKey key;
|
||||||
|
|
||||||
private SignatureSubpacketGeneratorWrapper wrapper;
|
private SignatureSubpackets wrapper;
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void setup() throws IOException {
|
public static void setup() throws IOException {
|
||||||
|
@ -72,27 +72,24 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void createWrapper() {
|
public void createWrapper() {
|
||||||
wrapper = SignatureSubpacketGeneratorWrapper.createHashedSubpackets(key);
|
wrapper = SignatureSubpackets.createHashedSubpackets(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void initialStateTest() {
|
public void initialStateTest() {
|
||||||
Date now = new Date();
|
wrapper = new SignatureSubpackets();
|
||||||
wrapper = SignatureSubpacketGeneratorWrapper.createHashedSubpackets();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
assertNull(vector.getSignatureCreationTime());
|
||||||
|
|
||||||
assertEquals(now.getTime(), vector.getSignatureCreationTime().getTime(), 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void initialStateFromKeyTest() throws PGPException {
|
public void initialStateFromKeyTest() throws PGPException {
|
||||||
Date now = new Date();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
|
||||||
|
|
||||||
assertEquals(key.getKeyID(), vector.getIssuerKeyID());
|
assertEquals(key.getKeyID(), vector.getIssuerKeyID());
|
||||||
assertEquals(key.getVersion(), vector.getIssuerFingerprint().getKeyVersion());
|
assertEquals(key.getVersion(), vector.getIssuerFingerprint().getKeyVersion());
|
||||||
assertArrayEquals(key.getFingerprint(), vector.getIssuerFingerprint().getFingerprint());
|
assertArrayEquals(key.getFingerprint(), vector.getIssuerFingerprint().getFingerprint());
|
||||||
assertEquals(now.getTime(), vector.getSignatureCreationTime().getTime(), 2000);
|
assertNull(vector.getSignatureCreationTime());
|
||||||
|
|
||||||
assertEquals(0, vector.getKeyFlags());
|
assertEquals(0, vector.getKeyFlags());
|
||||||
assertEquals(0, vector.getSignatureExpirationTime());
|
assertEquals(0, vector.getSignatureExpirationTime());
|
||||||
|
@ -116,7 +113,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
@Test
|
@Test
|
||||||
public void testNullKeyId() {
|
public void testNullKeyId() {
|
||||||
wrapper.setIssuerKeyId(null);
|
wrapper.setIssuerKeyId(null);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
assertEquals(0, vector.getIssuerKeyID());
|
assertEquals(0, vector.getIssuerKeyID());
|
||||||
}
|
}
|
||||||
|
@ -125,7 +122,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
@Test
|
@Test
|
||||||
public void testNullFingerprint() {
|
public void testNullFingerprint() {
|
||||||
wrapper.setIssuerFingerprint((IssuerFingerprint) null);
|
wrapper.setIssuerFingerprint((IssuerFingerprint) null);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
assertNull(vector.getIssuerFingerprint());
|
assertNull(vector.getIssuerFingerprint());
|
||||||
}
|
}
|
||||||
|
@ -134,7 +131,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
public void testAddNotationData() {
|
public void testAddNotationData() {
|
||||||
wrapper.addNotationData(true, "critical@notation.data", "isCritical");
|
wrapper.addNotationData(true, "critical@notation.data", "isCritical");
|
||||||
wrapper.addNotationData(false, "noncrit@notation.data", "notCritical");
|
wrapper.addNotationData(false, "noncrit@notation.data", "notCritical");
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
NotationData[] notationData = vector.getNotationDataOccurrences();
|
NotationData[] notationData = vector.getNotationDataOccurrences();
|
||||||
assertEquals(2, notationData.length);
|
assertEquals(2, notationData.length);
|
||||||
|
@ -151,7 +148,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
assertEquals("notCritical", second.getNotationValue());
|
assertEquals("notCritical", second.getNotationValue());
|
||||||
|
|
||||||
wrapper.clearNotationData();
|
wrapper.clearNotationData();
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertEquals(0, vector.getNotationDataOccurrences().length);
|
assertEquals(0, vector.getNotationDataOccurrences().length);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -159,14 +156,14 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
@Test
|
@Test
|
||||||
public void testIntendedRecipientFingerprints() {
|
public void testIntendedRecipientFingerprints() {
|
||||||
wrapper.addIntendedRecipientFingerprint(key);
|
wrapper.addIntendedRecipientFingerprint(key);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
assertEquals(1, vector.getSubpackets(SignatureSubpacketTags.INTENDED_RECIPIENT_FINGERPRINT).length);
|
assertEquals(1, vector.getSubpackets(SignatureSubpacketTags.INTENDED_RECIPIENT_FINGERPRINT).length);
|
||||||
assertArrayEquals(key.getFingerprint(), vector.getIntendedRecipientFingerprint().getFingerprint());
|
assertArrayEquals(key.getFingerprint(), vector.getIntendedRecipientFingerprint().getFingerprint());
|
||||||
assertEquals(key.getVersion(), vector.getIntendedRecipientFingerprint().getKeyVersion());
|
assertEquals(key.getVersion(), vector.getIntendedRecipientFingerprint().getKeyVersion());
|
||||||
|
|
||||||
wrapper.clearIntendedRecipientFingerprints();
|
wrapper.clearIntendedRecipientFingerprints();
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertEquals(0, vector.getSubpackets(SignatureSubpacketTags.INTENDED_RECIPIENT_FINGERPRINT).length);
|
assertEquals(0, vector.getSubpackets(SignatureSubpacketTags.INTENDED_RECIPIENT_FINGERPRINT).length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +175,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
assertTrue(keyIterator.hasNext());
|
assertTrue(keyIterator.hasNext());
|
||||||
PGPPublicKey second = keyIterator.next();
|
PGPPublicKey second = keyIterator.next();
|
||||||
wrapper.addRevocationKey(false, true, second);
|
wrapper.addRevocationKey(false, true, second);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
SignatureSubpacket[] revKeys = vector.getSubpackets(SignatureSubpacketTags.REVOCATION_KEY);
|
SignatureSubpacket[] revKeys = vector.getSubpackets(SignatureSubpacketTags.REVOCATION_KEY);
|
||||||
assertEquals(2, revKeys.length);
|
assertEquals(2, revKeys.length);
|
||||||
|
@ -196,14 +193,14 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
assertEquals((byte) (0x80 | 0x40), r2.getSignatureClass());
|
assertEquals((byte) (0x80 | 0x40), r2.getSignatureClass());
|
||||||
|
|
||||||
wrapper.clearRevocationKeys();
|
wrapper.clearRevocationKeys();
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertEquals(0, vector.getSubpackets(SignatureSubpacketTags.REVOCATION_KEY).length);
|
assertEquals(0, vector.getSubpackets(SignatureSubpacketTags.REVOCATION_KEY).length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetKeyFlags() {
|
public void testSetKeyFlags() {
|
||||||
wrapper.setKeyFlags(KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA); // duplicates are removed
|
wrapper.setKeyFlags(KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA); // duplicates are removed
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
assertEquals(KeyFlag.toBitmask(KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER), vector.getKeyFlags());
|
assertEquals(KeyFlag.toBitmask(KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER), vector.getKeyFlags());
|
||||||
assertTrue(vector.getSubpacket(SignatureSubpacketTags.KEY_FLAGS).isCritical());
|
assertTrue(vector.getSubpacket(SignatureSubpacketTags.KEY_FLAGS).isCritical());
|
||||||
|
@ -215,7 +212,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
long secondsInAWeek = 60 * 60 * 24 * 7;
|
long secondsInAWeek = 60 * 60 * 24 * 7;
|
||||||
Date inAWeek = new Date(now.getTime() + 1000 * secondsInAWeek);
|
Date inAWeek = new Date(now.getTime() + 1000 * secondsInAWeek);
|
||||||
wrapper.setSignatureExpirationTime(now, inAWeek);
|
wrapper.setSignatureExpirationTime(now, inAWeek);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
assertEquals(secondsInAWeek, vector.getSignatureExpirationTime());
|
assertEquals(secondsInAWeek, vector.getSignatureExpirationTime());
|
||||||
}
|
}
|
||||||
|
@ -232,17 +229,19 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
public void testSignerUserId() {
|
public void testSignerUserId() {
|
||||||
String userId = "Alice <alice@pgpainless.org>";
|
String userId = "Alice <alice@pgpainless.org>";
|
||||||
wrapper.setSignerUserId(userId);
|
wrapper.setSignerUserId(userId);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
assertEquals(userId, vector.getSignerUserID());
|
assertEquals(userId, vector.getSignerUserID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetPrimaryUserId() {
|
public void testSetPrimaryUserId() {
|
||||||
assertFalse(wrapper.getGenerator().generate().isPrimaryUserID());
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
assertFalse(vector.isPrimaryUserID());
|
||||||
|
|
||||||
wrapper.setPrimaryUserId();
|
wrapper.setPrimaryUserId();
|
||||||
assertTrue(wrapper.getGenerator().generate().isPrimaryUserID());
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
assertTrue(vector.isPrimaryUserID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -250,7 +249,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
long secondsSinceKeyCreation = (now.getTime() - key.getCreationTime().getTime()) / 1000;
|
long secondsSinceKeyCreation = (now.getTime() - key.getCreationTime().getTime()) / 1000;
|
||||||
wrapper.setKeyExpirationTime(key, now);
|
wrapper.setKeyExpirationTime(key, now);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
assertEquals(secondsSinceKeyCreation, vector.getKeyExpirationTime());
|
assertEquals(secondsSinceKeyCreation, vector.getKeyExpirationTime());
|
||||||
}
|
}
|
||||||
|
@ -264,7 +263,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSetPreferredCompressionAlgorithms() {
|
public void testSetPreferredCompressionAlgorithms() {
|
||||||
wrapper.setPreferredCompressionAlgorithms(CompressionAlgorithm.BZIP2, CompressionAlgorithm.ZIP, CompressionAlgorithm.BZIP2); // duplicates get removed
|
wrapper.setPreferredCompressionAlgorithms(CompressionAlgorithm.BZIP2, CompressionAlgorithm.ZIP, CompressionAlgorithm.BZIP2); // duplicates get removed
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
int[] ids = vector.getPreferredCompressionAlgorithms();
|
int[] ids = vector.getPreferredCompressionAlgorithms();
|
||||||
assertEquals(2, ids.length);
|
assertEquals(2, ids.length);
|
||||||
|
@ -272,11 +271,11 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
assertEquals(CompressionAlgorithm.ZIP.getAlgorithmId(), ids[1]);
|
assertEquals(CompressionAlgorithm.ZIP.getAlgorithmId(), ids[1]);
|
||||||
|
|
||||||
wrapper.setPreferredCompressionAlgorithms(); // empty
|
wrapper.setPreferredCompressionAlgorithms(); // empty
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertEquals(0, vector.getPreferredCompressionAlgorithms().length);
|
assertEquals(0, vector.getPreferredCompressionAlgorithms().length);
|
||||||
|
|
||||||
wrapper.setPreferredCompressionAlgorithms((PreferredAlgorithms) null);
|
wrapper.setPreferredCompressionAlgorithms((PreferredAlgorithms) null);
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertNull(vector.getPreferredCompressionAlgorithms());
|
assertNull(vector.getPreferredCompressionAlgorithms());
|
||||||
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> wrapper.setPreferredCompressionAlgorithms(
|
assertThrows(IllegalArgumentException.class, () -> wrapper.setPreferredCompressionAlgorithms(
|
||||||
|
@ -286,7 +285,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSetPreferredSymmetricKeyAlgorithms() {
|
public void testSetPreferredSymmetricKeyAlgorithms() {
|
||||||
wrapper.setPreferredSymmetricKeyAlgorithms(SymmetricKeyAlgorithm.AES_192, SymmetricKeyAlgorithm.AES_128, SymmetricKeyAlgorithm.AES_128); // duplicates get removed
|
wrapper.setPreferredSymmetricKeyAlgorithms(SymmetricKeyAlgorithm.AES_192, SymmetricKeyAlgorithm.AES_128, SymmetricKeyAlgorithm.AES_128); // duplicates get removed
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
int[] ids = vector.getPreferredSymmetricAlgorithms();
|
int[] ids = vector.getPreferredSymmetricAlgorithms();
|
||||||
assertEquals(2, ids.length);
|
assertEquals(2, ids.length);
|
||||||
|
@ -294,11 +293,11 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
assertEquals(SymmetricKeyAlgorithm.AES_128.getAlgorithmId(), ids[1]);
|
assertEquals(SymmetricKeyAlgorithm.AES_128.getAlgorithmId(), ids[1]);
|
||||||
|
|
||||||
wrapper.setPreferredSymmetricKeyAlgorithms(); // empty
|
wrapper.setPreferredSymmetricKeyAlgorithms(); // empty
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertEquals(0, vector.getPreferredSymmetricAlgorithms().length);
|
assertEquals(0, vector.getPreferredSymmetricAlgorithms().length);
|
||||||
|
|
||||||
wrapper.setPreferredSymmetricKeyAlgorithms((PreferredAlgorithms) null);
|
wrapper.setPreferredSymmetricKeyAlgorithms((PreferredAlgorithms) null);
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertNull(vector.getPreferredCompressionAlgorithms());
|
assertNull(vector.getPreferredCompressionAlgorithms());
|
||||||
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> wrapper.setPreferredSymmetricKeyAlgorithms(
|
assertThrows(IllegalArgumentException.class, () -> wrapper.setPreferredSymmetricKeyAlgorithms(
|
||||||
|
@ -308,7 +307,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSetPreferredHashAlgorithms() {
|
public void testSetPreferredHashAlgorithms() {
|
||||||
wrapper.setPreferredHashAlgorithms(HashAlgorithm.SHA512, HashAlgorithm.SHA384, HashAlgorithm.SHA512); // duplicates get removed
|
wrapper.setPreferredHashAlgorithms(HashAlgorithm.SHA512, HashAlgorithm.SHA384, HashAlgorithm.SHA512); // duplicates get removed
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
int[] ids = vector.getPreferredHashAlgorithms();
|
int[] ids = vector.getPreferredHashAlgorithms();
|
||||||
assertEquals(2, ids.length);
|
assertEquals(2, ids.length);
|
||||||
|
@ -316,11 +315,11 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
assertEquals(HashAlgorithm.SHA384.getAlgorithmId(), ids[1]);
|
assertEquals(HashAlgorithm.SHA384.getAlgorithmId(), ids[1]);
|
||||||
|
|
||||||
wrapper.setPreferredHashAlgorithms(); // empty
|
wrapper.setPreferredHashAlgorithms(); // empty
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertEquals(0, vector.getPreferredHashAlgorithms().length);
|
assertEquals(0, vector.getPreferredHashAlgorithms().length);
|
||||||
|
|
||||||
wrapper.setPreferredHashAlgorithms((PreferredAlgorithms) null);
|
wrapper.setPreferredHashAlgorithms((PreferredAlgorithms) null);
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertNull(vector.getPreferredHashAlgorithms());
|
assertNull(vector.getPreferredHashAlgorithms());
|
||||||
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> wrapper.setPreferredHashAlgorithms(
|
assertThrows(IllegalArgumentException.class, () -> wrapper.setPreferredHashAlgorithms(
|
||||||
|
@ -330,14 +329,14 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSetExportable() {
|
public void testSetExportable() {
|
||||||
wrapper.setExportable(true, false);
|
wrapper.setExportable(true, false);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
Exportable exportable = (Exportable) vector.getSubpacket(SignatureSubpacketTags.EXPORTABLE);
|
Exportable exportable = (Exportable) vector.getSubpacket(SignatureSubpacketTags.EXPORTABLE);
|
||||||
assertTrue(exportable.isCritical());
|
assertTrue(exportable.isCritical());
|
||||||
assertFalse(exportable.isExportable());
|
assertFalse(exportable.isExportable());
|
||||||
|
|
||||||
wrapper.setExportable(false, true);
|
wrapper.setExportable(false, true);
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
exportable = (Exportable) vector.getSubpacket(SignatureSubpacketTags.EXPORTABLE);
|
exportable = (Exportable) vector.getSubpacket(SignatureSubpacketTags.EXPORTABLE);
|
||||||
assertFalse(exportable.isCritical());
|
assertFalse(exportable.isCritical());
|
||||||
|
@ -347,14 +346,14 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSetRevocable() {
|
public void testSetRevocable() {
|
||||||
wrapper.setRevocable(true, true);
|
wrapper.setRevocable(true, true);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
Revocable revocable = (Revocable) vector.getSubpacket(SignatureSubpacketTags.REVOCABLE);
|
Revocable revocable = (Revocable) vector.getSubpacket(SignatureSubpacketTags.REVOCABLE);
|
||||||
assertTrue(revocable.isCritical());
|
assertTrue(revocable.isCritical());
|
||||||
assertTrue(revocable.isRevocable());
|
assertTrue(revocable.isRevocable());
|
||||||
|
|
||||||
wrapper.setRevocable(false, false);
|
wrapper.setRevocable(false, false);
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
revocable = (Revocable) vector.getSubpacket(SignatureSubpacketTags.REVOCABLE);
|
revocable = (Revocable) vector.getSubpacket(SignatureSubpacketTags.REVOCABLE);
|
||||||
assertFalse(revocable.isCritical());
|
assertFalse(revocable.isCritical());
|
||||||
|
@ -365,7 +364,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
public void testSetRevocationReason() {
|
public void testSetRevocationReason() {
|
||||||
wrapper.setRevocationReason(RevocationAttributes.createKeyRevocation()
|
wrapper.setRevocationReason(RevocationAttributes.createKeyRevocation()
|
||||||
.withReason(RevocationAttributes.Reason.KEY_RETIRED).withDescription("The key is too weak."));
|
.withReason(RevocationAttributes.Reason.KEY_RETIRED).withDescription("The key is too weak."));
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
assertEquals(1, vector.getSubpackets(SignatureSubpacketTags.REVOCATION_REASON).length);
|
assertEquals(1, vector.getSubpackets(SignatureSubpacketTags.REVOCATION_REASON).length);
|
||||||
RevocationReason reason = (RevocationReason) vector.getSubpacket(SignatureSubpacketTags.REVOCATION_REASON);
|
RevocationReason reason = (RevocationReason) vector.getSubpacket(SignatureSubpacketTags.REVOCATION_REASON);
|
||||||
|
@ -378,7 +377,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
byte[] hash = new byte[20];
|
byte[] hash = new byte[20];
|
||||||
new Random().nextBytes(hash);
|
new Random().nextBytes(hash);
|
||||||
wrapper.setSignatureTarget(PublicKeyAlgorithm.fromId(key.getAlgorithm()), HashAlgorithm.SHA512, hash);
|
wrapper.setSignatureTarget(PublicKeyAlgorithm.fromId(key.getAlgorithm()), HashAlgorithm.SHA512, hash);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
SignatureTarget target = vector.getSignatureTarget();
|
SignatureTarget target = vector.getSignatureTarget();
|
||||||
assertNotNull(target);
|
assertNotNull(target);
|
||||||
|
@ -390,7 +389,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSetFeatures() {
|
public void testSetFeatures() {
|
||||||
wrapper.setFeatures(Feature.MODIFICATION_DETECTION, Feature.AEAD_ENCRYPTED_DATA);
|
wrapper.setFeatures(Feature.MODIFICATION_DETECTION, Feature.AEAD_ENCRYPTED_DATA);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
Features features = vector.getFeatures();
|
Features features = vector.getFeatures();
|
||||||
assertTrue(features.supportsModificationDetection());
|
assertTrue(features.supportsModificationDetection());
|
||||||
|
@ -401,7 +400,7 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSetTrust() {
|
public void testSetTrust() {
|
||||||
wrapper.setTrust(10, 5);
|
wrapper.setTrust(10, 5);
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
TrustSignature trustSignature = (TrustSignature) vector.getSubpacket(SignatureSubpacketTags.TRUST_SIG);
|
TrustSignature trustSignature = (TrustSignature) vector.getSubpacket(SignatureSubpacketTags.TRUST_SIG);
|
||||||
assertNotNull(trustSignature);
|
assertNotNull(trustSignature);
|
||||||
|
@ -427,18 +426,18 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
|
|
||||||
wrapper.addEmbeddedSignature(sig1);
|
wrapper.addEmbeddedSignature(sig1);
|
||||||
|
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertEquals(1, vector.getEmbeddedSignatures().size());
|
assertEquals(1, vector.getEmbeddedSignatures().size());
|
||||||
assertArrayEquals(sig1.getSignature(), vector.getEmbeddedSignatures().get(0).getSignature());
|
assertArrayEquals(sig1.getSignature(), vector.getEmbeddedSignatures().get(0).getSignature());
|
||||||
|
|
||||||
wrapper.addEmbeddedSignature(sig2);
|
wrapper.addEmbeddedSignature(sig2);
|
||||||
|
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertEquals(2, vector.getEmbeddedSignatures().size());
|
assertEquals(2, vector.getEmbeddedSignatures().size());
|
||||||
assertArrayEquals(sig2.getSignature(), vector.getEmbeddedSignatures().get(1).getSignature());
|
assertArrayEquals(sig2.getSignature(), vector.getEmbeddedSignatures().get(1).getSignature());
|
||||||
|
|
||||||
wrapper.clearEmbeddedSignatures();
|
wrapper.clearEmbeddedSignatures();
|
||||||
vector = wrapper.getGenerator().generate();
|
vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
assertEquals(0, vector.getEmbeddedSignatures().size());
|
assertEquals(0, vector.getEmbeddedSignatures().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,8 +485,8 @@ public class SignatureSubpacketGeneratorWrapperTest {
|
||||||
subpackets.addCustomSubpacket(aead);
|
subpackets.addCustomSubpacket(aead);
|
||||||
|
|
||||||
|
|
||||||
SignatureSubpacketGeneratorWrapper wrapper = SignatureSubpacketGeneratorWrapper.createSubpacketsFrom(subpackets.generate());
|
SignatureSubpackets wrapper = SignatureSubpackets.createSubpacketsFrom(subpackets.generate());
|
||||||
PGPSignatureSubpacketVector vector = wrapper.getGenerator().generate();
|
PGPSignatureSubpacketVector vector = SignatureSubpacketsHelper.toVector(wrapper);
|
||||||
|
|
||||||
// Verify these are not extracted
|
// Verify these are not extracted
|
||||||
assertEquals(0, vector.getIssuerKeyID());
|
assertEquals(0, vector.getIssuerKeyID());
|
Loading…
Reference in a new issue