1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-09 18:29:39 +02:00

Port SignatureBuilders over to new classes

This commit is contained in:
Paul Schaub 2025-02-19 12:43:38 +01:00
parent 94dc25aa8b
commit 3feaf9134b
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
18 changed files with 398 additions and 246 deletions

View file

@ -409,7 +409,8 @@ class OpenPgpMessageInputStream(
val decryptionKeyCandidates = getDecryptionKeys(pkesk)
for (decryptionKeys in decryptionKeyCandidates) {
val secretKey = decryptionKeys.getSecretKeyFor(pkesk)!!
if (!secretKey.isEncryptionKey && !options.getAllowDecryptionWithNonEncryptionKey()) {
if (!secretKey.isEncryptionKey &&
!options.getAllowDecryptionWithNonEncryptionKey()) {
LOGGER.debug(
"Message is encrypted for ${secretKey.keyIdentifier}, but the key is not encryption capable.")
continue

View file

@ -11,8 +11,8 @@ import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey
import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPPrivateKey
/**
* Tuple class used to identify a subkey (component key) by fingerprints of the certificate,
* as well as the component keys fingerprint.
* Tuple class used to identify a subkey (component key) by fingerprints of the certificate, as well
* as the component keys fingerprint.
*/
class SubkeyIdentifier(
val certificateFingerprint: OpenPgpFingerprint,
@ -22,9 +22,12 @@ class SubkeyIdentifier(
/**
* Constructor for a [SubkeyIdentifier] pointing to the primary key identified by the
* [certificateFingerprint].
*
* @param certificateFingerprint primary key fingerprint
*/
constructor(certificateFingerprint: OpenPgpFingerprint) : this(certificateFingerprint, certificateFingerprint)
constructor(
certificateFingerprint: OpenPgpFingerprint
) : this(certificateFingerprint, certificateFingerprint)
/**
* Constructor for a [SubkeyIdentifier] pointing to the primary key of the given [PGPKeyRing].
@ -45,7 +48,10 @@ class SubkeyIdentifier(
* [componentKeyId]) from the given [certificate].
*/
@Deprecated("Pass in a KeyIdentifier instead of a keyId.")
constructor(certificate: PGPKeyRing, componentKeyId: Long) : this(certificate, KeyIdentifier(componentKeyId))
constructor(
certificate: PGPKeyRing,
componentKeyId: Long
) : this(certificate, KeyIdentifier(componentKeyId))
/**
* Constructor for a [SubkeyIdentifier] pointing to the given [componentKey].
@ -54,18 +60,14 @@ class SubkeyIdentifier(
*/
constructor(
componentKey: OpenPGPComponentKey
) : this(
OpenPgpFingerprint.of(componentKey.certificate),
OpenPgpFingerprint.of(componentKey))
) : this(OpenPgpFingerprint.of(componentKey.certificate), OpenPgpFingerprint.of(componentKey))
/**
* Constructor for a [SubkeyIdentifier] pointing to the given [componentKey].
*/
/** Constructor for a [SubkeyIdentifier] pointing to the given [componentKey]. */
constructor(componentKey: OpenPGPPrivateKey) : this(componentKey.secretKey)
/**
* Constructor for a [SubkeyIdentifier] pointing to a component key (identified by
* the [componentKeyFingerprint]) of the given [certificate].
* Constructor for a [SubkeyIdentifier] pointing to a component key (identified by the
* [componentKeyFingerprint]) of the given [certificate].
*
* @param certificate certificate
* @param componentKeyFingerprint fingerprint of the component key
@ -92,48 +94,34 @@ class SubkeyIdentifier(
?: throw NoSuchElementException(
"OpenPGP key does not contain subkey $componentKeyIdentifier")))
@Deprecated("Use certificateFingerprint instead.",
replaceWith = ReplaceWith("certificateFingerprint")
)
@Deprecated(
"Use certificateFingerprint instead.", replaceWith = ReplaceWith("certificateFingerprint"))
val primaryKeyFingerprint: OpenPgpFingerprint = certificateFingerprint
@Deprecated("Use componentKeyFingerprint instead.",
@Deprecated(
"Use componentKeyFingerprint instead.",
replaceWith = ReplaceWith("componentKeyFingerprint"))
val subkeyFingerprint: OpenPgpFingerprint = componentKeyFingerprint
/**
* [KeyIdentifier] of the component key.
*/
/** [KeyIdentifier] of the component key. */
val keyIdentifier = componentKeyFingerprint.keyIdentifier
/**
* [KeyIdentifier] of the component key.
*/
/** [KeyIdentifier] of the component key. */
val componentKeyIdentifier = keyIdentifier
/**
* [KeyIdentifier] of the primary key of the certificate the component key belongs to.
*/
/** [KeyIdentifier] of the primary key of the certificate the component key belongs to. */
val certificateIdentifier = certificateFingerprint.keyIdentifier
/**
* Key-ID of the component key.
*/
/** Key-ID of the component key. */
@Deprecated("Use of key-ids is discouraged.") val keyId = keyIdentifier.keyId
/**
* Fingerprint of the component key.
*/
/** Fingerprint of the component key. */
val fingerprint = componentKeyFingerprint
/**
* Key-ID of the component key.
*/
/** Key-ID of the component key. */
@Deprecated("Use of key-ids is discouraged.") val subkeyId = componentKeyIdentifier.keyId
/**
* Key-ID of the primary key of the certificate the component key belongs to.
*/
/** Key-ID of the primary key of the certificate the component key belongs to. */
@Deprecated("Use of key-ids is discouraged.") val primaryKeyId = certificateIdentifier.keyId
val isPrimaryKey = certificateIdentifier.matches(componentKeyIdentifier)

View file

@ -7,9 +7,11 @@ package org.pgpainless.key.certification
import java.util.*
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPPublicKeyRing
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSecretKeyRing
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.api.OpenPGPCertificate
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.api.OpenPGPSignature
import org.pgpainless.PGPainless
import org.pgpainless.algorithm.CertificationType
import org.pgpainless.algorithm.KeyFlag
@ -42,17 +44,34 @@ class CertifyCertificate {
* @param certificate certificate
* @return API
*/
@JvmOverloads
fun userIdOnCertificate(
userId: CharSequence,
certificate: OpenPGPCertificate,
certificationType: CertificationType = CertificationType.GENERIC
): CertificationOnUserId = CertificationOnUserId(userId, certificate, certificationType)
/**
* Create a certification over a User-Id. By default, this method will use
* [CertificationType.GENERIC] to create the signature.
*
* @param userId user-id to certify
* @param certificate certificate
* @return API
*/
@Deprecated("Pass in an OpenPGPCertificate instead of PGPPublicKeyRing.")
fun userIdOnCertificate(userId: String, certificate: PGPPublicKeyRing): CertificationOnUserId =
userIdOnCertificate(userId, certificate, CertificationType.GENERIC)
/**
* Create a certification of the given [CertificationType] over a User-Id.
*
* @param userid user-id to certify
* @param userId user-id to certify
* @param certificate certificate
* @param certificationType type of signature
* @return API
*/
@Deprecated("Pass in an OpenPGPCertificate instead of PGPPublicKeyRing.")
fun userIdOnCertificate(
userId: String,
certificate: PGPPublicKeyRing,
@ -67,6 +86,19 @@ class CertifyCertificate {
* @param certificate certificate
* @return API
*/
@JvmOverloads
fun certificate(certificate: OpenPGPCertificate, trustworthiness: Trustworthiness? = null) =
DelegationOnCertificate(certificate, trustworthiness)
/**
* Create a delegation (direct key signature) over a certificate. This can be used to mark a
* certificate as a trusted introducer (see [certificate] method with [Trustworthiness]
* argument).
*
* @param certificate certificate
* @return API
*/
@Deprecated("Pass in an OpenPGPCertificate instead of PGPPublicKeyRing.")
fun certificate(certificate: PGPPublicKeyRing): DelegationOnCertificate =
certificate(certificate, null)
@ -79,15 +111,35 @@ class CertifyCertificate {
* @param trustworthiness trustworthiness of the certificate
* @return API
*/
@Deprecated("Pass in an OpenPGPCertificate instead of PGPPublicKeyRing.")
fun certificate(certificate: PGPPublicKeyRing, trustworthiness: Trustworthiness?) =
DelegationOnCertificate(certificate, trustworthiness)
class CertificationOnUserId(
val userId: String,
val certificate: PGPPublicKeyRing,
val userId: CharSequence,
val certificate: OpenPGPCertificate,
val certificationType: CertificationType
) {
@Deprecated("Use primary constructor instead.")
constructor(
userId: String,
certificate: PGPPublicKeyRing,
certificationType: CertificationType
) : this(userId, PGPainless.getInstance().toCertificate(certificate), certificationType)
fun withKey(
key: OpenPGPKey,
protector: SecretKeyRingProtector
): CertificationOnUserIdWithSubpackets {
val secretKey = getCertifyingSecretKey(key)
val sigBuilder =
ThirdPartyCertificationSignatureBuilder(
certificationType.asSignatureType(), secretKey, protector)
return CertificationOnUserIdWithSubpackets(certificate, userId, sigBuilder)
}
/**
* Create the certification using the given key.
*
@ -96,26 +148,27 @@ class CertifyCertificate {
* @return API
* @throws PGPException in case of an OpenPGP related error
*/
@Deprecated("Pass in an OpenPGPKey instead of a PGPSecretKeyRing.")
fun withKey(
certificationKey: PGPSecretKeyRing,
protector: SecretKeyRingProtector
): CertificationOnUserIdWithSubpackets {
val secretKey = getCertifyingSecretKey(certificationKey)
val sigBuilder =
ThirdPartyCertificationSignatureBuilder(
certificationType.asSignatureType(), secretKey, protector)
return CertificationOnUserIdWithSubpackets(certificate, userId, sigBuilder)
}
): CertificationOnUserIdWithSubpackets =
withKey(PGPainless.getInstance().toKey(certificationKey), protector)
}
class CertificationOnUserIdWithSubpackets(
val certificate: PGPPublicKeyRing,
val userId: String,
val certificate: OpenPGPCertificate,
val userId: CharSequence,
val sigBuilder: ThirdPartyCertificationSignatureBuilder
) {
@Deprecated("Pass in an OpenPGPCertificate instead of a PGPPublicKeyRing.")
constructor(
certificate: PGPPublicKeyRing,
userId: String,
sigBuilder: ThirdPartyCertificationSignatureBuilder
) : this(PGPainless.getInstance().toCertificate(certificate), userId, sigBuilder)
/**
* Apply the given signature subpackets and build the certification.
*
@ -139,16 +192,38 @@ class CertifyCertificate {
fun build(): CertificationResult {
val signature = sigBuilder.build(certificate, userId)
val certifiedCertificate =
KeyRingUtils.injectCertification(certificate, userId, signature)
OpenPGPCertificate(
KeyRingUtils.injectCertification(
certificate.pgpPublicKeyRing, userId, signature.signature))
return CertificationResult(certifiedCertificate, signature)
}
}
class DelegationOnCertificate(
val certificate: PGPPublicKeyRing,
val certificate: OpenPGPCertificate,
val trustworthiness: Trustworthiness?
) {
@Deprecated("Pass in an OpenPGPCertificate instead of PGPPublicKeyRing.")
constructor(
certificate: PGPPublicKeyRing,
trustworthiness: Trustworthiness?
) : this(PGPainless.getInstance().toCertificate(certificate), trustworthiness)
fun withKey(
key: OpenPGPKey,
protector: SecretKeyRingProtector
): DelegationOnCertificateWithSubpackets {
val secretKey = getCertifyingSecretKey(key)
val sigBuilder = ThirdPartyDirectKeySignatureBuilder(secretKey, protector)
if (trustworthiness != null) {
sigBuilder.hashedSubpackets.setTrust(
true, trustworthiness.depth, trustworthiness.amount)
}
return DelegationOnCertificateWithSubpackets(certificate, sigBuilder)
}
/**
* Build the delegation using the given certification key.
*
@ -157,25 +232,25 @@ class CertifyCertificate {
* @return API
* @throws PGPException in case of an OpenPGP related error
*/
@Deprecated("Pass in an OpenPGPKey instead of PGPSecretKeyRing.")
fun withKey(
certificationKey: PGPSecretKeyRing,
protector: SecretKeyRingProtector
): DelegationOnCertificateWithSubpackets {
val secretKey = getCertifyingSecretKey(certificationKey)
val sigBuilder = ThirdPartyDirectKeySignatureBuilder(secretKey, protector)
if (trustworthiness != null) {
sigBuilder.hashedSubpackets.setTrust(
true, trustworthiness.depth, trustworthiness.amount)
}
return DelegationOnCertificateWithSubpackets(certificate, sigBuilder)
}
): DelegationOnCertificateWithSubpackets =
withKey(PGPainless.getInstance().toKey(certificationKey), protector)
}
class DelegationOnCertificateWithSubpackets(
val certificate: PGPPublicKeyRing,
val certificate: OpenPGPCertificate,
val sigBuilder: ThirdPartyDirectKeySignatureBuilder
) {
@Deprecated("Pass in an OpenPGPCertificate instead of a PGPPublicKeyRing.")
constructor(
certificate: PGPPublicKeyRing,
sigBuilder: ThirdPartyDirectKeySignatureBuilder
) : this(PGPainless.getInstance().toCertificate(certificate), sigBuilder)
/**
* Apply the given signature subpackets and build the delegation signature.
*
@ -197,10 +272,14 @@ class CertifyCertificate {
* @throws PGPException in case of an OpenPGP related error
*/
fun build(): CertificationResult {
val delegatedKey = certificate.publicKey
val delegatedKey = certificate.primaryKey
val delegation = sigBuilder.build(delegatedKey)
val delegatedCertificate =
KeyRingUtils.injectCertification(certificate, delegatedKey, delegation)
OpenPGPCertificate(
KeyRingUtils.injectCertification(
certificate.pgpPublicKeyRing,
delegatedKey.pgpPublicKey,
delegation.signature))
return CertificationResult(delegatedCertificate, delegation)
}
}
@ -212,13 +291,18 @@ class CertifyCertificate {
* @param certification the newly created signature
*/
data class CertificationResult(
val certifiedCertificate: PGPPublicKeyRing,
val certification: PGPSignature
)
val certifiedCertificate: OpenPGPCertificate,
val certification: OpenPGPSignature
) {
val publicKeyRing: PGPPublicKeyRing = certifiedCertificate.pgpPublicKeyRing
val pgpSignature: PGPSignature = certification.signature
}
companion object {
@JvmStatic
private fun getCertifyingSecretKey(certificationKey: PGPSecretKeyRing): PGPSecretKey {
private fun getCertifyingSecretKey(
certificationKey: OpenPGPKey
): OpenPGPKey.OpenPGPSecretKey {
val now = Date()
val info = PGPainless.inspectKeyRing(certificationKey, now)

View file

@ -12,6 +12,8 @@ import openpgp.openPgpKeyId
import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.bcpg.sig.KeyExpirationTime
import org.bouncycastle.openpgp.*
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.api.OpenPGPSignature
import org.pgpainless.PGPainless
import org.pgpainless.PGPainless.Companion.inspectKeyRing
import org.pgpainless.algorithm.AlgorithmSuite
@ -38,10 +40,16 @@ import org.pgpainless.signature.subpackets.*
import org.pgpainless.util.Passphrase
import org.pgpainless.util.selection.userid.SelectUserId
class SecretKeyRingEditor(
var secretKeyRing: PGPSecretKeyRing,
override val referenceTime: Date = Date()
) : SecretKeyRingEditorInterface {
class SecretKeyRingEditor(var key: OpenPGPKey, override val referenceTime: Date = Date()) :
SecretKeyRingEditorInterface {
private var secretKeyRing: PGPSecretKeyRing = key.pgpSecretKeyRing
@JvmOverloads
constructor(
secretKeyRing: PGPSecretKeyRing,
referenceTime: Date = Date()
) : this(PGPainless.getInstance().toKey(secretKeyRing), referenceTime)
override fun addUserId(
userId: CharSequence,
@ -74,7 +82,7 @@ class SecretKeyRingEditor(
}
val builder =
SelfSignatureBuilder(primaryKey, protector).apply {
SelfSignatureBuilder(key.primarySecretKey, protector).apply {
hashedSubpackets.setSignatureCreationTime(referenceTime)
setSignatureType(SignatureType.POSITIVE_CERTIFICATION)
}
@ -88,6 +96,7 @@ class SecretKeyRingEditor(
builder.applyCallback(callback)
secretKeyRing =
injectCertification(secretKeyRing, sanitizedUserId, builder.build(sanitizedUserId))
key = PGPainless.getInstance().toKey(secretKeyRing)
return this
}
@ -294,13 +303,14 @@ class SecretKeyRingEditor(
false,
subkeyProtector.getEncryptor(subkey.keyID))
val skBindingBuilder =
SubkeyBindingSignatureBuilder(primaryKey, primaryKeyProtector, hashAlgorithm)
SubkeyBindingSignatureBuilder(key.primarySecretKey, primaryKeyProtector, hashAlgorithm)
skBindingBuilder.apply {
hashedSubpackets.setSignatureCreationTime(referenceTime)
hashedSubpackets.setKeyFlags(flags)
if (subkeyAlgorithm.isSigningCapable()) {
val pkBindingBuilder =
PrimaryKeyBindingSignatureBuilder(secretSubkey, subkeyProtector, hashAlgorithm)
PrimaryKeyBindingSignatureBuilder(
key.primarySecretKey, subkeyProtector, hashAlgorithm)
pkBindingBuilder.hashedSubpackets.setSignatureCreationTime(referenceTime)
hashedSubpackets.addEmbeddedSignature(pkBindingBuilder.build(primaryKey.publicKey))
}
@ -430,7 +440,7 @@ class SecretKeyRingEditor(
injectCertification(
secretKeyRing,
secretKeyRing.publicKey,
reissueDirectKeySignature(expiration, protector, prevDirectKeySig))
reissueDirectKeySignature(expiration, protector, prevDirectKeySig).signature)
}
val primaryUserId =
@ -590,12 +600,11 @@ class SecretKeyRingEditor(
revokeeSubkey: PGPPublicKey,
callback: RevocationSignatureSubpackets.Callback?
): PGPSignature {
val primaryKey = secretKeyRing.secretKey
val signatureType =
if (revokeeSubkey.isMasterKey) SignatureType.KEY_REVOCATION
else SignatureType.SUBKEY_REVOCATION
return RevocationSignatureBuilder(signatureType, primaryKey, protector)
return RevocationSignatureBuilder(signatureType, key.primarySecretKey, protector)
.apply { applyCallback(callback) }
.build(revokeeSubkey)
}
@ -606,7 +615,7 @@ class SecretKeyRingEditor(
callback: RevocationSignatureSubpackets.Callback?
): SecretKeyRingEditorInterface {
RevocationSignatureBuilder(
SignatureType.CERTIFICATION_REVOCATION, secretKeyRing.secretKey, protector)
SignatureType.CERTIFICATION_REVOCATION, key.primarySecretKey, protector)
.apply {
hashedSubpackets.setSignatureCreationTime(referenceTime)
applyCallback(callback)
@ -635,7 +644,7 @@ class SecretKeyRingEditor(
prevUserIdSig: PGPSignature
): PGPSignature {
val builder =
SelfSignatureBuilder(secretKeyRing.secretKey, secretKeyRingProtector, prevUserIdSig)
SelfSignatureBuilder(key.primarySecretKey, secretKeyRingProtector, prevUserIdSig)
builder.hashedSubpackets.setSignatureCreationTime(referenceTime)
builder.applyCallback(
object : SelfSignatureSubpackets.Callback {
@ -654,7 +663,7 @@ class SecretKeyRingEditor(
@Nonnull primaryUserId: String,
@Nonnull prevUserIdSig: PGPSignature
): PGPSignature {
return SelfSignatureBuilder(secretKeyRing.secretKey, secretKeyRingProtector, prevUserIdSig)
return SelfSignatureBuilder(key.primarySecretKey, secretKeyRingProtector, prevUserIdSig)
.apply {
hashedSubpackets.setSignatureCreationTime(referenceTime)
applyCallback(
@ -680,9 +689,9 @@ class SecretKeyRingEditor(
expiration: Date?,
secretKeyRingProtector: SecretKeyRingProtector,
prevDirectKeySig: PGPSignature
): PGPSignature {
): OpenPGPSignature {
return DirectKeySelfSignatureBuilder(
secretKeyRing.secretKey, secretKeyRingProtector, prevDirectKeySig)
secretKeyRing, secretKeyRingProtector, prevDirectKeySig)
.apply {
hashedSubpackets.setSignatureCreationTime(referenceTime)
applyCallback(
@ -709,11 +718,11 @@ class SecretKeyRingEditor(
prevSubkeyBindingSignature: PGPSignature
): PGPSignature {
val primaryKey = secretKeyRing.publicKey
val secretPrimaryKey = secretKeyRing.secretKey
val secretSubkey: PGPSecretKey? = secretKeyRing.getSecretKey(subkey.keyID)
val builder =
SubkeyBindingSignatureBuilder(secretPrimaryKey, protector, prevSubkeyBindingSignature)
SubkeyBindingSignatureBuilder(
key.primarySecretKey, protector, prevSubkeyBindingSignature)
builder.hashedSubpackets.apply {
// set expiration
setSignatureCreationTime(referenceTime)
@ -732,7 +741,8 @@ class SecretKeyRingEditor(
// create new embedded back-sig
clearEmbeddedSignatures()
addEmbeddedSignature(
PrimaryKeyBindingSignatureBuilder(secretSubkey, protector)
PrimaryKeyBindingSignatureBuilder(
key.getSecretKey(subkey.keyIdentifier), protector)
.build(primaryKey))
}
}

View file

@ -6,11 +6,11 @@ package org.pgpainless.signature.builder
import java.util.function.Predicate
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPPrivateKey
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.PGPSignatureGenerator
import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.pgpainless.PGPainless
import org.pgpainless.algorithm.HashAlgorithm
import org.pgpainless.algorithm.SignatureType
@ -23,8 +23,7 @@ import org.pgpainless.signature.subpackets.SignatureSubpackets
import org.pgpainless.signature.subpackets.SignatureSubpacketsHelper
abstract class AbstractSignatureBuilder<B : AbstractSignatureBuilder<B>>(
protected val privateSigningKey: PGPPrivateKey,
protected val publicSigningKey: PGPPublicKey,
protected val signingKey: OpenPGPKey.OpenPGPPrivateKey,
protected var _hashAlgorithm: HashAlgorithm,
protected var _signatureType: SignatureType,
protected val _hashedSubpackets: SignatureSubpackets,
@ -42,14 +41,13 @@ abstract class AbstractSignatureBuilder<B : AbstractSignatureBuilder<B>>(
@Throws(PGPException::class)
protected constructor(
signatureType: SignatureType,
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector,
hashAlgorithm: HashAlgorithm,
hashedSubpackets: SignatureSubpackets,
unhashedSubpackets: SignatureSubpackets
) : this(
UnlockSecretKey.unlockSecretKey(signingKey, protector),
signingKey.publicKey,
hashAlgorithm,
signatureType,
hashedSubpackets,
@ -58,27 +56,28 @@ abstract class AbstractSignatureBuilder<B : AbstractSignatureBuilder<B>>(
@Throws(PGPException::class)
constructor(
signatureType: SignatureType,
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector
) : this(
signatureType,
signingKey,
protector,
negotiateHashAlgorithm(signingKey.publicKey),
SignatureSubpackets.createHashedSubpackets(signingKey.publicKey),
negotiateHashAlgorithm(signingKey),
SignatureSubpackets.createHashedSubpackets(signingKey.pgpSecretKey.publicKey),
SignatureSubpackets.createEmptySubpackets())
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector,
archetypeSignature: PGPSignature
) : this(
SignatureType.requireFromCode(archetypeSignature.signatureType),
signingKey,
protector,
negotiateHashAlgorithm(signingKey.publicKey),
SignatureSubpackets.refreshHashedSubpackets(signingKey.publicKey, archetypeSignature),
negotiateHashAlgorithm(signingKey),
SignatureSubpackets.refreshHashedSubpackets(
signingKey.publicKey.pgpPublicKey, archetypeSignature),
SignatureSubpackets.refreshUnhashedSubpackets(archetypeSignature))
val hashAlgorithm = _hashAlgorithm
@ -113,11 +112,11 @@ abstract class AbstractSignatureBuilder<B : AbstractSignatureBuilder<B>>(
PGPSignatureGenerator(
ImplementationFactory.getInstance()
.getPGPContentSignerBuilder(
publicSigningKey.algorithm, hashAlgorithm.algorithmId))
signingKey.publicKey.pgpPublicKey.algorithm, hashAlgorithm.algorithmId))
.apply {
setUnhashedSubpackets(SignatureSubpacketsHelper.toVector(_unhashedSubpackets))
setHashedSubpackets(SignatureSubpacketsHelper.toVector(_hashedSubpackets))
init(_signatureType.code, privateSigningKey)
init(_signatureType.code, signingKey.keyPair.privateKey)
}
companion object {
@ -133,5 +132,9 @@ abstract class AbstractSignatureBuilder<B : AbstractSignatureBuilder<B>>(
HashAlgorithmNegotiator.negotiateSignatureHashAlgorithm(PGPainless.getPolicy())
.negotiateHashAlgorithm(
OpenPgpKeyAttributeUtil.getOrGuessPreferredHashAlgorithms(publicKey))
@JvmStatic
fun negotiateHashAlgorithm(key: OpenPGPComponentKey): HashAlgorithm =
negotiateHashAlgorithm(key.pgpPublicKey)
}
}

View file

@ -6,8 +6,12 @@ package org.pgpainless.signature.builder
import java.util.function.Predicate
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSecretKeyRing
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentSignature
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.api.OpenPGPSignature
import org.pgpainless.PGPainless
import org.pgpainless.algorithm.SignatureType
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets
@ -23,14 +27,24 @@ class DirectKeySelfSignatureBuilder : AbstractSignatureBuilder<DirectKeySelfSign
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKeyRing: PGPSecretKeyRing,
protector: SecretKeyRingProtector,
archetypeSignature: PGPSignature
) : this(
PGPainless.getInstance().toKey(signingKeyRing).primarySecretKey,
protector,
archetypeSignature)
@Throws(PGPException::class)
constructor(
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector,
archetypeSignature: PGPSignature
) : super(signingKey, protector, archetypeSignature)
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector
) : super(SignatureType.DIRECT_KEY, signingKey, protector)
@ -45,6 +59,8 @@ class DirectKeySelfSignatureBuilder : AbstractSignatureBuilder<DirectKeySelfSign
}
@Throws(PGPException::class)
fun build(): PGPSignature =
buildAndInitSignatureGenerator().let { it.generateCertification(publicSigningKey) }
fun build(): OpenPGPSignature =
buildAndInitSignatureGenerator()
.generateCertification(signingKey.publicKey.pgpPublicKey)
.let { OpenPGPComponentSignature(it, signingKey.publicKey, signingKey.publicKey) }
}

View file

@ -7,8 +7,8 @@ package org.pgpainless.signature.builder
import java.util.function.Predicate
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.pgpainless.algorithm.HashAlgorithm
import org.pgpainless.algorithm.SignatureType
import org.pgpainless.key.protection.SecretKeyRingProtector
@ -28,13 +28,13 @@ class PrimaryKeyBindingSignatureBuilder :
@Throws(PGPException::class)
constructor(
signingSubkey: PGPSecretKey,
signingSubkey: OpenPGPKey.OpenPGPSecretKey,
subkeyProtector: SecretKeyRingProtector
) : super(SignatureType.PRIMARYKEY_BINDING, signingSubkey, subkeyProtector)
@Throws(PGPException::class)
constructor(
signingSubkey: PGPSecretKey,
signingSubkey: OpenPGPKey.OpenPGPSecretKey,
subkeyProtector: SecretKeyRingProtector,
hashAlgorithm: HashAlgorithm
) : super(
@ -42,7 +42,7 @@ class PrimaryKeyBindingSignatureBuilder :
signingSubkey,
subkeyProtector,
hashAlgorithm,
SignatureSubpackets.createHashedSubpackets(signingSubkey.publicKey),
SignatureSubpackets.createHashedSubpackets(signingSubkey.publicKey.pgpPublicKey),
SignatureSubpackets.createEmptySubpackets())
val hashedSubpackets: SelfSignatureSubpackets = _hashedSubpackets
@ -57,5 +57,6 @@ class PrimaryKeyBindingSignatureBuilder :
@Throws(PGPException::class)
fun build(primaryKey: PGPPublicKey): PGPSignature =
buildAndInitSignatureGenerator().generateCertification(primaryKey, publicSigningKey)
buildAndInitSignatureGenerator()
.generateCertification(primaryKey, signingKey.publicKey.pgpPublicKey)
}

View file

@ -7,14 +7,20 @@ package org.pgpainless.signature.builder
import java.util.function.Predicate
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.pgpainless.algorithm.SignatureType
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.signature.subpackets.RevocationSignatureSubpackets
/** [AbstractSignatureBuilder] subclass devoted to revocation signatures. */
class RevocationSignatureBuilder : AbstractSignatureBuilder<RevocationSignatureBuilder> {
class RevocationSignatureBuilder
@Throws(PGPException::class)
constructor(
signatureType: SignatureType,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector
) : AbstractSignatureBuilder<RevocationSignatureBuilder>(signatureType, signingKey, protector) {
override val signatureTypePredicate: Predicate<SignatureType>
get() =
@ -26,15 +32,6 @@ class RevocationSignatureBuilder : AbstractSignatureBuilder<RevocationSignatureB
SignatureType.CERTIFICATION_REVOCATION)
}
@Throws(PGPException::class)
constructor(
signatureType: SignatureType,
signingKey: PGPSecretKey,
protector: SecretKeyRingProtector
) : super(signatureType, signingKey, protector) {
hashedSubpackets.setRevocable(false)
}
val hashedSubpackets: RevocationSignatureSubpackets = _hashedSubpackets
val unhashedSubpackets: RevocationSignatureSubpackets = _unhashedSubpackets
@ -52,9 +49,9 @@ class RevocationSignatureBuilder : AbstractSignatureBuilder<RevocationSignatureB
require(revokeeKey.isMasterKey) {
"Signature type is KEY_REVOCATION, but provided revokee does not appear to be a primary key."
}
it.generateCertification(publicSigningKey)
it.generateCertification(signingKey.publicKey.pgpPublicKey)
} else {
it.generateCertification(publicSigningKey, revokeeKey)
it.generateCertification(signingKey.publicKey.pgpPublicKey, revokeeKey)
}
}
@ -66,5 +63,9 @@ class RevocationSignatureBuilder : AbstractSignatureBuilder<RevocationSignatureB
"Signature type is != CERTIFICATION_REVOCATION."
}
}
.generateCertification(revokeeUserId.toString(), publicSigningKey)
.generateCertification(revokeeUserId.toString(), signingKey.publicKey.pgpPublicKey)
init {
hashedSubpackets.setRevocable(false)
}
}

View file

@ -6,9 +6,9 @@ package org.pgpainless.signature.builder
import java.util.function.Predicate
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVector
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.pgpainless.algorithm.SignatureType
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets
@ -31,20 +31,20 @@ class SelfSignatureBuilder : AbstractSignatureBuilder<SelfSignatureBuilder> {
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector
) : super(SignatureType.GENERIC_CERTIFICATION, signingKey, protector)
@Throws(PGPException::class)
constructor(
signatureType: SignatureType,
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector
) : super(signatureType, signingKey, protector)
@Throws(PGPException::class)
constructor(
primaryKey: PGPSecretKey,
primaryKey: OpenPGPKey.OpenPGPSecretKey,
primaryKeyProtector: SecretKeyRingProtector,
oldCertification: PGPSignature
) : super(primaryKey, primaryKeyProtector, oldCertification)
@ -61,9 +61,11 @@ class SelfSignatureBuilder : AbstractSignatureBuilder<SelfSignatureBuilder> {
@Throws(PGPException::class)
fun build(userId: CharSequence): PGPSignature =
buildAndInitSignatureGenerator().generateCertification(userId.toString(), publicSigningKey)
buildAndInitSignatureGenerator()
.generateCertification(userId.toString(), signingKey.publicKey.pgpPublicKey)
@Throws(PGPException::class)
fun build(userAttributes: PGPUserAttributeSubpacketVector): PGPSignature =
buildAndInitSignatureGenerator().generateCertification(userAttributes, publicSigningKey)
buildAndInitSignatureGenerator()
.generateCertification(userAttributes, signingKey.publicKey.pgpPublicKey)
}

View file

@ -7,8 +7,8 @@ package org.pgpainless.signature.builder
import java.util.function.Predicate
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.pgpainless.algorithm.HashAlgorithm
import org.pgpainless.algorithm.SignatureType
import org.pgpainless.key.protection.SecretKeyRingProtector
@ -26,13 +26,13 @@ class SubkeyBindingSignatureBuilder : AbstractSignatureBuilder<SubkeyBindingSign
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector
) : super(SignatureType.SUBKEY_BINDING, signingKey, protector)
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector,
hashAlgorithm: HashAlgorithm
) : super(
@ -40,12 +40,12 @@ class SubkeyBindingSignatureBuilder : AbstractSignatureBuilder<SubkeyBindingSign
signingKey,
protector,
hashAlgorithm,
SignatureSubpackets.createHashedSubpackets(signingKey.publicKey),
SignatureSubpackets.createHashedSubpackets(signingKey.publicKey.pgpPublicKey),
SignatureSubpackets.createEmptySubpackets())
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector,
oldSubkeyBinding: PGPSignature
) : super(
@ -69,5 +69,6 @@ class SubkeyBindingSignatureBuilder : AbstractSignatureBuilder<SubkeyBindingSign
@Throws(PGPException::class)
fun build(subkey: PGPPublicKey): PGPSignature =
buildAndInitSignatureGenerator().generateCertification(publicSigningKey, subkey)
buildAndInitSignatureGenerator()
.generateCertification(signingKey.publicKey.pgpPublicKey, subkey)
}

View file

@ -7,9 +7,13 @@ package org.pgpainless.signature.builder
import java.util.function.Predicate
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPPublicKeyRing
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVector
import org.bouncycastle.openpgp.api.OpenPGPCertificate
import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentSignature
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.api.OpenPGPSignature
import org.pgpainless.PGPainless
import org.pgpainless.algorithm.SignatureType
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.signature.subpackets.CertificationSubpackets
@ -42,7 +46,7 @@ class ThirdPartyCertificationSignatureBuilder :
*/
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector
) : super(SignatureType.GENERIC_CERTIFICATION, signingKey, protector)
@ -57,7 +61,7 @@ class ThirdPartyCertificationSignatureBuilder :
@Throws(PGPException::class)
constructor(
signatureType: SignatureType,
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector
) : super(signatureType, signingKey, protector)
@ -71,7 +75,7 @@ class ThirdPartyCertificationSignatureBuilder :
*/
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector,
archetypeSignature: PGPSignature
) : super(signingKey, protector, archetypeSignature)
@ -86,6 +90,16 @@ class ThirdPartyCertificationSignatureBuilder :
}
}
fun build(certificate: OpenPGPCertificate, userId: CharSequence): OpenPGPSignature =
buildAndInitSignatureGenerator()
.generateCertification(userId.toString(), certificate.primaryKey.pgpPublicKey)
.let {
OpenPGPComponentSignature(
it,
signingKey.publicKey,
OpenPGPCertificate.OpenPGPUserId(userId.toString(), certificate.primaryKey))
}
/**
* Create a certification signature for the given user-id and the given third-party certificate.
*
@ -95,9 +109,19 @@ class ThirdPartyCertificationSignatureBuilder :
* @throws PGPException if the signature generator cannot be initialized
*/
@Throws(PGPException::class)
@Deprecated("Pass in an OpenPGPCertificate instead of a PGPPublicKeyRing.")
fun build(certificate: PGPPublicKeyRing, userId: CharSequence): PGPSignature =
buildAndInitSignatureGenerator()
.generateCertification(userId.toString(), certificate.publicKey)
build(PGPainless.getInstance().toCertificate(certificate), userId).signature
fun build(
certificate: OpenPGPCertificate,
userAttribute: PGPUserAttributeSubpacketVector
): OpenPGPSignature =
OpenPGPComponentSignature(
buildAndInitSignatureGenerator()
.generateCertification(userAttribute, certificate.primaryKey.pgpPublicKey),
signingKey.publicKey,
OpenPGPCertificate.OpenPGPUserAttribute(userAttribute, certificate.primaryKey))
/**
* Create a certification signature for the given user attribute and the given third-party
@ -109,9 +133,10 @@ class ThirdPartyCertificationSignatureBuilder :
* @throws PGPException if the signature generator cannot be initialized
*/
@Throws(PGPException::class)
@Deprecated("Pass in an OpenPGPCertificate instead of a PGPPublicKeyRing.")
fun build(
certificate: PGPPublicKeyRing,
userAttribute: PGPUserAttributeSubpacketVector
): PGPSignature =
buildAndInitSignatureGenerator().generateCertification(userAttribute, certificate.publicKey)
build(PGPainless.getInstance().toCertificate(certificate), userAttribute).signature
}

View file

@ -8,8 +8,13 @@ import java.util.function.Predicate
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPPublicKeyRing
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.api.OpenPGPCertificate
import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey
import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentSignature
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.api.OpenPGPSignature
import org.pgpainless.PGPainless
import org.pgpainless.algorithm.SignatureType
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.signature.subpackets.CertificationSubpackets
@ -27,13 +32,13 @@ class ThirdPartyDirectKeySignatureBuilder :
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector
) : super(SignatureType.DIRECT_KEY, signingKey, protector)
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector,
archetypeSignature: PGPSignature
) : super(signingKey, protector, archetypeSignature)
@ -48,9 +53,20 @@ class ThirdPartyDirectKeySignatureBuilder :
}
}
@Throws(PGPException::class)
fun build(certificate: PGPPublicKeyRing): PGPSignature = build(certificate.publicKey)
fun build(certificate: OpenPGPCertificate): OpenPGPSignature = build(certificate.primaryKey)
fun build(componentKey: OpenPGPComponentKey): OpenPGPSignature =
OpenPGPComponentSignature(
buildAndInitSignatureGenerator().generateCertification(componentKey.pgpPublicKey),
signingKey.publicKey,
componentKey)
@Throws(PGPException::class)
@Deprecated("Pass in an OpenPGPCertificate instead.")
fun build(certificate: PGPPublicKeyRing): PGPSignature =
build(PGPainless.getInstance().toCertificate(certificate)).signature
@Deprecated("Pass in an OpenPGPComponentKey instead.")
@Throws(PGPException::class)
fun build(certifiedKey: PGPPublicKey): PGPSignature =
buildAndInitSignatureGenerator().generateCertification(certifiedKey)

View file

@ -6,9 +6,9 @@ package org.pgpainless.signature.builder
import java.util.function.Predicate
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.PGPSignatureGenerator
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.pgpainless.algorithm.SignatureType
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.signature.subpackets.SignatureSubpackets
@ -26,13 +26,13 @@ class UniversalSignatureBuilder : AbstractSignatureBuilder<UniversalSignatureBui
@Throws(PGPException::class)
constructor(
signatureType: SignatureType,
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector
) : super(signatureType, signingKey, protector)
@Throws(PGPException::class)
constructor(
signingKey: PGPSecretKey,
signingKey: OpenPGPKey.OpenPGPSecretKey,
protector: SecretKeyRingProtector,
archetypeSignature: PGPSignature
) : super(signingKey, protector, archetypeSignature)

View file

@ -15,9 +15,10 @@ import java.util.List;
import org.bouncycastle.bcpg.sig.TrustSignature;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.openpgp.api.OpenPGPSignature;
import org.bouncycastle.util.Arrays;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
@ -36,13 +37,11 @@ public class CertifyCertificateTest {
@Test
public void testUserIdCertification() throws PGPException, IOException {
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
PGPSecretKeyRing alice = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@pgpainless.org>")
.getPGPSecretKeyRing();
OpenPGPKey alice = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@pgpainless.org>");
String bobUserId = "Bob <bob@pgpainless.org>";
PGPSecretKeyRing bob = PGPainless.generateKeyRing().modernKeyRing(bobUserId)
.getPGPSecretKeyRing();
OpenPGPKey bob = PGPainless.generateKeyRing().modernKeyRing(bobUserId);
PGPPublicKeyRing bobCertificate = PGPainless.extractCertificate(bob);
OpenPGPCertificate bobCertificate = bob.toCertificate();
CertifyCertificate.CertificationResult result = PGPainless.certify()
.userIdOnCertificate(bobUserId, bobCertificate)
@ -50,35 +49,33 @@ public class CertifyCertificateTest {
.build();
assertNotNull(result);
PGPSignature signature = result.getCertification();
PGPSignature signature = result.getPgpSignature();
assertNotNull(signature);
assertEquals(SignatureType.GENERIC_CERTIFICATION, SignatureType.valueOf(signature.getSignatureType()));
assertEquals(alice.getPublicKey().getKeyID(), signature.getKeyID());
assertEquals(alice.getPrimaryKey().getPGPPublicKey().getKeyID(), signature.getKeyID());
assertTrue(SignatureVerifier.verifyUserIdCertification(
bobUserId, signature, alice.getPublicKey(), bob.getPublicKey(), PGPainless.getPolicy(), DateUtil.now()));
bobUserId, signature, alice.getPrimaryKey().getPGPPublicKey(), bob.getPrimaryKey().getPGPPublicKey(), PGPainless.getPolicy(), DateUtil.now()));
PGPPublicKeyRing bobCertified = result.getCertifiedCertificate();
PGPPublicKey bobCertifiedKey = bobCertified.getPublicKey();
OpenPGPCertificate bobCertified = result.getCertifiedCertificate();
PGPPublicKey bobCertifiedKey = bobCertified.getPrimaryKey().getPGPPublicKey();
// There are 2 sigs now, bobs own and alice'
assertEquals(2, CollectionUtils.iteratorToList(bobCertifiedKey.getSignaturesForID(bobUserId)).size());
List<PGPSignature> sigsByAlice = CollectionUtils.iteratorToList(
bobCertifiedKey.getSignaturesForKeyID(alice.getPublicKey().getKeyID()));
bobCertifiedKey.getSignaturesForKeyID(alice.getPrimaryKey().getPGPPublicKey().getKeyID()));
assertEquals(1, sigsByAlice.size());
assertEquals(signature, sigsByAlice.get(0));
assertFalse(Arrays.areEqual(bobCertificate.getEncoded(), bobCertified.getEncoded()));
assertFalse(Arrays.areEqual(bobCertificate.getPGPPublicKeyRing().getEncoded(), bobCertified.getPGPPublicKeyRing().getEncoded()));
}
@Test
public void testKeyDelegation() throws PGPException, IOException {
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
PGPSecretKeyRing alice = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@pgpainless.org>")
.getPGPSecretKeyRing();
PGPSecretKeyRing bob = PGPainless.generateKeyRing().modernKeyRing("Bob <bob@pgpainless.org>")
.getPGPSecretKeyRing();
OpenPGPKey alice = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@pgpainless.org>");
OpenPGPKey bob = PGPainless.generateKeyRing().modernKeyRing("Bob <bob@pgpainless.org>");
PGPPublicKeyRing bobCertificate = PGPainless.extractCertificate(bob);
OpenPGPCertificate bobCertificate = bob.toCertificate();
CertifyCertificate.CertificationResult result = PGPainless.certify()
.certificate(bobCertificate, Trustworthiness.fullyTrusted().introducer())
@ -86,11 +83,12 @@ public class CertifyCertificateTest {
.build();
assertNotNull(result);
PGPSignature signature = result.getCertification();
OpenPGPSignature signature = result.getCertification();
PGPSignature pgpSignature = signature.getSignature();
assertNotNull(signature);
assertEquals(SignatureType.DIRECT_KEY, SignatureType.valueOf(signature.getSignatureType()));
assertEquals(alice.getPublicKey().getKeyID(), signature.getKeyID());
TrustSignature trustSignaturePacket = signature.getHashedSubPackets().getTrust();
assertEquals(SignatureType.DIRECT_KEY, SignatureType.valueOf(pgpSignature.getSignatureType()));
assertEquals(alice.getPrimaryKey().getPGPPublicKey().getKeyID(), pgpSignature.getKeyID());
TrustSignature trustSignaturePacket = pgpSignature.getHashedSubPackets().getTrust();
assertNotNull(trustSignaturePacket);
Trustworthiness trustworthiness = new Trustworthiness(trustSignaturePacket.getTrustAmount(), trustSignaturePacket.getDepth());
assertTrue(trustworthiness.isFullyTrusted());
@ -98,29 +96,27 @@ public class CertifyCertificateTest {
assertFalse(trustworthiness.canIntroduce(1));
assertTrue(SignatureVerifier.verifyDirectKeySignature(
signature, alice.getPublicKey(), bob.getPublicKey(), PGPainless.getPolicy(), DateUtil.now()));
pgpSignature, alice.getPrimaryKey().getPGPPublicKey(), bob.getPrimaryKey().getPGPPublicKey(), PGPainless.getPolicy(), DateUtil.now()));
PGPPublicKeyRing bobCertified = result.getCertifiedCertificate();
PGPPublicKey bobCertifiedKey = bobCertified.getPublicKey();
OpenPGPCertificate bobCertified = result.getCertifiedCertificate();
PGPPublicKey bobCertifiedKey = bobCertified.getPrimaryKey().getPGPPublicKey();
List<PGPSignature> sigsByAlice = CollectionUtils.iteratorToList(
bobCertifiedKey.getSignaturesForKeyID(alice.getPublicKey().getKeyID()));
bobCertifiedKey.getSignaturesForKeyID(alice.getPrimaryKey().getPGPPublicKey().getKeyID()));
assertEquals(1, sigsByAlice.size());
assertEquals(signature, sigsByAlice.get(0));
assertEquals(signature.getSignature(), sigsByAlice.get(0));
assertFalse(Arrays.areEqual(bobCertificate.getEncoded(), bobCertified.getEncoded()));
assertFalse(Arrays.areEqual(bobCertificate.getPGPPublicKeyRing().getEncoded(), bobCertified.getPGPPublicKeyRing().getEncoded()));
}
@Test
public void testPetNameCertification() {
PGPSecretKeyRing aliceKey = PGPainless.generateKeyRing()
.modernKeyRing("Alice <alice@pgpainless.org>")
.getPGPSecretKeyRing();
PGPSecretKeyRing bobKey = PGPainless.generateKeyRing()
.modernKeyRing("Bob <bob@pgpainless.org>")
.getPGPSecretKeyRing();
OpenPGPKey aliceKey = PGPainless.generateKeyRing()
.modernKeyRing("Alice <alice@pgpainless.org>");
OpenPGPKey bobKey = PGPainless.generateKeyRing()
.modernKeyRing("Bob <bob@pgpainless.org>");
PGPPublicKeyRing bobCert = PGPainless.extractCertificate(bobKey);
OpenPGPCertificate bobCert = bobKey.toCertificate();
String petName = "Bobby";
CertifyCertificate.CertificationResult result = PGPainless.certify()
@ -133,11 +129,12 @@ public class CertifyCertificateTest {
}
});
PGPSignature certification = result.getCertification();
assertEquals(aliceKey.getPublicKey().getKeyID(), certification.getKeyID());
assertEquals(CertificationType.GENERIC.asSignatureType().getCode(), certification.getSignatureType());
OpenPGPSignature certification = result.getCertification();
PGPSignature signature = certification.getSignature();
assertEquals(aliceKey.getPrimaryKey().getPGPPublicKey().getKeyID(), signature.getKeyID());
assertEquals(CertificationType.GENERIC.asSignatureType().getCode(), signature.getSignatureType());
PGPPublicKeyRing certWithPetName = result.getCertifiedCertificate();
OpenPGPCertificate certWithPetName = result.getCertifiedCertificate();
KeyRingInfo info = PGPainless.inspectKeyRing(certWithPetName);
assertTrue(info.getUserIds().contains(petName));
assertFalse(info.getValidUserIds().contains(petName));
@ -145,13 +142,11 @@ public class CertifyCertificateTest {
@Test
public void testScopedDelegation() {
PGPSecretKeyRing aliceKey = PGPainless.generateKeyRing()
.modernKeyRing("Alice <alice@pgpainless.org>")
.getPGPSecretKeyRing();
PGPSecretKeyRing caKey = PGPainless.generateKeyRing()
.modernKeyRing("CA <ca@example.com>")
.getPGPSecretKeyRing();
PGPPublicKeyRing caCert = PGPainless.extractCertificate(caKey);
OpenPGPKey aliceKey = PGPainless.generateKeyRing()
.modernKeyRing("Alice <alice@pgpainless.org>");
OpenPGPKey caKey = PGPainless.generateKeyRing()
.modernKeyRing("CA <ca@example.com>");
OpenPGPCertificate caCert = caKey.toCertificate();
CertifyCertificate.CertificationResult result = PGPainless.certify()
.certificate(caCert, Trustworthiness.fullyTrusted().introducer())
@ -163,9 +158,10 @@ public class CertifyCertificateTest {
}
});
PGPSignature certification = result.getCertification();
assertEquals(SignatureType.DIRECT_KEY.getCode(), certification.getSignatureType());
OpenPGPSignature certification = result.getCertification();
PGPSignature signature = certification.getSignature();
assertEquals(SignatureType.DIRECT_KEY.getCode(), signature.getSignatureType());
assertEquals("^.*<.+@example.com>.*$",
certification.getHashedSubPackets().getRegularExpression().getRegex());
signature.getHashedSubPackets().getRegularExpression().getRegex());
}
}

