From 0effc84fac73a99fdff183e83b89c6f4f47bcf4e Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Fri, 20 Oct 2023 14:10:37 +0200 Subject: [PATCH] Kotlin conversion: SignatureSubpackets + subclasses --- .../subpackets/BaseSignatureSubpackets.java | 140 ---- .../subpackets/CertificationSubpackets.java | 12 - .../RevocationSignatureSubpackets.java | 26 - .../subpackets/SelfSignatureSubpackets.java | 98 --- .../SignatureSubpacketCallback.java | 26 - .../subpackets/SignatureSubpackets.java | 735 ------------------ .../subpackets/SignatureSubpacketsHelper.java | 4 +- .../src/main/kotlin/openpgp/DateExtensions.kt | 12 +- .../secretkeyring/SecretKeyRingEditor.kt | 6 +- .../subpackets/BaseSignatureSubpackets.kt | 128 +++ .../subpackets/CertificationSubpackets.kt | 11 + .../RevocationSignatureSubpackets.kt | 21 + .../subpackets/SelfSignatureSubpackets.kt | 84 ++ .../subpackets/SignatureSubpacketCallback.kt | 26 + .../subpackets/SignatureSubpackets.kt | 491 ++++++++++++ 15 files changed, 777 insertions(+), 1043 deletions(-) delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/BaseSignatureSubpackets.java delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/CertificationSubpackets.java delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/RevocationSignatureSubpackets.java delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SelfSignatureSubpackets.java delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketCallback.java delete mode 100644 pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpackets.java create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/BaseSignatureSubpackets.kt create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/CertificationSubpackets.kt create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/RevocationSignatureSubpackets.kt create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SelfSignatureSubpackets.kt create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SignatureSubpacketCallback.kt create mode 100644 pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SignatureSubpackets.kt diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/BaseSignatureSubpackets.java b/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/BaseSignatureSubpackets.java deleted file mode 100644 index 09fe1a99..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/BaseSignatureSubpackets.java +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.signature.subpackets; - -import java.io.IOException; -import java.net.URL; -import java.util.Date; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import org.bouncycastle.bcpg.sig.EmbeddedSignature; -import org.bouncycastle.bcpg.sig.Exportable; -import org.bouncycastle.bcpg.sig.IntendedRecipientFingerprint; -import org.bouncycastle.bcpg.sig.IssuerFingerprint; -import org.bouncycastle.bcpg.sig.IssuerKeyID; -import org.bouncycastle.bcpg.sig.NotationData; -import org.bouncycastle.bcpg.sig.PolicyURI; -import org.bouncycastle.bcpg.sig.RegularExpression; -import org.bouncycastle.bcpg.sig.Revocable; -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.pgpainless.algorithm.HashAlgorithm; -import org.pgpainless.algorithm.PublicKeyAlgorithm; - -public interface BaseSignatureSubpackets { - - interface Callback extends SignatureSubpacketCallback { - - } - - /** - * Add both an {@link IssuerKeyID} and {@link IssuerFingerprint} subpacket pointing to the given key. - * - * @param key key - * @return this - * - * @deprecated this method MUST NOT be used for OpenPGP v6, since v6 signatures MUST NOT contain any - * {@link IssuerKeyID} packets. - */ - BaseSignatureSubpackets setIssuerFingerprintAndKeyId(PGPPublicKey key); - - BaseSignatureSubpackets setIssuerKeyId(long keyId); - - BaseSignatureSubpackets setIssuerKeyId(boolean isCritical, long keyId); - - BaseSignatureSubpackets setIssuerKeyId(@Nullable IssuerKeyID issuerKeyID); - - BaseSignatureSubpackets setIssuerFingerprint(@Nonnull PGPPublicKey key); - - BaseSignatureSubpackets setIssuerFingerprint(boolean isCritical, @Nonnull PGPPublicKey key); - - BaseSignatureSubpackets setIssuerFingerprint(@Nullable IssuerFingerprint fingerprint); - - BaseSignatureSubpackets setSignatureCreationTime(@Nonnull Date creationTime); - - BaseSignatureSubpackets setSignatureCreationTime(boolean isCritical, @Nonnull Date creationTime); - - BaseSignatureSubpackets setSignatureCreationTime(@Nullable SignatureCreationTime signatureCreationTime); - - BaseSignatureSubpackets setSignatureExpirationTime(@Nonnull Date creationTime, @Nonnull Date expirationTime); - - BaseSignatureSubpackets setSignatureExpirationTime(boolean isCritical, @Nonnull Date creationTime, @Nonnull Date expirationTime); - - BaseSignatureSubpackets setSignatureExpirationTime(boolean isCritical, long seconds); - - BaseSignatureSubpackets setSignatureExpirationTime(@Nullable SignatureExpirationTime expirationTime); - - BaseSignatureSubpackets setSignerUserId(@Nonnull String userId); - - BaseSignatureSubpackets setSignerUserId(boolean isCritical, @Nonnull String userId); - - BaseSignatureSubpackets setSignerUserId(@Nullable SignerUserID signerUserId); - - BaseSignatureSubpackets addNotationData(boolean isCritical, @Nonnull String notationName, @Nonnull String notationValue); - - BaseSignatureSubpackets addNotationData(boolean isCritical, boolean isHumanReadable, @Nonnull String notationName, @Nonnull String notationValue); - - BaseSignatureSubpackets addNotationData(@Nonnull NotationData notationData); - - BaseSignatureSubpackets clearNotationData(); - - BaseSignatureSubpackets addIntendedRecipientFingerprint(@Nonnull PGPPublicKey recipient); - - BaseSignatureSubpackets addIntendedRecipientFingerprint(boolean isCritical, @Nonnull PGPPublicKey recipient); - - BaseSignatureSubpackets addIntendedRecipientFingerprint(IntendedRecipientFingerprint intendedRecipientFingerprint); - - BaseSignatureSubpackets clearIntendedRecipientFingerprints(); - - BaseSignatureSubpackets setExportable(boolean isExportable); - - BaseSignatureSubpackets setExportable(boolean isCritical, boolean isExportable); - - BaseSignatureSubpackets setExportable(@Nullable Exportable exportable); - - BaseSignatureSubpackets setPolicyUrl(@Nonnull URL policyUrl); - - BaseSignatureSubpackets setPolicyUrl(boolean isCritical, @Nonnull URL policyUrl); - - BaseSignatureSubpackets setPolicyUrl(@Nullable PolicyURI policyUrl); - - BaseSignatureSubpackets setRegularExpression(@Nonnull String regex); - - BaseSignatureSubpackets setRegularExpression(boolean isCritical, @Nonnull String regex); - - BaseSignatureSubpackets setRegularExpression(@Nullable RegularExpression regex); - - BaseSignatureSubpackets setRevocable(boolean revocable); - - BaseSignatureSubpackets setRevocable(boolean isCritical, boolean isRevocable); - - BaseSignatureSubpackets setRevocable(@Nullable Revocable revocable); - - BaseSignatureSubpackets setSignatureTarget(@Nonnull PublicKeyAlgorithm keyAlgorithm, @Nonnull HashAlgorithm hashAlgorithm, @Nonnull byte[] hashData); - - BaseSignatureSubpackets setSignatureTarget(boolean isCritical, @Nonnull PublicKeyAlgorithm keyAlgorithm, @Nonnull HashAlgorithm hashAlgorithm, @Nonnull byte[] hashData); - - BaseSignatureSubpackets setSignatureTarget(@Nullable SignatureTarget signatureTarget); - - BaseSignatureSubpackets setTrust(int depth, int amount); - - BaseSignatureSubpackets setTrust(boolean isCritical, int depth, int amount); - - BaseSignatureSubpackets setTrust(@Nullable TrustSignature trust); - - BaseSignatureSubpackets addEmbeddedSignature(@Nonnull PGPSignature signature) throws IOException; - - BaseSignatureSubpackets addEmbeddedSignature(boolean isCritical, @Nonnull PGPSignature signature) throws IOException; - - BaseSignatureSubpackets addEmbeddedSignature(@Nonnull EmbeddedSignature embeddedSignature); - - BaseSignatureSubpackets clearEmbeddedSignatures(); -} diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/CertificationSubpackets.java b/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/CertificationSubpackets.java deleted file mode 100644 index 24614882..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/CertificationSubpackets.java +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.signature.subpackets; - -public interface CertificationSubpackets extends BaseSignatureSubpackets { - - interface Callback extends SignatureSubpacketCallback { - - } -} diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/RevocationSignatureSubpackets.java b/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/RevocationSignatureSubpackets.java deleted file mode 100644 index 358437dc..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/RevocationSignatureSubpackets.java +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.signature.subpackets; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import org.bouncycastle.bcpg.sig.RevocationReason; -import org.pgpainless.key.util.RevocationAttributes; - -public interface RevocationSignatureSubpackets extends BaseSignatureSubpackets { - - interface Callback extends SignatureSubpacketCallback { - - } - - RevocationSignatureSubpackets setRevocationReason(RevocationAttributes revocationAttributes); - - RevocationSignatureSubpackets setRevocationReason(boolean isCritical, RevocationAttributes revocationAttributes); - - RevocationSignatureSubpackets setRevocationReason(boolean isCritical, RevocationAttributes.Reason reason, @Nonnull String description); - - RevocationSignatureSubpackets setRevocationReason(@Nullable RevocationReason reason); -} diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SelfSignatureSubpackets.java b/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SelfSignatureSubpackets.java deleted file mode 100644 index 02cc5e93..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SelfSignatureSubpackets.java +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.signature.subpackets; - -import java.util.Date; -import java.util.List; -import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import org.bouncycastle.bcpg.sig.Features; -import org.bouncycastle.bcpg.sig.KeyExpirationTime; -import org.bouncycastle.bcpg.sig.KeyFlags; -import org.bouncycastle.bcpg.sig.PreferredAlgorithms; -import org.bouncycastle.bcpg.sig.PrimaryUserID; -import org.bouncycastle.bcpg.sig.RevocationKey; -import org.bouncycastle.openpgp.PGPPublicKey; -import org.pgpainless.algorithm.CompressionAlgorithm; -import org.pgpainless.algorithm.Feature; -import org.pgpainless.algorithm.HashAlgorithm; -import org.pgpainless.algorithm.KeyFlag; -import org.pgpainless.algorithm.SymmetricKeyAlgorithm; - -public interface SelfSignatureSubpackets extends BaseSignatureSubpackets { - - interface Callback extends SignatureSubpacketCallback { - - } - - SelfSignatureSubpackets setKeyFlags(KeyFlag... keyFlags); - - default SelfSignatureSubpackets setKeyFlags(List keyFlags) { - KeyFlag[] flags = keyFlags.toArray(new KeyFlag[0]); - return setKeyFlags(flags); - } - - SelfSignatureSubpackets setKeyFlags(boolean isCritical, KeyFlag... keyFlags); - - SelfSignatureSubpackets setKeyFlags(@Nullable KeyFlags keyFlags); - - SelfSignatureSubpackets setPrimaryUserId(); - - SelfSignatureSubpackets setPrimaryUserId(boolean isCritical); - - SelfSignatureSubpackets setPrimaryUserId(@Nullable PrimaryUserID primaryUserId); - - SelfSignatureSubpackets setKeyExpirationTime(@Nonnull PGPPublicKey key, @Nonnull Date keyExpirationTime); - - SelfSignatureSubpackets setKeyExpirationTime(@Nonnull Date keyCreationTime, @Nonnull Date keyExpirationTime); - - SelfSignatureSubpackets setKeyExpirationTime(boolean isCritical, @Nonnull Date keyCreationTime, @Nonnull Date keyExpirationTime); - - SelfSignatureSubpackets setKeyExpirationTime(boolean isCritical, long secondsFromCreationToExpiration); - - SelfSignatureSubpackets setKeyExpirationTime(@Nullable KeyExpirationTime keyExpirationTime); - - SelfSignatureSubpackets setPreferredCompressionAlgorithms(CompressionAlgorithm... algorithms); - - SelfSignatureSubpackets setPreferredCompressionAlgorithms(Set algorithms); - - SelfSignatureSubpackets setPreferredCompressionAlgorithms(boolean isCritical, Set algorithms); - - SelfSignatureSubpackets setPreferredCompressionAlgorithms(@Nullable PreferredAlgorithms algorithms); - - SelfSignatureSubpackets setPreferredSymmetricKeyAlgorithms(SymmetricKeyAlgorithm... algorithms); - - SelfSignatureSubpackets setPreferredSymmetricKeyAlgorithms(Set algorithms); - - SelfSignatureSubpackets setPreferredSymmetricKeyAlgorithms(boolean isCritical, Set algorithms); - - SelfSignatureSubpackets setPreferredSymmetricKeyAlgorithms(@Nullable PreferredAlgorithms algorithms); - - SelfSignatureSubpackets setPreferredHashAlgorithms(HashAlgorithm... algorithms); - - SelfSignatureSubpackets setPreferredHashAlgorithms(Set algorithms); - - SelfSignatureSubpackets setPreferredHashAlgorithms(boolean isCritical, Set algorithms); - - SelfSignatureSubpackets setPreferredHashAlgorithms(@Nullable PreferredAlgorithms algorithms); - - SelfSignatureSubpackets addRevocationKey(@Nonnull PGPPublicKey revocationKey); - - SelfSignatureSubpackets addRevocationKey(boolean isCritical, @Nonnull PGPPublicKey revocationKey); - - SelfSignatureSubpackets addRevocationKey(boolean isCritical, boolean isSensitive, @Nonnull PGPPublicKey revocationKey); - - SelfSignatureSubpackets addRevocationKey(@Nonnull RevocationKey revocationKey); - - SelfSignatureSubpackets clearRevocationKeys(); - - SelfSignatureSubpackets setFeatures(Feature... features); - - SelfSignatureSubpackets setFeatures(boolean isCritical, Feature... features); - - SelfSignatureSubpackets setFeatures(@Nullable Features features); -} diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketCallback.java b/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketCallback.java deleted file mode 100644 index 11650ea3..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketCallback.java +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.signature.subpackets; - -public interface SignatureSubpacketCallback { - - /** - * Callback method that can be used to modify the hashed subpackets of a signature. - * - * @param hashedSubpackets hashed subpackets - */ - default void modifyHashedSubpackets(S hashedSubpackets) { - - } - - /** - * Callback method that can be used to modify the unhashed subpackets of a signature. - * - * @param unhashedSubpackets unhashed subpackets - */ - default void modifyUnhashedSubpackets(S unhashedSubpackets) { - - } -} diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpackets.java b/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpackets.java deleted file mode 100644 index d0466b6a..00000000 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpackets.java +++ /dev/null @@ -1,735 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.signature.subpackets; - -import java.io.IOException; -import java.net.URL; -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.PolicyURI; -import org.bouncycastle.bcpg.sig.PreferredAlgorithms; -import org.bouncycastle.bcpg.sig.PrimaryUserID; -import org.bouncycastle.bcpg.sig.RegularExpression; -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 notationDataList = new ArrayList<>(); - private final List intendedRecipientFingerprintList = new ArrayList<>(); - private final List 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 embeddedSignatureList = new ArrayList<>(); - private SignerUserID signerUserId; - private KeyExpirationTime keyExpirationTime; - private PolicyURI policyURI; - private PrimaryUserID primaryUserId; - private RegularExpression regularExpression; - private Revocable revocable; - private RevocationReason revocationReason; - private final List residualSubpackets = new ArrayList<>(); - - public SignatureSubpackets() { - - } - - public interface Callback extends SignatureSubpacketCallback { - - } - - 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; - } - - public static SignatureSubpackets createEmptySubpackets() { - return new SignatureSubpackets(); - } - - @Override - public SignatureSubpackets setIssuerFingerprintAndKeyId(PGPPublicKey key) { - setIssuerKeyId(key.getKeyID()); - setIssuerFingerprint(key); - return this; - } - - @Override - public SignatureSubpackets setIssuerKeyId(long keyId) { - return setIssuerKeyId(false, 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(false, 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) { - enforceBounds(seconds); - 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) { - enforceBounds(secondsFromCreationToExpiration); - return setKeyExpirationTime(new KeyExpirationTime(isCritical, secondsFromCreationToExpiration)); - } - - /** - * Enforce that
secondsFromCreationToExpiration
is within bounds of an unsigned 32bit number. - * Values less than 0 are illegal, as well as values greater 0xffffffff. - * - * @param secondsFromCreationToExpiration number to check - * @throws IllegalArgumentException in case of an under- or overflow - */ - private void enforceBounds(long secondsFromCreationToExpiration) { - if (secondsFromCreationToExpiration < 0) { - throw new IllegalArgumentException("Seconds from creation to expiration cannot be less than 0."); - } - if (secondsFromCreationToExpiration > 0xffffffffL) { - throw new IllegalArgumentException("Integer overflow. Seconds from creation to expiration cannot be larger than 0xffffffff"); - } - } - - @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 algorithms) { - return setPreferredCompressionAlgorithms(false, algorithms); - } - - @Override - public SignatureSubpackets setPreferredCompressionAlgorithms(boolean isCritical, Set algorithms) { - int[] ids = new int[algorithms.size()]; - Iterator 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 algorithms) { - return setPreferredSymmetricKeyAlgorithms(false, algorithms); - } - - @Override - public SignatureSubpackets setPreferredSymmetricKeyAlgorithms(boolean isCritical, Set algorithms) { - int[] ids = new int[algorithms.size()]; - Iterator 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 algorithms) { - return setPreferredHashAlgorithms(false, algorithms); - } - - @Override - public SignatureSubpackets setPreferredHashAlgorithms(boolean isCritical, Set algorithms) { - int[] ids = new int[algorithms.size()]; - Iterator 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 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 getIntendedRecipientFingerprintSubpackets() { - return new ArrayList<>(intendedRecipientFingerprintList); - } - - @Override - public SignatureSubpackets setExportable(boolean exportable) { - return setExportable(true, exportable); - } - - @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 BaseSignatureSubpackets setPolicyUrl(@Nonnull URL policyUrl) { - return setPolicyUrl(false, policyUrl); - } - - @Override - public BaseSignatureSubpackets setPolicyUrl(boolean isCritical, @Nonnull URL policyUrl) { - return setPolicyUrl(new PolicyURI(isCritical, policyUrl.toString())); - } - - @Override - public BaseSignatureSubpackets setPolicyUrl(@Nullable PolicyURI policyUrl) { - this.policyURI = policyUrl; - return this; - } - - public PolicyURI getPolicyURI() { - return policyURI; - } - - @Override - public BaseSignatureSubpackets setRegularExpression(@Nonnull String regex) { - return setRegularExpression(false, regex); - } - - @Override - public BaseSignatureSubpackets setRegularExpression(boolean isCritical, @Nonnull String regex) { - return setRegularExpression(new RegularExpression(isCritical, regex)); - } - - @Override - public BaseSignatureSubpackets setRegularExpression(@Nullable RegularExpression regex) { - this.regularExpression = regex; - return this; - } - - public RegularExpression getRegularExpression() { - return regularExpression; - } - - @Override - public SignatureSubpackets setRevocable(boolean revocable) { - return setRevocable(true, revocable); - } - - @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 getRevocationKeySubpackets() { - return new ArrayList<>(revocationKeyList); - } - - @Override - public SignatureSubpackets setRevocationReason(RevocationAttributes revocationAttributes) { - return setRevocationReason(false, 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 getEmbeddedSignatureSubpackets() { - return new ArrayList<>(embeddedSignatureList); - } - - public SignatureSubpackets addResidualSubpacket(SignatureSubpacket subpacket) { - this.residualSubpackets.add(subpacket); - return this; - } - - public List getResidualSubpackets() { - return new ArrayList<>(residualSubpackets); - } - -} diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketsHelper.java b/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketsHelper.java index 8af60a03..2a7d4f83 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketsHelper.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/subpackets/SignatureSubpacketsHelper.java @@ -143,8 +143,8 @@ public class SignatureSubpacketsHelper { addSubpacket(generator, subpackets.getSignatureCreationTimeSubpacket()); addSubpacket(generator, subpackets.getSignatureExpirationTimeSubpacket()); addSubpacket(generator, subpackets.getExportableSubpacket()); - addSubpacket(generator, subpackets.getPolicyURI()); - addSubpacket(generator, subpackets.getRegularExpression()); + addSubpacket(generator, subpackets.getPolicyURISubpacket()); + addSubpacket(generator, subpackets.getRegularExpressionSubpacket()); for (NotationData notationData : subpackets.getNotationDataSubpackets()) { addSubpacket(generator, notationData); } diff --git a/pgpainless-core/src/main/kotlin/openpgp/DateExtensions.kt b/pgpainless-core/src/main/kotlin/openpgp/DateExtensions.kt index 5972cd3a..a1c80710 100644 --- a/pgpainless-core/src/main/kotlin/openpgp/DateExtensions.kt +++ b/pgpainless-core/src/main/kotlin/openpgp/DateExtensions.kt @@ -24,11 +24,21 @@ fun Date.plusSeconds(seconds: Long): Date? { else Date(this.time + 1000 * seconds) } +val Date.asSeconds: Long + get() = time / 1000 + +fun Date.secondsTill(later: Date): Long { + require(this <= later) { + "Timestamp MUST be before the later timestamp." + } + return later.asSeconds - this.asSeconds +} + /** * Return a new [Date] instance with this instance's time floored down to seconds precision. */ fun Date.toSecondsPrecision(): Date { - return Date((time / 1000) * 1000) + return Date(asSeconds * 1000) } internal val parser: SimpleDateFormat diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt index b219a739..3425145b 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt @@ -144,14 +144,14 @@ class SecretKeyRingEditor( ?: throw AssertionError("Certification for old user-ID MUST NOT be null.") addUserId(newUID, object : SelfSignatureSubpackets.Callback { - override fun modifyHashedSubpackets(hashedSubpackets: SelfSignatureSubpackets?) { + override fun modifyHashedSubpackets(hashedSubpackets: SelfSignatureSubpackets) { SignatureSubpacketsHelper.applyFrom(oldCertification.hashedSubPackets, hashedSubpackets as SignatureSubpackets) if (oldUID == info.primaryUserId && !oldCertification.hashedSubPackets.isPrimaryUserID) { hashedSubpackets.setPrimaryUserId() } } - override fun modifyUnhashedSubpackets(unhashedSubpackets: SelfSignatureSubpackets?) { + override fun modifyUnhashedSubpackets(unhashedSubpackets: SelfSignatureSubpackets) { SignatureSubpacketsHelper.applyFrom(oldCertification.unhashedSubPackets, unhashedSubpackets as SignatureSubpackets) } }, protector) @@ -163,7 +163,7 @@ class SecretKeyRingEditor( subkeyPassphrase: Passphrase, protector: SecretKeyRingProtector): SecretKeyRingEditorInterface { val callback = object : SelfSignatureSubpackets.Callback { - override fun modifyHashedSubpackets(hashedSubpackets: SelfSignatureSubpackets?) { + override fun modifyHashedSubpackets(hashedSubpackets: SelfSignatureSubpackets) { SignatureSubpacketsHelper.applyFrom(keySpec.subpackets, hashedSubpackets as SignatureSubpackets) } } diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/BaseSignatureSubpackets.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/BaseSignatureSubpackets.kt new file mode 100644 index 00000000..66618b23 --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/BaseSignatureSubpackets.kt @@ -0,0 +1,128 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.signature.subpackets + +import org.bouncycastle.bcpg.sig.* +import org.bouncycastle.openpgp.PGPPublicKey +import org.bouncycastle.openpgp.PGPSignature +import org.pgpainless.algorithm.HashAlgorithm +import org.pgpainless.algorithm.PublicKeyAlgorithm +import java.io.IOException +import java.net.URL +import java.util.* + +interface BaseSignatureSubpackets { + + interface Callback : SignatureSubpacketCallback + + /** + * Add both an [IssuerKeyID] and [IssuerFingerprint] subpacket pointing to the given key. + * + * @param key key + * @return this + * + * @deprecated this method MUST NOT be used for OpenPGP v6, since v6 signatures MUST NOT contain any + * [IssuerKeyID] packets. + */ + fun setIssuerFingerprintAndKeyId(key: PGPPublicKey): BaseSignatureSubpackets + + fun setIssuerKeyId(keyId: Long): BaseSignatureSubpackets + + fun setIssuerKeyId(isCritical: Boolean, keyId: Long): BaseSignatureSubpackets + + fun setIssuerKeyId(issuerKeyID: IssuerKeyID?): BaseSignatureSubpackets + + fun setIssuerFingerprint(isCritical: Boolean, issuer: PGPPublicKey): BaseSignatureSubpackets + + fun setIssuerFingerprint(issuer: PGPPublicKey): BaseSignatureSubpackets + + fun setIssuerFingerprint(fingerprint: IssuerFingerprint?): BaseSignatureSubpackets + + fun setSignatureCreationTime(creationTime: Date): BaseSignatureSubpackets + + fun setSignatureCreationTime(isCritical: Boolean, creationTime: Date): BaseSignatureSubpackets + + fun setSignatureCreationTime(creationTime: SignatureCreationTime?): BaseSignatureSubpackets + + fun setSignatureExpirationTime(creationTime: Date, expirationTime: Date?): BaseSignatureSubpackets + + fun setSignatureExpirationTime(isCritical: Boolean, creationTime: Date, expirationTime: Date?): BaseSignatureSubpackets + + fun setSignatureExpirationTime(isCritical: Boolean, seconds: Long): BaseSignatureSubpackets + + fun setSignatureExpirationTime(expirationTime: SignatureExpirationTime?): BaseSignatureSubpackets + + fun setSignerUserId(userId: CharSequence): BaseSignatureSubpackets + + fun setSignerUserId(isCritical: Boolean, userId: CharSequence): BaseSignatureSubpackets + + fun setSignerUserId(signerUserID: SignerUserID?): BaseSignatureSubpackets + + fun addNotationData(isCritical: Boolean, notationName: String, notationValue: String): BaseSignatureSubpackets + + fun addNotationData(isCritical: Boolean, isHumanReadable: Boolean, notationName: String, notationValue: String): BaseSignatureSubpackets + + fun addNotationData(notationData: NotationData): BaseSignatureSubpackets + + fun clearNotationData(): BaseSignatureSubpackets + + fun addIntendedRecipientFingerprint(recipientKey: PGPPublicKey): BaseSignatureSubpackets + + fun addIntendedRecipientFingerprint(isCritical: Boolean, recipientKey: PGPPublicKey): BaseSignatureSubpackets + + fun addIntendedRecipientFingerprint(intendedRecipient: IntendedRecipientFingerprint): BaseSignatureSubpackets + + fun clearIntendedRecipientFingerprints(): BaseSignatureSubpackets + + fun setExportable(): BaseSignatureSubpackets + + fun setExportable(isExportable: Boolean): BaseSignatureSubpackets + + fun setExportable(isCritical: Boolean, isExportable: Boolean): BaseSignatureSubpackets + + fun setExportable(exportable: Exportable?): BaseSignatureSubpackets + + fun setPolicyUrl(policyUrl: URL): BaseSignatureSubpackets + + fun setPolicyUrl(isCritical: Boolean, policyUrl: URL): BaseSignatureSubpackets + + fun setPolicyUrl(policyUrl: PolicyURI?): BaseSignatureSubpackets + + fun setRegularExpression(regex: CharSequence): BaseSignatureSubpackets + + fun setRegularExpression(isCritical: Boolean, regex: CharSequence): BaseSignatureSubpackets + + fun setRegularExpression(regex: RegularExpression?): BaseSignatureSubpackets + + fun setRevocable(): BaseSignatureSubpackets + + fun setRevocable(isRevocable: Boolean): BaseSignatureSubpackets + + fun setRevocable(isCritical: Boolean, isRevocable: Boolean): BaseSignatureSubpackets + + fun setRevocable(revocable: Revocable?): BaseSignatureSubpackets + + fun setSignatureTarget(keyAlgorithm: PublicKeyAlgorithm, hashAlgorithm: HashAlgorithm, hashData: ByteArray): BaseSignatureSubpackets + + fun setSignatureTarget(isCritical: Boolean, keyAlgorithm: PublicKeyAlgorithm, hashAlgorithm: HashAlgorithm, hashData: ByteArray): BaseSignatureSubpackets + + fun setSignatureTarget(signatureTarget: SignatureTarget?): BaseSignatureSubpackets + + fun setTrust(depth: Int, amount: Int): BaseSignatureSubpackets + + fun setTrust(isCritical: Boolean, depth: Int, amount: Int): BaseSignatureSubpackets + + fun setTrust(trust: TrustSignature?): BaseSignatureSubpackets + + @Throws(IOException::class) + fun addEmbeddedSignature(signature: PGPSignature): BaseSignatureSubpackets + + @Throws(IOException::class) + fun addEmbeddedSignature(isCritical: Boolean, signature: PGPSignature): BaseSignatureSubpackets + + fun addEmbeddedSignature(embeddedSignature: EmbeddedSignature): BaseSignatureSubpackets + + fun clearEmbeddedSignatures(): BaseSignatureSubpackets +} \ No newline at end of file diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/CertificationSubpackets.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/CertificationSubpackets.kt new file mode 100644 index 00000000..423edd8e --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/CertificationSubpackets.kt @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.signature.subpackets + +interface CertificationSubpackets : BaseSignatureSubpackets { + + interface Callback : SignatureSubpacketCallback + +} \ No newline at end of file diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/RevocationSignatureSubpackets.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/RevocationSignatureSubpackets.kt new file mode 100644 index 00000000..327ed4a9 --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/RevocationSignatureSubpackets.kt @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.signature.subpackets + +import org.bouncycastle.bcpg.sig.RevocationReason +import org.pgpainless.key.util.RevocationAttributes + +interface RevocationSignatureSubpackets : BaseSignatureSubpackets { + + interface Callback : SignatureSubpacketCallback + + fun setRevocationReason(revocationAttributes: RevocationAttributes): RevocationSignatureSubpackets + + fun setRevocationReason(isCritical: Boolean, revocationAttributes: RevocationAttributes): RevocationSignatureSubpackets + + fun setRevocationReason(isCritical: Boolean, reason: RevocationAttributes.Reason, description: CharSequence): RevocationSignatureSubpackets + + fun setRevocationReason(reason: RevocationReason?): RevocationSignatureSubpackets +} \ No newline at end of file diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SelfSignatureSubpackets.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SelfSignatureSubpackets.kt new file mode 100644 index 00000000..ce8e09a9 --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SelfSignatureSubpackets.kt @@ -0,0 +1,84 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.signature.subpackets + +import org.bouncycastle.bcpg.sig.Features +import org.bouncycastle.bcpg.sig.KeyExpirationTime +import org.bouncycastle.bcpg.sig.KeyFlags +import org.bouncycastle.bcpg.sig.PreferredAlgorithms +import org.bouncycastle.bcpg.sig.PrimaryUserID +import org.bouncycastle.bcpg.sig.RevocationKey +import org.bouncycastle.openpgp.PGPPublicKey +import org.pgpainless.algorithm.* +import java.util.* + +interface SelfSignatureSubpackets : BaseSignatureSubpackets { + + interface Callback : SignatureSubpacketCallback + + fun setKeyFlags(vararg keyflags: KeyFlag): SelfSignatureSubpackets + + fun setKeyFlags(keyFlags: List): SelfSignatureSubpackets + + fun setKeyFlags(isCritical: Boolean, vararg keyFlags: KeyFlag): SelfSignatureSubpackets + + fun setKeyFlags(keyFlags: KeyFlags?): SelfSignatureSubpackets + + fun setPrimaryUserId(): SelfSignatureSubpackets + + fun setPrimaryUserId(isCritical: Boolean): SelfSignatureSubpackets + + fun setPrimaryUserId(primaryUserID: PrimaryUserID?): SelfSignatureSubpackets + + fun setKeyExpirationTime(key: PGPPublicKey, keyExpirationTime: Date?): SelfSignatureSubpackets + + fun setKeyExpirationTime(keyCreationTime: Date, keyExpirationTime: Date?): SelfSignatureSubpackets + + fun setKeyExpirationTime(isCritical: Boolean, keyCreationTime: Date, keyExpirationTime: Date?): SelfSignatureSubpackets + + fun setKeyExpirationTime(isCritical: Boolean, secondsFromCreationToExpiration: Long): SelfSignatureSubpackets + + fun setKeyExpirationTime(keyExpirationTime: KeyExpirationTime?): SelfSignatureSubpackets + + fun setPreferredCompressionAlgorithms(vararg algorithms: CompressionAlgorithm): SelfSignatureSubpackets + + fun setPreferredCompressionAlgorithms(algorithms: Collection): SelfSignatureSubpackets + + fun setPreferredCompressionAlgorithms(isCritical: Boolean, algorithms: Collection): SelfSignatureSubpackets + + fun setPreferredCompressionAlgorithms(preferredAlgorithms: PreferredAlgorithms?): SelfSignatureSubpackets + + fun setPreferredSymmetricKeyAlgorithms(vararg algorithms: SymmetricKeyAlgorithm): SelfSignatureSubpackets + + fun setPreferredSymmetricKeyAlgorithms(algorithms: Collection): SelfSignatureSubpackets + + fun setPreferredSymmetricKeyAlgorithms(isCritical: Boolean, algorithms: Collection): SelfSignatureSubpackets + + fun setPreferredSymmetricKeyAlgorithms(algorithms: PreferredAlgorithms?): SelfSignatureSubpackets + + fun setPreferredHashAlgorithms(vararg algorithms: HashAlgorithm): SelfSignatureSubpackets + + fun setPreferredHashAlgorithms(algorithms: Collection): SelfSignatureSubpackets + + fun setPreferredHashAlgorithms(isCritical: Boolean, algorithms: Collection): SelfSignatureSubpackets + + fun setPreferredHashAlgorithms(algorithms: PreferredAlgorithms?): SelfSignatureSubpackets + + fun addRevocationKey(revocationKey: PGPPublicKey): SelfSignatureSubpackets + + fun addRevocationKey(isCritical: Boolean, revocationKey: PGPPublicKey): SelfSignatureSubpackets + + fun addRevocationKey(isCritical: Boolean, isSensitive: Boolean, revocationKey: PGPPublicKey): SelfSignatureSubpackets + + fun addRevocationKey(revocationKey: RevocationKey): SelfSignatureSubpackets + + fun clearRevocationKeys(): SelfSignatureSubpackets + + fun setFeatures(vararg features: Feature): SelfSignatureSubpackets + + fun setFeatures(isCritical: Boolean, vararg features: Feature): SelfSignatureSubpackets + + fun setFeatures(features: Features?): SelfSignatureSubpackets +} \ No newline at end of file diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SignatureSubpacketCallback.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SignatureSubpacketCallback.kt new file mode 100644 index 00000000..d147dc97 --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SignatureSubpacketCallback.kt @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.signature.subpackets + +interface SignatureSubpacketCallback { + + /** + * Callback method that can be used to modify the hashed subpackets of a signature. + * + * @param hashedSubpackets hashed subpackets + */ + fun modifyHashedSubpackets(hashedSubpackets: S) { + // Empty default implementation to allow for cleaner overriding + } + + /** + * Callback method that can be used to modify the unhashed subpackets of a signature. + * + * @param unhashedSubpackets unhashed subpackets + */ + fun modifyUnhashedSubpackets(unhashedSubpackets: S) { + // Empty default implementation to allow for cleaner overriding + } +} \ No newline at end of file diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SignatureSubpackets.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SignatureSubpackets.kt new file mode 100644 index 00000000..d7d907f0 --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/subpackets/SignatureSubpackets.kt @@ -0,0 +1,491 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.signature.subpackets + +import openpgp.secondsTill +import openpgp.toSecondsPrecision +import org.bouncycastle.bcpg.SignatureSubpacket +import org.bouncycastle.bcpg.SignatureSubpacketTags +import org.bouncycastle.bcpg.sig.* +import org.bouncycastle.openpgp.PGPPublicKey +import org.bouncycastle.openpgp.PGPSignature +import org.bouncycastle.openpgp.PGPSignatureSubpacketVector +import org.pgpainless.algorithm.* +import org.pgpainless.key.util.RevocationAttributes +import java.lang.IllegalArgumentException +import java.net.URL +import java.util.* +import kotlin.experimental.or + +class SignatureSubpackets + : BaseSignatureSubpackets, SelfSignatureSubpackets, CertificationSubpackets, RevocationSignatureSubpackets { + + interface Callback : SignatureSubpacketCallback + + var signatureCreationTimeSubpacket: SignatureCreationTime? = null + var signatureExpirationTimeSubpacket: SignatureExpirationTime? = null + var issuerKeyIdSubpacket: IssuerKeyID? = null + var issuerFingerprintSubpacket: IssuerFingerprint? = null + val notationDataSubpackets: List = mutableListOf() + val intendedRecipientFingerprintSubpackets: List = mutableListOf() + val revocationKeySubpackets: List = mutableListOf() + var exportableSubpacket: Exportable? = null + var signatureTargetSubpacket: SignatureTarget? = null + var featuresSubpacket: Features? = null + var keyFlagsSubpacket: KeyFlags? = null + var trustSubpacket: TrustSignature? = null + var preferredCompressionAlgorithmsSubpacket: PreferredAlgorithms? = null + var preferredSymmetricKeyAlgorithmsSubpacket: PreferredAlgorithms? = null + var preferredHashAlgorithmsSubpacket: PreferredAlgorithms? = null + val embeddedSignatureSubpackets: List = mutableListOf() + var signerUserIdSubpacket: SignerUserID? = null + var keyExpirationTimeSubpacket: KeyExpirationTime? = null + var policyURISubpacket: PolicyURI? = null + var primaryUserIdSubpacket: PrimaryUserID? = null + var regularExpressionSubpacket: RegularExpression? = null + var revocableSubpacket: Revocable? = null + var revocationReasonSubpacket: RevocationReason? = null + val residualSubpackets: List = mutableListOf() + + companion object { + + @JvmStatic + fun refreshHashedSubpackets(issuer: PGPPublicKey, oldSignature: PGPSignature): SignatureSubpackets { + return createHashedSubpacketsFrom(issuer, oldSignature.hashedSubPackets) + } + + @JvmStatic + fun refreshUnhashedSubpackets(oldSignature: PGPSignature): SignatureSubpackets { + return createSubpacketsFrom(oldSignature.unhashedSubPackets) + } + + @JvmStatic + fun createHashedSubpacketsFrom(issuer: PGPPublicKey, base: PGPSignatureSubpacketVector): SignatureSubpackets { + return createSubpacketsFrom(base).apply { + setIssuerFingerprintAndKeyId(issuer) + } + } + + @JvmStatic + fun createSubpacketsFrom(base: PGPSignatureSubpacketVector): SignatureSubpackets { + return SignatureSubpackets().apply { + SignatureSubpacketsHelper.applyFrom(base, this) + } + } + + @JvmStatic + fun createHashedSubpackets(issuer: PGPPublicKey): SignatureSubpackets { + return SignatureSubpackets().apply { + setIssuerFingerprintAndKeyId(issuer) + } + } + + @JvmStatic + fun createEmptySubpackets(): SignatureSubpackets { + return SignatureSubpackets() + } + } + + override fun setRevocationReason(revocationAttributes: RevocationAttributes): SignatureSubpackets = apply { + setRevocationReason(false, revocationAttributes) + } + + override fun setRevocationReason(isCritical: Boolean, revocationAttributes: RevocationAttributes): SignatureSubpackets = apply { + setRevocationReason(isCritical, revocationAttributes.reason, revocationAttributes.description) + } + + override fun setRevocationReason(isCritical: Boolean, reason: RevocationAttributes.Reason, description: CharSequence): SignatureSubpackets = apply { + setRevocationReason(RevocationReason(isCritical, reason.code, description.toString())) + } + + override fun setRevocationReason(reason: RevocationReason?): SignatureSubpackets = apply { + this.revocationReasonSubpacket = reason + } + + override fun setKeyFlags(vararg keyflags: KeyFlag): SignatureSubpackets = apply { + setKeyFlags(true, *keyflags) + } + + override fun setKeyFlags(keyFlags: List): SignatureSubpackets = apply { + setKeyFlags(true, *keyFlags.toTypedArray()) + } + + override fun setKeyFlags(isCritical: Boolean, vararg keyFlags: KeyFlag): SignatureSubpackets = apply { + setKeyFlags(KeyFlags(isCritical, KeyFlag.toBitmask(*keyFlags))) + } + + override fun setKeyFlags(keyFlags: KeyFlags?): SignatureSubpackets = apply { + this.keyFlagsSubpacket = keyFlags + } + + override fun setPrimaryUserId(): SignatureSubpackets = apply { + setPrimaryUserId(true) + } + + override fun setPrimaryUserId(isCritical: Boolean): SignatureSubpackets = apply { + setPrimaryUserId(PrimaryUserID(isCritical, true)) + } + + override fun setPrimaryUserId(primaryUserID: PrimaryUserID?): SignatureSubpackets = apply { + this.primaryUserIdSubpacket = primaryUserID + } + + override fun setKeyExpirationTime(key: PGPPublicKey, keyExpirationTime: Date?): SignatureSubpackets = apply { + setKeyExpirationTime(key.creationTime, keyExpirationTime) + } + + override fun setKeyExpirationTime(keyCreationTime: Date, keyExpirationTime: Date?): SignatureSubpackets = apply { + setKeyExpirationTime(true, keyCreationTime, keyExpirationTime) + } + + override fun setKeyExpirationTime(isCritical: Boolean, keyCreationTime: Date, keyExpirationTime: Date?): SignatureSubpackets = apply { + if (keyExpirationTime == null) { + setKeyExpirationTime(isCritical, 0) + } else { + setKeyExpirationTime(isCritical, keyCreationTime.secondsTill(keyExpirationTime)) + } + } + + override fun setKeyExpirationTime(isCritical: Boolean, secondsFromCreationToExpiration: Long): SignatureSubpackets = apply { + enforceExpirationBounds(secondsFromCreationToExpiration) + setKeyExpirationTime(KeyExpirationTime(isCritical, secondsFromCreationToExpiration)) + } + + override fun setKeyExpirationTime(keyExpirationTime: KeyExpirationTime?): SignatureSubpackets = apply { + this.keyExpirationTimeSubpacket = keyExpirationTime + } + + override fun setPreferredCompressionAlgorithms(vararg algorithms: CompressionAlgorithm): SignatureSubpackets = apply { + setPreferredCompressionAlgorithms(setOf(*algorithms)) + } + + override fun setPreferredCompressionAlgorithms(algorithms: Collection): SignatureSubpackets = apply { + setPreferredCompressionAlgorithms(false, algorithms) + } + + override fun setPreferredCompressionAlgorithms(isCritical: Boolean, algorithms: Collection): SignatureSubpackets = apply { + setPreferredCompressionAlgorithms(PreferredAlgorithms( + SignatureSubpacketTags.PREFERRED_COMP_ALGS, + isCritical, + algorithms.map { it.algorithmId }.toIntArray())) + } + + override fun setPreferredCompressionAlgorithms(algorithms: PreferredAlgorithms?): SignatureSubpackets = apply { + require(algorithms == null || algorithms.type == SignatureSubpacketTags.PREFERRED_COMP_ALGS) { + "Invalid preferred compression algorithms type." + } + this.preferredCompressionAlgorithmsSubpacket = algorithms + } + + override fun setPreferredSymmetricKeyAlgorithms(vararg algorithms: SymmetricKeyAlgorithm): SignatureSubpackets = apply { + setPreferredSymmetricKeyAlgorithms(setOf(*algorithms)) + } + + override fun setPreferredSymmetricKeyAlgorithms(algorithms: Collection): SignatureSubpackets = apply { + setPreferredSymmetricKeyAlgorithms(false, algorithms) + } + + override fun setPreferredSymmetricKeyAlgorithms(isCritical: Boolean, algorithms: Collection): SignatureSubpackets = apply { + setPreferredSymmetricKeyAlgorithms(PreferredAlgorithms( + SignatureSubpacketTags.PREFERRED_SYM_ALGS, + isCritical, + algorithms.map { it.algorithmId }.toIntArray() + )) + } + + override fun setPreferredSymmetricKeyAlgorithms(algorithms: PreferredAlgorithms?): SignatureSubpackets = apply { + require(algorithms == null || algorithms.type == SignatureSubpacketTags.PREFERRED_SYM_ALGS) { + "Invalid preferred symmetric algorithms type." + } + this.preferredSymmetricKeyAlgorithmsSubpacket = algorithms + } + + override fun setPreferredHashAlgorithms(vararg algorithms: HashAlgorithm): SignatureSubpackets = apply { + setPreferredHashAlgorithms(setOf(*algorithms)) + } + + override fun setPreferredHashAlgorithms(algorithms: Collection): SignatureSubpackets = apply { + setPreferredHashAlgorithms(false, algorithms) + } + + override fun setPreferredHashAlgorithms(isCritical: Boolean, algorithms: Collection): SignatureSubpackets = apply { + setPreferredHashAlgorithms(PreferredAlgorithms( + SignatureSubpacketTags.PREFERRED_HASH_ALGS, + isCritical, + algorithms.map { it.algorithmId }.toIntArray() + )) + } + + override fun setPreferredHashAlgorithms(algorithms: PreferredAlgorithms?): SignatureSubpackets = apply { + require(algorithms == null || algorithms.type == SignatureSubpacketTags.PREFERRED_HASH_ALGS) { + "Invalid preferred hash algorithms type." + } + this.preferredHashAlgorithmsSubpacket = algorithms + } + + override fun addRevocationKey(revocationKey: PGPPublicKey): SignatureSubpackets = apply { + addRevocationKey(true, revocationKey) + } + + override fun addRevocationKey(isCritical: Boolean, revocationKey: PGPPublicKey): SignatureSubpackets = apply { + addRevocationKey(isCritical, false, revocationKey) + } + + override fun addRevocationKey(isCritical: Boolean, isSensitive: Boolean, revocationKey: PGPPublicKey): SignatureSubpackets = apply { + val clazz = 0x80.toByte() or if (isSensitive) 0x40.toByte() else 0x00.toByte() + addRevocationKey(RevocationKey(isCritical, clazz, revocationKey.algorithm, revocationKey.fingerprint)) + } + + override fun addRevocationKey(revocationKey: RevocationKey): SignatureSubpackets = apply { + (this.revocationKeySubpackets as MutableList).add(revocationKey) + } + + override fun clearRevocationKeys(): SignatureSubpackets = apply { + (this.revocationKeySubpackets as MutableList).clear() + } + + override fun setFeatures(vararg features: Feature): SignatureSubpackets = apply { + setFeatures(true, *features) + } + + override fun setFeatures(isCritical: Boolean, vararg features: Feature): SignatureSubpackets = apply { + setFeatures(Features(isCritical, Feature.toBitmask(*features))) + } + + override fun setFeatures(features: Features?): SignatureSubpackets = apply { + this.featuresSubpacket = features + } + + override fun setIssuerFingerprintAndKeyId(key: PGPPublicKey): SignatureSubpackets = apply { + setIssuerKeyId(key.keyID) + setIssuerFingerprint(key) + } + + override fun setIssuerKeyId(keyId: Long): SignatureSubpackets = apply { + setIssuerKeyId(false, keyId) + } + + override fun setIssuerKeyId(isCritical: Boolean, keyId: Long): SignatureSubpackets = apply { + setIssuerKeyId(IssuerKeyID(isCritical, keyId)) + } + + override fun setIssuerKeyId(issuerKeyID: IssuerKeyID?): SignatureSubpackets = apply { + this.issuerKeyIdSubpacket = issuerKeyID + } + + override fun setIssuerFingerprint(isCritical: Boolean, issuer: PGPPublicKey): SignatureSubpackets = apply { + setIssuerFingerprint(IssuerFingerprint(isCritical, issuer.version, issuer.fingerprint)) + } + + override fun setIssuerFingerprint(issuer: PGPPublicKey): SignatureSubpackets = apply { + setIssuerFingerprint(false, issuer) + } + + override fun setIssuerFingerprint(fingerprint: IssuerFingerprint?): SignatureSubpackets = apply { + this.issuerFingerprintSubpacket = fingerprint + } + + override fun setSignatureCreationTime(creationTime: Date): SignatureSubpackets = apply { + setSignatureCreationTime(true, creationTime) + } + + override fun setSignatureCreationTime(isCritical: Boolean, creationTime: Date): SignatureSubpackets = apply { + setSignatureCreationTime(SignatureCreationTime(isCritical, creationTime)) + } + + override fun setSignatureCreationTime(creationTime: SignatureCreationTime?): SignatureSubpackets = apply { + this.signatureCreationTimeSubpacket = creationTime + } + override fun setSignatureExpirationTime(creationTime: Date, expirationTime: Date?): SignatureSubpackets = apply { + setSignatureExpirationTime(true, creationTime, expirationTime) + } + + override fun setSignatureExpirationTime(isCritical: Boolean, creationTime: Date, expirationTime: Date?): SignatureSubpackets = apply { + if (expirationTime != null) { + require(creationTime.toSecondsPrecision() < expirationTime.toSecondsPrecision()) { + "Expiration time MUST NOT be less or equal the creation time." + } + setSignatureExpirationTime(SignatureExpirationTime(isCritical, creationTime.secondsTill(expirationTime))) + } else { + setSignatureExpirationTime(SignatureExpirationTime(isCritical, 0)) + } + } + + override fun setSignatureExpirationTime(isCritical: Boolean, seconds: Long): SignatureSubpackets = apply { + enforceExpirationBounds(seconds) + setSignatureExpirationTime(SignatureExpirationTime(isCritical, seconds)) + } + + /** + * Enforce that
seconds
is within bounds of an unsigned 32bit number. + * Values less than 0 are illegal, as well as values greater 0xffffffff. + * + * @param seconds number to check + * @throws IllegalArgumentException in case of an under- or overflow + */ + private fun enforceExpirationBounds(seconds: Long) { + require(seconds <= 0xffffffffL) { + "Integer overflow. Seconds from creation to expiration (${seconds}) cannot be larger than ${0xffffffffL}." + } + require(seconds >= 0) { + "Seconds from creation to expiration cannot be less than 0." + } + } + + override fun setSignatureExpirationTime(expirationTime: SignatureExpirationTime?): SignatureSubpackets = apply { + this.signatureExpirationTimeSubpacket = expirationTime + } + + override fun setSignerUserId(userId: CharSequence): SignatureSubpackets = apply { + setSignerUserId(false, userId) + } + + override fun setSignerUserId(isCritical: Boolean, userId: CharSequence): SignatureSubpackets = apply { + setSignerUserId(SignerUserID(isCritical, userId.toString())) + } + + override fun setSignerUserId(signerUserID: SignerUserID?): SignatureSubpackets = apply { + this.signerUserIdSubpacket = signerUserID + } + + override fun addNotationData(isCritical: Boolean, notationName: String, notationValue: String): SignatureSubpackets = apply { + addNotationData(isCritical, true, notationName, notationValue) + } + + override fun addNotationData(isCritical: Boolean, isHumanReadable: Boolean, notationName: String, notationValue: String): SignatureSubpackets = apply { + addNotationData(NotationData(isCritical, isHumanReadable, notationName, notationValue)) + } + + override fun addNotationData(notationData: NotationData): SignatureSubpackets = apply { + (this.notationDataSubpackets as MutableList).add(notationData) + } + + override fun clearNotationData(): SignatureSubpackets = apply { + (this.notationDataSubpackets as MutableList).clear() + } + + override fun addIntendedRecipientFingerprint(recipientKey: PGPPublicKey): SignatureSubpackets = apply { + addIntendedRecipientFingerprint(false, recipientKey) + } + + override fun addIntendedRecipientFingerprint(isCritical: Boolean, recipientKey: PGPPublicKey): SignatureSubpackets = apply { + addIntendedRecipientFingerprint(IntendedRecipientFingerprint(isCritical, recipientKey.version, recipientKey.fingerprint)) + } + + override fun addIntendedRecipientFingerprint(intendedRecipient: IntendedRecipientFingerprint): SignatureSubpackets = apply { + (this.intendedRecipientFingerprintSubpackets as MutableList).add(intendedRecipient) + } + + override fun clearIntendedRecipientFingerprints(): SignatureSubpackets = apply { + (this.intendedRecipientFingerprintSubpackets as MutableList).clear() + } + + override fun setExportable(): SignatureSubpackets = apply { + setExportable(true) + } + + override fun setExportable(isExportable: Boolean): SignatureSubpackets = apply { + setExportable(true, isExportable) + } + + override fun setExportable(isCritical: Boolean, isExportable: Boolean): SignatureSubpackets = apply { + setExportable(Exportable(isCritical, isExportable)) + } + + override fun setExportable(exportable: Exportable?): SignatureSubpackets = apply { + this.exportableSubpacket = exportable + } + + override fun setPolicyUrl(policyUrl: URL): SignatureSubpackets = apply { + setPolicyUrl(false, policyUrl) + } + + override fun setPolicyUrl(isCritical: Boolean, policyUrl: URL): SignatureSubpackets = apply { + setPolicyUrl(PolicyURI(isCritical, policyUrl.toString())) + } + + override fun setPolicyUrl(policyUrl: PolicyURI?): SignatureSubpackets = apply { + this.policyURISubpacket = policyURISubpacket + } + + override fun setRegularExpression(regex: CharSequence): SignatureSubpackets = apply { + setRegularExpression(false, regex) + } + + override fun setRegularExpression(isCritical: Boolean, regex: CharSequence): SignatureSubpackets = apply { + setRegularExpression(RegularExpression(isCritical, regex.toString())) + } + + override fun setRegularExpression(regex: RegularExpression?): SignatureSubpackets = apply { + this.regularExpressionSubpacket = regex + } + + override fun setRevocable(): SignatureSubpackets = apply { + setRevocable(true) + } + + override fun setRevocable(isRevocable: Boolean): SignatureSubpackets = apply { + setRevocable(true, isRevocable) + } + + override fun setRevocable(isCritical: Boolean, isRevocable: Boolean): SignatureSubpackets = apply { + setRevocable(Revocable(isCritical, isRevocable)) + } + + override fun setRevocable(revocable: Revocable?): SignatureSubpackets = apply { + this.revocableSubpacket = revocable + } + + override fun setSignatureTarget(keyAlgorithm: PublicKeyAlgorithm, hashAlgorithm: HashAlgorithm, hashData: ByteArray): SignatureSubpackets = apply { + setSignatureTarget(true, keyAlgorithm, hashAlgorithm, hashData) + } + + override fun setSignatureTarget(isCritical: Boolean, keyAlgorithm: PublicKeyAlgorithm, hashAlgorithm: HashAlgorithm, hashData: ByteArray): SignatureSubpackets = apply { + setSignatureTarget(SignatureTarget(isCritical, keyAlgorithm.algorithmId, hashAlgorithm.algorithmId, hashData)) + } + + override fun setSignatureTarget(signatureTarget: SignatureTarget?): SignatureSubpackets = apply { + this.signatureTargetSubpacket = signatureTarget + } + + override fun setTrust(depth: Int, amount: Int): SignatureSubpackets = apply { + setTrust(true, depth, amount) + } + + override fun setTrust(isCritical: Boolean, depth: Int, amount: Int): SignatureSubpackets = apply { + setTrust(TrustSignature(isCritical, depth, amount)) + } + + override fun setTrust(trust: TrustSignature?): SignatureSubpackets = apply { + this.trustSubpacket = trust + } + + override fun addEmbeddedSignature(signature: PGPSignature): SignatureSubpackets = apply { + addEmbeddedSignature(true, signature) + } + + override fun addEmbeddedSignature(isCritical: Boolean, signature: PGPSignature): SignatureSubpackets = apply { + val sig = signature.encoded + val data = if (sig.size - 1 > 256) { + ByteArray(sig.size - 3) + } else { + ByteArray(sig.size - 2) + } + System.arraycopy(sig, sig.size - data.size, data, 0, data.size) + addEmbeddedSignature(EmbeddedSignature(isCritical, false, data)) + } + + override fun addEmbeddedSignature(embeddedSignature: EmbeddedSignature): SignatureSubpackets = apply { + (this.embeddedSignatureSubpackets as MutableList).add(embeddedSignature) + } + + override fun clearEmbeddedSignatures(): SignatureSubpackets = apply { + (this.embeddedSignatureSubpackets as MutableList).clear() + } + + fun addResidualSubpacket(subpacket: org.bouncycastle.bcpg.SignatureSubpacket): SignatureSubpackets = apply { + (residualSubpackets as MutableList).add(subpacket) + } +} \ No newline at end of file