diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/OpenPgpKeyGenerator.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/OpenPgpKeyGenerator.kt index c1e1a639..73a66b1b 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/OpenPgpKeyGenerator.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/OpenPgpKeyGenerator.kt @@ -23,6 +23,7 @@ import org.pgpainless.key.generation.type.rsa.RsaLength import org.pgpainless.key.generation.type.xdh.XDHSpec import org.pgpainless.policy.Policy import org.pgpainless.signature.builder.DirectKeySelfSignatureBuilder +import org.pgpainless.signature.builder.PrimaryKeyBindingSignatureBuilder import org.pgpainless.signature.builder.SelfSignatureBuilder import org.pgpainless.signature.builder.SubkeyBindingSignatureBuilder import org.pgpainless.signature.subpackets.SelfSignatureSubpackets @@ -738,14 +739,27 @@ abstract class ApplyToSubkey( bindingTime: Date, subpacketsCallback: SelfSignatureSubpackets.Callback ): PGPSignature { - return SubkeyBindingSignatureBuilder( - primaryKey.privateKey, primaryKey.publicKey, hashAlgorithm) + return SubkeyBindingSignatureBuilder(primaryKey, hashAlgorithm) .applyCallback( - subpacketsCallback.then( - SelfSignatureSubpackets.applyHashed { - setSignatureCreationTime(bindingTime) - })) - .build(subkey.publicKey) + subpacketsCallback + .then( + SelfSignatureSubpackets.applyHashed { + setSignatureCreationTime(bindingTime) + }) + .then( + SelfSignatureSubpackets.applyHashed { + if (isSigningCapable(getKeyFlags())) { + addEmbeddedSignature( + PrimaryKeyBindingSignatureBuilder(subkey, hashAlgorithm) + .build(primaryKey)) + } + })) + .build(subkey) + } + + private fun isSigningCapable(flags: List?): Boolean { + val signCapableFlags = listOf(KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER) + return flags?.any { signCapableFlags.contains(it) } ?: false } } } diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/AbstractSignatureBuilder.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/AbstractSignatureBuilder.kt index b6ee5006..eb4c9f1f 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/AbstractSignatureBuilder.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/AbstractSignatureBuilder.kt @@ -6,6 +6,7 @@ package org.pgpainless.signature.builder import java.util.function.Predicate import org.bouncycastle.openpgp.PGPException +import org.bouncycastle.openpgp.PGPKeyPair import org.bouncycastle.openpgp.PGPPrivateKey import org.bouncycastle.openpgp.PGPPublicKey import org.bouncycastle.openpgp.PGPSecretKey @@ -53,6 +54,27 @@ abstract class AbstractSignatureBuilder>( hashedSubpackets, unhashedSubpackets) + @Throws(PGPException::class) + constructor( + signatureType: SignatureType, + signingKey: PGPKeyPair, + hashAlgorithm: HashAlgorithm, + hashedSubpackets: SignatureSubpackets, + unhashedSubpackets: SignatureSubpackets + ) : this( + signingKey.privateKey, + signingKey.publicKey, + hashAlgorithm, + signatureType, + hashedSubpackets, + unhashedSubpackets) + + @Throws(PGPException::class) + constructor( + signingKey: PGPKeyPair, + archetypeSignature: PGPSignature + ) : this(signingKey.privateKey, signingKey.publicKey, archetypeSignature) + @Throws(PGPException::class) constructor( privateSigningKey: PGPPrivateKey, diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/DirectKeySelfSignatureBuilder.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/DirectKeySelfSignatureBuilder.kt index 3df219e4..e58adad3 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/DirectKeySelfSignatureBuilder.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/DirectKeySelfSignatureBuilder.kt @@ -6,6 +6,7 @@ package org.pgpainless.signature.builder import java.util.function.Predicate import org.bouncycastle.openpgp.PGPException +import org.bouncycastle.openpgp.PGPKeyPair import org.bouncycastle.openpgp.PGPPrivateKey import org.bouncycastle.openpgp.PGPPublicKey import org.bouncycastle.openpgp.PGPSecretKey @@ -32,6 +33,12 @@ class DirectKeySelfSignatureBuilder : AbstractSignatureBuilder { @@ -26,6 +29,18 @@ class RevocationSignatureBuilder : AbstractSignatureBuilder { oldCertification: PGPSignature ) : super(primaryKey, primaryKeyProtector, oldCertification) + @Throws(PGPException::class) + constructor( + primaryKey: PGPKeyPair, + oldCertification: PGPSignature + ) : this(primaryKey.privateKey, primaryKey.publicKey, oldCertification) + @Throws(PGPException::class) constructor( privatePrimaryKey: PGPPrivateKey, @@ -60,6 +67,13 @@ class SelfSignatureBuilder : AbstractSignatureBuilder { oldCertification: PGPSignature ) : super(privatePrimaryKey, publicPrimaryKey, oldCertification) + @Throws(PGPException::class) + constructor( + primaryKey: PGPKeyPair, + signatureType: SignatureType = SignatureType.POSITIVE_CERTIFICATION, + hashAlgorithm: HashAlgorithm + ) : this(primaryKey.privateKey, primaryKey.publicKey, signatureType, hashAlgorithm) + @Throws(PGPException::class) constructor( privatePrimaryKey: PGPPrivateKey, diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/SubkeyBindingSignatureBuilder.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/SubkeyBindingSignatureBuilder.kt index 6b8b3a0d..731ad276 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/SubkeyBindingSignatureBuilder.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/SubkeyBindingSignatureBuilder.kt @@ -6,6 +6,7 @@ package org.pgpainless.signature.builder import java.util.function.Predicate import org.bouncycastle.openpgp.PGPException +import org.bouncycastle.openpgp.PGPKeyPair import org.bouncycastle.openpgp.PGPPrivateKey import org.bouncycastle.openpgp.PGPPublicKey import org.bouncycastle.openpgp.PGPSecretKey @@ -25,6 +26,12 @@ class SubkeyBindingSignatureBuilder : AbstractSignatureBuilder get() = Predicate { it == SignatureType.SUBKEY_BINDING } + @Throws(PGPException::class) + constructor( + signingKey: PGPKeyPair, + hashAlgorithm: HashAlgorithm = negotiateHashAlgorithm(signingKey.publicKey) + ) : this(signingKey.privateKey, signingKey.publicKey, hashAlgorithm) + @Throws(PGPException::class) constructor( signingKey: PGPPrivateKey, @@ -84,4 +91,7 @@ class SubkeyBindingSignatureBuilder : AbstractSignatureBuilder