View file

@ -14,10 +14,10 @@ import java.util.HashSet;
import java.util.Set;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.EncryptionPurpose;
@ -33,10 +33,10 @@ public class SubkeyAndPrimaryKeyBindingSignatureTest {
@Test
public void testRebindSubkey() throws PGPException, IOException {
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
OpenPGPKey secretKeys = PGPainless.getInstance().toKey(TestKeys.getEmilSecretKeyRing());
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
PGPSecretKey primaryKey = secretKeys.getSecretKey();
OpenPGPKey.OpenPGPSecretKey primaryKey = secretKeys.getPrimarySecretKey();
OpenPGPCertificate.OpenPGPComponentKey encryptionSubkey =
info.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0);
assertNotNull(encryptionSubkey);
@ -57,9 +57,9 @@ public class SubkeyAndPrimaryKeyBindingSignatureTest {
});
PGPSignature binding = sbb.build(encryptionSubkey.getPGPPublicKey());
secretKeys = KeyRingUtils.injectCertification(secretKeys, encryptionSubkey.getPGPPublicKey(), binding);
PGPSecretKeyRing secretKeyRing = KeyRingUtils.injectCertification(secretKeys.getPGPKeyRing(), encryptionSubkey.getPGPPublicKey(), binding);
info = PGPainless.inspectKeyRing(secretKeys);
info = PGPainless.inspectKeyRing(secretKeyRing);
assertEquals(Collections.singleton(HashAlgorithm.SHA512), info.getPreferredHashAlgorithms(encryptionSubkey.getKeyIdentifier()));
}
}

View file

@ -4,11 +4,13 @@
package org.pgpainless.signature.builder;
import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.bcpg.sig.Exportable;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.openpgp.api.OpenPGPSignature;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.SignatureType;
@ -28,28 +30,25 @@ public class ThirdPartyCertificationSignatureBuilderTest {
@Test
public void testInvalidSignatureTypeThrows() {
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice")
.getPGPSecretKeyRing();
OpenPGPKey secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice");
assertThrows(IllegalArgumentException.class, () ->
new ThirdPartyCertificationSignatureBuilder(
SignatureType.BINARY_DOCUMENT, // invalid type
secretKeys.getSecretKey(),
secretKeys.getPrimarySecretKey(),
SecretKeyRingProtector.unprotectedKeys()));
}
@Test
public void testUserIdCertification() throws PGPException {
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice")
.getPGPSecretKeyRing();
OpenPGPKey secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice");
PGPPublicKeyRing bobsPublicKeys = PGPainless.extractCertificate(
PGPainless.generateKeyRing().modernKeyRing("Bob")
.getPGPSecretKeyRing());
OpenPGPCertificate bobsPublicKeys = PGPainless.generateKeyRing().modernKeyRing("Bob")
.toCertificate();
ThirdPartyCertificationSignatureBuilder signatureBuilder = new ThirdPartyCertificationSignatureBuilder(
secretKeys.getSecretKey(),
secretKeys.getPrimarySecretKey(),
SecretKeyRingProtector.unprotectedKeys());
signatureBuilder.applyCallback(new CertificationSubpackets.Callback() {
@ -59,16 +58,20 @@ public class ThirdPartyCertificationSignatureBuilderTest {
}
});
PGPSignature certification = signatureBuilder.build(bobsPublicKeys, "Bob");
assertEquals(SignatureType.GENERIC_CERTIFICATION, SignatureType.valueOf(certification.getSignatureType()));
assertEquals(secretKeys.getPublicKey().getKeyID(), certification.getKeyID());
assertArrayEquals(secretKeys.getPublicKey().getFingerprint(), certification.getHashedSubPackets().getIssuerFingerprint().getFingerprint());
Exportable exportable = SignatureSubpacketsUtil.getExportableCertification(certification);
OpenPGPSignature certification = signatureBuilder.build(bobsPublicKeys, "Bob");
PGPSignature signature = certification.getSignature();
assertEquals(SignatureType.GENERIC_CERTIFICATION, SignatureType.valueOf(signature.getSignatureType()));
assertTrue(KeyIdentifier.matches(signature.getKeyIdentifiers(), secretKeys.getKeyIdentifier(), true));
assertArrayEquals(
secretKeys.getPrimaryKey().getPGPPublicKey().getFingerprint(),
signature.getHashedSubPackets().getIssuerFingerprint().getFingerprint());
Exportable exportable = SignatureSubpacketsUtil.getExportableCertification(signature);
assertNotNull(exportable);
assertFalse(exportable.isExportable());
// test sig correctness
certification.init(ImplementationFactory.getInstance().getPgpContentVerifierBuilderProvider(), secretKeys.getPublicKey());
assertTrue(certification.verifyCertification("Bob", bobsPublicKeys.getPublicKey()));
signature.init(ImplementationFactory.getInstance().getPgpContentVerifierBuilderProvider(),
secretKeys.getPrimaryKey().getPGPPublicKey());
assertTrue(signature.verifyCertification("Bob", bobsPublicKeys.getPrimaryKey().getPGPPublicKey()));
}
}

View file

@ -14,6 +14,8 @@ import java.util.Date;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.openpgp.api.OpenPGPSignature;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.CompressionAlgorithm;
@ -32,12 +34,11 @@ public class ThirdPartyDirectKeySignatureBuilderTest {
@Test
public void testDirectKeySignatureBuilding() throws PGPException {
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice")
.getPGPSecretKeyRing();
OpenPGPKey secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice");
DirectKeySelfSignatureBuilder dsb = new DirectKeySelfSignatureBuilder(
secretKeys.getSecretKey(),
secretKeys.getPrimarySecretKey(),
SecretKeyRingProtector.unprotectedKeys());
Date now = new Date();
@ -54,11 +55,14 @@ public class ThirdPartyDirectKeySignatureBuilderTest {
}
});
PGPSignature directKeySig = dsb.build();
OpenPGPSignature directKeySig = dsb.build();
assertNotNull(directKeySig);
secretKeys = KeyRingUtils.injectCertification(secretKeys, secretKeys.getPublicKey(), directKeySig);
PGPSecretKeyRing secretKeyRing = KeyRingUtils.injectCertification(
secretKeys.getPGPSecretKeyRing(),
secretKeys.getPrimaryKey().getPGPPublicKey(),
directKeySig.getSignature());
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys, t1);
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeyRing, t1);
PGPSignature signature = info.getLatestDirectKeySelfSignature();
assertNotNull(signature);
@ -69,7 +73,7 @@ public class ThirdPartyDirectKeySignatureBuilderTest {
assertEquals(Collections.singleton(HashAlgorithm.SHA512), SignatureSubpacketsUtil.parsePreferredHashAlgorithms(signature));
assertEquals(Collections.singleton(CompressionAlgorithm.ZIP), SignatureSubpacketsUtil.parsePreferredCompressionAlgorithms(signature));
assertEquals(Collections.singleton(SymmetricKeyAlgorithm.AES_256), SignatureSubpacketsUtil.parsePreferredSymmetricKeyAlgorithms(signature));
assertEquals(secretKeys.getPublicKey().getKeyID(), signature.getKeyID());
assertArrayEquals(secretKeys.getPublicKey().getFingerprint(), signature.getHashedSubPackets().getIssuerFingerprint().getFingerprint());
assertEquals(secretKeyRing.getPublicKey().getKeyID(), signature.getKeyID());
assertArrayEquals(secretKeyRing.getPublicKey().getFingerprint(), signature.getHashedSubPackets().getIssuerFingerprint().getFingerprint());
}
}

View file

@ -6,15 +6,16 @@ package org.pgpainless.signature.builder;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.bcpg.sig.PrimaryUserID;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureGenerator;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
@ -51,18 +52,18 @@ public class UniversalSignatureBuilderTest {
"=Dqbd\n" +
"-----END PGP PRIVATE KEY BLOCK-----";
private PGPSecretKeyRing secretKeys;
private OpenPGPKey secretKeys;
private final SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
@BeforeEach
public void parseKey() throws IOException {
secretKeys = PGPainless.readKeyRing().secretKeyRing(KEY);
secretKeys = PGPainless.getInstance().readKey().parseKey(KEY);
}
@Test
public void createPetNameSignature() throws PGPException {
PGPSecretKey signingKey = secretKeys.getSecretKey();
PGPSignature archetype = signingKey.getPublicKey().getSignatures().next();
OpenPGPKey.OpenPGPSecretKey signingKey = secretKeys.getPrimarySecretKey();
PGPSignature archetype = signingKey.getPublicKey().getPGPPublicKey().getSignatures().next();
UniversalSignatureBuilder builder = new UniversalSignatureBuilder(
signingKey, protector, archetype);
@ -77,11 +78,11 @@ public class UniversalSignatureBuilderTest {
PGPSignatureGenerator generator = builder.getSignatureGenerator();
String petName = "mykey";
PGPSignature petNameSig = generator.generateCertification(petName, secretKeys.getPublicKey());
PGPSignature petNameSig = generator.generateCertification(petName, secretKeys.getPrimarySecretKey().getPublicKey().getPGPPublicKey());
assertEquals(SignatureType.POSITIVE_CERTIFICATION.getCode(), petNameSig.getSignatureType());
assertEquals(4, petNameSig.getVersion());
assertEquals(signingKey.getKeyID(), petNameSig.getKeyID());
assertTrue(KeyIdentifier.matches(petNameSig.getKeyIdentifiers(), signingKey.getKeyIdentifier(), true));
assertEquals(HashAlgorithm.SHA512.getAlgorithmId(), petNameSig.getHashAlgorithm());
assertEquals(KeyFlag.toBitmask(KeyFlag.CERTIFY_OTHER), petNameSig.getHashedSubPackets().getKeyFlags());
assertFalse(petNameSig.getHashedSubPackets().isExportable());