diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/PGPainless.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/PGPainless.kt index 190d926e..e2918389 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/PGPainless.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/PGPainless.kt @@ -67,9 +67,14 @@ class PGPainless( * @param referenceTime reference time for evaluation * @return [KeyRingInfo] wrapper */ + @JvmOverloads fun inspect(keyOrCertificate: OpenPGPCertificate, referenceTime: Date = Date()): KeyRingInfo = KeyRingInfo(keyOrCertificate, this, referenceTime) + @JvmOverloads + fun modify(key: OpenPGPKey, referenceTime: Date = Date()): SecretKeyRingEditor = + SecretKeyRingEditor(key, this, referenceTime) + fun readKey(): OpenPGPKeyReader = api.readKeyOrCertificate() fun toKey(secretKeyRing: PGPSecretKeyRing): OpenPGPKey = diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.kt index 904ba78e..1241b110 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.kt @@ -694,7 +694,7 @@ class OpenPgpMessageInputStream( private fun getDecryptionKey(pkesk: PGPPublicKeyEncryptedData): OpenPGPKey? = options.getDecryptionKeys().firstOrNull { it.pgpSecretKeyRing.getSecretKeyFor(pkesk) != null && - PGPainless.inspectKeyRing(it).decryptionSubkeys.any { subkey -> + api.inspect(it).decryptionSubkeys.any { subkey -> pkesk.keyIdentifier.matches(subkey.keyIdentifier) } } @@ -702,7 +702,7 @@ class OpenPgpMessageInputStream( private fun getDecryptionKeys(pkesk: PGPPublicKeyEncryptedData): List = options.getDecryptionKeys().filter { it.pgpSecretKeyRing.getSecretKeyFor(pkesk) != null && - PGPainless.inspectKeyRing(it).decryptionSubkeys.any { subkey -> + api.inspect(it).decryptionSubkeys.any { subkey -> pkesk.keyIdentifier.matches(subkey.keyIdentifier) } } @@ -713,7 +713,7 @@ class OpenPgpMessageInputStream( val algorithm = pkesk.algorithm val candidates = mutableListOf() options.getDecryptionKeys().forEach { - val info = PGPainless.inspectKeyRing(it) + val info = api.inspect(it) for (key in info.decryptionSubkeys) { if (key.pgpPublicKey.algorithm == algorithm && info.isSecretKeyAvailable(key.keyIdentifier)) { diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionOptions.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionOptions.kt index c4adf3b3..d6aef95d 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionOptions.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionOptions.kt @@ -10,7 +10,6 @@ import org.bouncycastle.openpgp.api.OpenPGPCertificate import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey import org.bouncycastle.openpgp.operator.PGPKeyEncryptionMethodGenerator import org.pgpainless.PGPainless -import org.pgpainless.PGPainless.Companion.inspectKeyRing import org.pgpainless.algorithm.EncryptionPurpose import org.pgpainless.algorithm.SymmetricKeyAlgorithm import org.pgpainless.algorithm.negotiation.SymmetricKeyAlgorithmNegotiator.Companion.byPopularity @@ -191,7 +190,7 @@ class EncryptionOptions(private val purpose: EncryptionPurpose, private val api: userId: CharSequence, encryptionKeySelector: EncryptionKeySelector ) = apply { - val info = inspectKeyRing(cert, evaluationDate) + val info = api.inspect(cert, evaluationDate) val subkeys = encryptionKeySelector.selectEncryptionSubkeys( info.getEncryptionSubkeys(userId, purpose)) @@ -289,7 +288,7 @@ class EncryptionOptions(private val purpose: EncryptionPurpose, private val api: selector: EncryptionKeySelector, wildcardKeyId: Boolean ) = apply { - val info = inspectKeyRing(cert, evaluationDate) + val info = api.inspect(cert, evaluationDate) val primaryKeyExpiration = try { info.primaryKeyExpirationDate diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionResult.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionResult.kt index 4f6e6978..a969d8c3 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionResult.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionResult.kt @@ -8,6 +8,7 @@ import java.util.* import org.bouncycastle.openpgp.PGPLiteralData import org.bouncycastle.openpgp.PGPPublicKeyRing import org.bouncycastle.openpgp.PGPSignature +import org.bouncycastle.openpgp.api.OpenPGPCertificate import org.pgpainless.algorithm.CompressionAlgorithm import org.pgpainless.algorithm.StreamEncoding import org.pgpainless.algorithm.SymmetricKeyAlgorithm @@ -34,6 +35,9 @@ data class EncryptionResult( val isForYourEyesOnly: Boolean get() = PGPLiteralData.CONSOLE == fileName + fun isEncryptedFor(certificate: OpenPGPCertificate) = + recipients.any { certificate.getKey(it.keyIdentifier) != null } + /** * Returns true, if the message was encrypted for at least one subkey of the given certificate. * diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/SigningOptions.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/SigningOptions.kt index 51be8167..0d518c96 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/SigningOptions.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/SigningOptions.kt @@ -12,7 +12,6 @@ import org.bouncycastle.openpgp.api.OpenPGPKey import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPPrivateKey import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPSecretKey import org.pgpainless.PGPainless -import org.pgpainless.PGPainless.Companion.inspectKeyRing import org.pgpainless.algorithm.DocumentSignatureType import org.pgpainless.algorithm.HashAlgorithm import org.pgpainless.algorithm.PublicKeyAlgorithm.Companion.requireFromId @@ -138,6 +137,7 @@ class SigningOptions(private val api: PGPainless) { signatureType: DocumentSignatureType ) = addInlineSignature(signingKeyProtector, api.toKey(signingKey), signatureType) + @JvmOverloads fun addInlineSignature( signingKeyProtector: SecretKeyRingProtector, signingKey: OpenPGPKey, @@ -145,7 +145,7 @@ class SigningOptions(private val api: PGPainless) { signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT, subpacketsCallback: Callback? = null ) = apply { - val keyRingInfo = inspectKeyRing(signingKey, evaluationDate) + val keyRingInfo = api.inspect(signingKey, evaluationDate) if (userId != null && !keyRingInfo.isUserIdValid(userId)) { throw UnboundUserIdException( of(signingKey), @@ -212,7 +212,7 @@ class SigningOptions(private val api: PGPainless) { subpacketsCallback: Callback? = null ): SigningOptions = apply { val openPGPKey = signingKey.openPGPKey - val keyRingInfo = inspectKeyRing(openPGPKey, evaluationDate) + val keyRingInfo = api.inspect(openPGPKey, evaluationDate) val signingPubKeys = keyRingInfo.signingSubkeys if (signingPubKeys.isEmpty()) { throw UnacceptableSigningKeyException(openPGPKey) @@ -319,7 +319,7 @@ class SigningOptions(private val api: PGPainless) { signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT, subpacketCallback: Callback? = null ): SigningOptions = apply { - val keyRingInfo = inspectKeyRing(signingKey, evaluationDate) + val keyRingInfo = api.inspect(signingKey, evaluationDate) if (userId != null && !keyRingInfo.isUserIdValid(userId)) { throw UnboundUserIdException( of(signingKey), @@ -380,7 +380,7 @@ class SigningOptions(private val api: PGPainless) { signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT, subpacketCallback: Callback? = null ): SigningOptions = apply { - val keyRingInfo = inspectKeyRing(signingKey.openPGPKey, evaluationDate) + val keyRingInfo = api.inspect(signingKey.openPGPKey, evaluationDate) val signingPrivKey: OpenPGPPrivateKey = signingKey.unlock(signingKeyProtector) val hashAlgorithms = if (userId != null) keyRingInfo.getPreferredHashAlgorithms(userId) diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/certification/CertifyCertificate.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/certification/CertifyCertificate.kt index e43b30d8..f30b7539 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/certification/CertifyCertificate.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/certification/CertifyCertificate.kt @@ -134,7 +134,7 @@ class CertifyCertificate(private val api: PGPainless) { key: OpenPGPKey, protector: SecretKeyRingProtector ): CertificationOnUserIdWithSubpackets { - val secretKey = getCertifyingSecretKey(key) + val secretKey = getCertifyingSecretKey(key, api) val sigBuilder = ThirdPartyCertificationSignatureBuilder( certificationType.asSignatureType(), secretKey, protector, api) @@ -220,7 +220,7 @@ class CertifyCertificate(private val api: PGPainless) { key: OpenPGPKey, protector: SecretKeyRingProtector ): DelegationOnCertificateWithSubpackets { - val secretKey = getCertifyingSecretKey(key) + val secretKey = getCertifyingSecretKey(key, api) val sigBuilder = ThirdPartyDirectKeySignatureBuilder(secretKey, protector, api) if (trustworthiness != null) { sigBuilder.hashedSubpackets.setTrust( @@ -306,10 +306,11 @@ class CertifyCertificate(private val api: PGPainless) { companion object { @JvmStatic private fun getCertifyingSecretKey( - certificationKey: OpenPGPKey + certificationKey: OpenPGPKey, + api: PGPainless ): OpenPGPKey.OpenPGPSecretKey { val now = Date() - val info = PGPainless.inspectKeyRing(certificationKey, now) + val info = api.inspect(certificationKey, now) val fingerprint = info.fingerprint val certificationPubKey = info.getPublicKey(fingerprint) 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 11efe78f..094eabc3 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 @@ -8,10 +8,11 @@ import java.util.* import java.util.function.Predicate import javax.annotation.Nonnull import kotlin.NoSuchElementException -import openpgp.openPgpKeyId import org.bouncycastle.bcpg.KeyIdentifier import org.bouncycastle.bcpg.sig.KeyExpirationTime import org.bouncycastle.openpgp.* +import org.bouncycastle.openpgp.api.OpenPGPCertificate +import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPSubkey import org.bouncycastle.openpgp.api.OpenPGPImplementation import org.bouncycastle.openpgp.api.OpenPGPKey @@ -20,7 +21,6 @@ import org.bouncycastle.openpgp.api.OpenPGPKeyEditor import org.bouncycastle.openpgp.api.OpenPGPSignature import org.bouncycastle.openpgp.api.SignatureParameters import org.pgpainless.PGPainless -import org.pgpainless.PGPainless.Companion.inspectKeyRing import org.pgpainless.algorithm.AlgorithmSuite import org.pgpainless.algorithm.KeyFlag import org.pgpainless.algorithm.OpenPGPKeyVersion @@ -29,7 +29,6 @@ import org.pgpainless.algorithm.negotiation.HashAlgorithmNegotiator import org.pgpainless.bouncycastle.extensions.checksumCalculator import org.pgpainless.bouncycastle.extensions.getKeyExpirationDate import org.pgpainless.bouncycastle.extensions.publicKeyAlgorithm -import org.pgpainless.bouncycastle.extensions.requirePublicKey import org.pgpainless.key.OpenPgpFingerprint import org.pgpainless.key.generation.KeyRingBuilder import org.pgpainless.key.generation.KeySpec @@ -50,8 +49,6 @@ class SecretKeyRingEditor( override val referenceTime: Date = Date() ) : SecretKeyRingEditorInterface { - private var secretKeyRing: PGPSecretKeyRing = key.pgpSecretKeyRing - @JvmOverloads constructor( secretKeyRing: PGPSecretKeyRing, @@ -64,8 +61,7 @@ class SecretKeyRingEditor( callback: SelfSignatureSubpackets.Callback?, protector: SecretKeyRingProtector ): SecretKeyRingEditorInterface { - key = PGPainless.getInstance().toKey(secretKeyRing) - val info = inspectKeyRing(key, referenceTime) + val info = api.inspect(key, referenceTime) require(!info.isHardRevoked(userId)) { "User-ID $userId is hard revoked and cannot be re-certified." } @@ -89,7 +85,7 @@ class SecretKeyRingEditor( .setSignatureCreationTime(referenceTime) .setHashedSubpacketsFunction { subpacketGenerator -> val subpackets = SignatureSubpackets(subpacketGenerator) - subpackets.setAppropriateIssuerInfo(secretKeyRing.publicKey) + subpackets.setAppropriateIssuerInfo(key.primaryKey.pgpPublicKey) subpackets.setKeyFlags(info.getKeyFlagsOf(key.keyIdentifier)) subpackets.setPreferredHashAlgorithms(hashAlgorithmPreferences) @@ -111,7 +107,6 @@ class SecretKeyRingEditor( } }) .done() - secretKeyRing = key.pgpSecretKeyRing return this } @@ -120,8 +115,8 @@ class SecretKeyRingEditor( protector: SecretKeyRingProtector ): SecretKeyRingEditorInterface { val uid = sanitizeUserId(userId) - val primaryKey = secretKeyRing.publicKey - var info = inspectKeyRing(secretKeyRing, referenceTime) + val primaryKey = key.primaryKey.pgpPublicKey + var info = api.inspect(key, referenceTime) val primaryUserId = info.primaryUserId val signature = if (primaryUserId == null) info.latestDirectKeySelfSignature @@ -144,7 +139,7 @@ class SecretKeyRingEditor( protector) // unmark previous primary user-ids to be non-primary - info = inspectKeyRing(secretKeyRing, referenceTime) + info = api.inspect(key, referenceTime) info.validAndExpiredUserIds .filterNot { it == uid } .forEach { otherUserId -> @@ -215,7 +210,7 @@ class SecretKeyRingEditor( require(oldUID.isNotBlank()) { "Old user-ID cannot be empty." } require(newUID.isNotBlank()) { "New user-ID cannot be empty." } - val info = inspectKeyRing(secretKeyRing, referenceTime) + val info = api.inspect(key, referenceTime) if (!info.isUserIdValid(oldUID)) { throw NoSuchElementException( "Key does not carry user-ID '$oldUID', or it is not valid.") @@ -244,7 +239,6 @@ class SecretKeyRingEditor( } }, protector) - return revokeUserId(oldUID, protector) } @@ -270,7 +264,7 @@ class SecretKeyRingEditor( callback: SelfSignatureSubpackets.Callback?, protector: SecretKeyRingProtector ): SecretKeyRingEditorInterface { - val version = OpenPGPKeyVersion.from(secretKeyRing.publicKey.version) + val version = OpenPGPKeyVersion.from(key.primarySecretKey.version) val keyPair = KeyRingBuilder.generateKeyPair(keySpec, version, api.implementation) val subkeyProtector = PasswordBasedSecretKeyRingProtector.forKeyId(keyPair.keyIdentifier, subkeyPassphrase) @@ -303,8 +297,8 @@ class SecretKeyRingEditor( "Public key algorithm policy violation: $subkeyAlgorithm with bit strength $bitStrength is not acceptable." } - val primaryKey = secretKeyRing.secretKey - val info = inspectKeyRing(secretKeyRing, referenceTime) + val primaryKey = key.primarySecretKey.pgpSecretKey + val info = api.inspect(key, referenceTime) val hashAlgorithm = HashAlgorithmNegotiator.negotiateSignatureHashAlgorithm(api.algorithmPolicy) .negotiateHashAlgorithm(info.preferredHashAlgorithms) @@ -341,7 +335,8 @@ class SecretKeyRingEditor( secretSubkey = KeyRingUtils.secretKeyPlusSignature( secretSubkey, skBindingBuilder.build(secretSubkey.publicKey)) - secretKeyRing = KeyRingUtils.keysPlusSecretKey(secretKeyRing, secretSubkey) + val secretKeyRing = KeyRingUtils.keysPlusSecretKey(key.pgpSecretKeyRing, secretSubkey) + key = api.toKey(secretKeyRing) return this } @@ -356,26 +351,33 @@ class SecretKeyRingEditor( protector: SecretKeyRingProtector, callback: RevocationSignatureSubpackets.Callback? ): SecretKeyRingEditorInterface { - return revokeSubKey(secretKeyRing.secretKey.keyID, protector, callback) + return revokeSubKey(key.keyIdentifier, protector, callback) } override fun revokeSubKey( - subkeyId: Long, + subkeyIdentifier: KeyIdentifier, protector: SecretKeyRingProtector, revocationAttributes: RevocationAttributes? ): SecretKeyRingEditorInterface { return revokeSubKey( - subkeyId, protector, callbackFromRevocationAttributes(revocationAttributes)) + subkeyIdentifier, protector, callbackFromRevocationAttributes(revocationAttributes)) } override fun revokeSubKey( - subkeyId: Long, + subkeyIdentifier: KeyIdentifier, protector: SecretKeyRingProtector, callback: RevocationSignatureSubpackets.Callback? ): SecretKeyRingEditorInterface { - val revokeeSubKey = secretKeyRing.requirePublicKey(subkeyId) + var secretKeyRing = key.pgpSecretKeyRing + val revokeeSubKey = + key.getKey(subkeyIdentifier) + ?: throw NoSuchElementException( + "Certificate ${key.keyIdentifier} does not contain subkey $subkeyIdentifier") val subkeyRevocation = generateRevocation(protector, revokeeSubKey, callback) - secretKeyRing = injectCertification(secretKeyRing, revokeeSubKey, subkeyRevocation) + secretKeyRing = + injectCertification( + secretKeyRing, revokeeSubKey.pgpPublicKey, subkeyRevocation.signature) + key = api.toKey(secretKeyRing) return this } @@ -451,6 +453,7 @@ class SecretKeyRingEditor( expiration: Date?, protector: SecretKeyRingProtector ): SecretKeyRingEditorInterface { + var secretKeyRing = key.pgpSecretKeyRing require(secretKeyRing.secretKey.isMasterKey) { "OpenPGP key does not appear to contain a primary secret key." } @@ -465,8 +468,9 @@ class SecretKeyRingEditor( reissueDirectKeySignature(expiration, protector, prevDirectKeySig).signature) } - val primaryUserId = - inspectKeyRing(secretKeyRing, referenceTime).getPossiblyExpiredPrimaryUserId() + val info = api.inspect(key, referenceTime) + + val primaryUserId = info.getPossiblyExpiredPrimaryUserId() if (primaryUserId != null) { val prevUserIdSig = getPreviousUserIdSignatures(primaryUserId) val userIdSig = @@ -474,7 +478,6 @@ class SecretKeyRingEditor( secretKeyRing = injectCertification(secretKeyRing, primaryUserId, userIdSig) } - val info = inspectKeyRing(secretKeyRing, referenceTime) for (userId in info.validUserIds) { if (userId == primaryUserId) { continue @@ -493,35 +496,40 @@ class SecretKeyRingEditor( } } + key = api.toKey(secretKeyRing) return this } override fun setExpirationDateOfSubkey( expiration: Date?, - keyId: Long, + keyId: KeyIdentifier, protector: SecretKeyRingProtector ): SecretKeyRingEditorInterface = apply { + var secretKeyRing = key.pgpSecretKeyRing + // is primary key - if (keyId == secretKeyRing.publicKey.keyID) { + if (keyId.matches(key.keyIdentifier)) { return setExpirationDate(expiration, protector) } // is subkey val subkey = - secretKeyRing.getPublicKey(keyId) - ?: throw NoSuchElementException("No subkey with ID ${keyId.openPgpKeyId()} found.") + key.getKey(keyId) ?: throw NoSuchElementException("No subkey with ID $keyId found.") val prevBinding = - inspectKeyRing(secretKeyRing).getCurrentSubkeyBindingSignature(keyId) + api.inspect(key).getCurrentSubkeyBindingSignature(keyId) ?: throw NoSuchElementException( - "Previous subkey binding signaure for ${keyId.openPgpKeyId()} MUST NOT be null.") + "Previous subkey binding signaure for $keyId MUST NOT be null.") val bindingSig = reissueSubkeyBindingSignature(subkey, expiration, protector, prevBinding) - secretKeyRing = injectCertification(secretKeyRing, subkey, bindingSig) + secretKeyRing = + injectCertification(secretKeyRing, subkey.pgpPublicKey, bindingSig.signature) + + key = api.toKey(secretKeyRing) } override fun createMinimalRevocationCertificate( protector: SecretKeyRingProtector, revocationAttributes: RevocationAttributes? - ): PGPPublicKeyRing { + ): OpenPGPCertificate { // Check reason if (revocationAttributes != null) { require(RevocationAttributes.Reason.isKeyRevocation(revocationAttributes.reason)) { @@ -530,49 +538,47 @@ class SecretKeyRingEditor( } val revocation = createRevocation(protector, revocationAttributes) - var primaryKey = secretKeyRing.secretKey.publicKey + var primaryKey = key.primaryKey.pgpPublicKey primaryKey = KeyRingUtils.getStrippedDownPublicKey(primaryKey) - primaryKey = PGPPublicKey.addCertification(primaryKey, revocation) - return PGPPublicKeyRing(listOf(primaryKey)) + primaryKey = PGPPublicKey.addCertification(primaryKey, revocation.signature) + return api.toCertificate(PGPPublicKeyRing(listOf(primaryKey))) } override fun createRevocation( protector: SecretKeyRingProtector, revocationAttributes: RevocationAttributes? - ): PGPSignature { + ): OpenPGPSignature { return generateRevocation( - protector, - secretKeyRing.publicKey, - callbackFromRevocationAttributes(revocationAttributes)) + protector, key.primaryKey, callbackFromRevocationAttributes(revocationAttributes)) } override fun createRevocation( - subkeyId: Long, + subkeyIdentifier: KeyIdentifier, protector: SecretKeyRingProtector, revocationAttributes: RevocationAttributes? - ): PGPSignature { + ): OpenPGPSignature { return generateRevocation( protector, - secretKeyRing.requirePublicKey(subkeyId), + key.getKey(subkeyIdentifier), callbackFromRevocationAttributes(revocationAttributes)) } override fun createRevocation( - subkeyId: Long, + subkeyIdentifier: KeyIdentifier, protector: SecretKeyRingProtector, callback: RevocationSignatureSubpackets.Callback? - ): PGPSignature { - return generateRevocation(protector, secretKeyRing.requirePublicKey(subkeyId), callback) + ): OpenPGPSignature { + return generateRevocation(protector, key.getKey(subkeyIdentifier), callback) } override fun createRevocation( subkeyFingerprint: OpenPgpFingerprint, protector: SecretKeyRingProtector, revocationAttributes: RevocationAttributes? - ): PGPSignature { + ): OpenPGPSignature { return generateRevocation( protector, - secretKeyRing.requirePublicKey(subkeyFingerprint), + key.getKey(subkeyFingerprint.keyIdentifier), callbackFromRevocationAttributes(revocationAttributes)) } @@ -599,8 +605,8 @@ class SecretKeyRingEditor( mapOf(keyIdentifier to oldPassphrase), oldProtectionSettings, null)) } - override fun done(): PGPSecretKeyRing { - return secretKeyRing + override fun done(): OpenPGPKey { + return key } private fun sanitizeUserId(userId: CharSequence): CharSequence = @@ -619,11 +625,11 @@ class SecretKeyRingEditor( private fun generateRevocation( protector: SecretKeyRingProtector, - revokeeSubkey: PGPPublicKey, + revokeeSubkey: OpenPGPComponentKey, callback: RevocationSignatureSubpackets.Callback? - ): PGPSignature { + ): OpenPGPSignature { val signatureType = - if (revokeeSubkey.isMasterKey) SignatureType.KEY_REVOCATION + if (revokeeSubkey.isPrimaryKey) SignatureType.KEY_REVOCATION else SignatureType.SUBKEY_REVOCATION return RevocationSignatureBuilder(signatureType, key.primarySecretKey, protector, api) @@ -643,19 +649,20 @@ class SecretKeyRingEditor( applyCallback(callback) } .let { - secretKeyRing = - injectCertification(secretKeyRing, userId, it.build(userId.toString())) + val secretKeyRing = + injectCertification(key.pgpSecretKeyRing, userId, it.build(userId.toString())) + key = api.toKey(secretKeyRing) } return this } private fun getPreviousDirectKeySignature(): PGPSignature? { - val info = inspectKeyRing(secretKeyRing, referenceTime) + val info = api.inspect(key, referenceTime) return info.latestDirectKeySelfSignature } private fun getPreviousUserIdSignatures(userId: String): PGPSignature? { - val info = inspectKeyRing(secretKeyRing, referenceTime) + val info = api.inspect(key, referenceTime) return info.getLatestUserIdCertification(userId) } @@ -696,7 +703,7 @@ class SecretKeyRingEditor( ) { if (expiration != null) { hashedSubpackets.setKeyExpirationTime( - true, secretKeyRing.publicKey.creationTime, expiration) + true, key.primaryKey.creationTime, expiration) } else { hashedSubpackets.setKeyExpirationTime(KeyExpirationTime(true, 0)) } @@ -713,6 +720,7 @@ class SecretKeyRingEditor( secretKeyRingProtector: SecretKeyRingProtector, prevDirectKeySig: PGPSignature ): OpenPGPSignature { + val secretKeyRing = key.pgpSecretKeyRing return DirectKeySelfSignatureBuilder( secretKeyRing, secretKeyRingProtector, prevDirectKeySig, api) .apply { @@ -735,13 +743,13 @@ class SecretKeyRingEditor( } private fun reissueSubkeyBindingSignature( - subkey: PGPPublicKey, + subkey: OpenPGPComponentKey, expiration: Date?, protector: SecretKeyRingProtector, prevSubkeyBindingSignature: PGPSignature - ): PGPSignature { - val primaryKey = secretKeyRing.publicKey - val secretSubkey: PGPSecretKey? = secretKeyRing.getSecretKey(subkey.keyID) + ): OpenPGPSignature { + val primaryKey = key.primaryKey + val secretSubkey: OpenPGPSecretKey? = key.getSecretKey(subkey) val builder = SubkeyBindingSignatureBuilder( @@ -749,7 +757,7 @@ class SecretKeyRingEditor( builder.hashedSubpackets.apply { // set expiration setSignatureCreationTime(referenceTime) - setKeyExpirationTime(subkey, expiration) + setKeyExpirationTime(subkey.pgpPublicKey, expiration) setSignatureExpirationTime(null) // avoid copying sig exp time // signing-capable subkeys need embedded primary key binding sig @@ -758,7 +766,7 @@ class SecretKeyRingEditor( if (secretSubkey == null) { throw NoSuchElementException( "Secret key does not contain secret-key" + - " component for subkey ${subkey.keyID.openPgpKeyId()}") + " component for subkey ${subkey.keyIdentifier}") } // create new embedded back-sig @@ -766,7 +774,8 @@ class SecretKeyRingEditor( addEmbeddedSignature( PrimaryKeyBindingSignatureBuilder( key.getSecretKey(subkey.keyIdentifier), protector, api) - .build(primaryKey)) + .build(primaryKey) + .signature) } } } @@ -775,7 +784,7 @@ class SecretKeyRingEditor( } private fun selectUserIds(predicate: Predicate): List = - inspectKeyRing(secretKeyRing).validUserIds.filter { predicate.test(it) } + key.validUserIds.map { it.userId }.filter { predicate.test(it) }.toList() private class WithKeyRingEncryptionSettingsImpl( private val editor: SecretKeyRingEditor, @@ -805,15 +814,17 @@ class SecretKeyRingEditor( val protector = PasswordBasedSecretKeyRingProtector( newProtectionSettings, SolitaryPassphraseProvider(passphrase)) - val secretKeys = changePassphrase(keyId, editor.secretKeyRing, oldProtector, protector) - editor.secretKeyRing = secretKeys + val secretKeys = + changePassphrase(keyId, editor.key.pgpSecretKeyRing, oldProtector, protector) + editor.key = editor.api.toKey(secretKeys) return editor } override fun toNoPassphrase(): SecretKeyRingEditorInterface { val protector = UnprotectedKeysProtector() - val secretKeys = changePassphrase(keyId, editor.secretKeyRing, oldProtector, protector) - editor.secretKeyRing = secretKeys + val secretKeys = + changePassphrase(keyId, editor.key.pgpSecretKeyRing, oldProtector, protector) + editor.key = editor.api.toKey(secretKeys) return editor } } diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.kt index ad8e36ff..4a1f70ff 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.kt @@ -10,6 +10,9 @@ import java.security.NoSuchAlgorithmException import java.util.* import org.bouncycastle.bcpg.KeyIdentifier import org.bouncycastle.openpgp.* +import org.bouncycastle.openpgp.api.OpenPGPCertificate +import org.bouncycastle.openpgp.api.OpenPGPKey +import org.bouncycastle.openpgp.api.OpenPGPSignature import org.pgpainless.algorithm.KeyFlag import org.pgpainless.key.OpenPgpFingerprint import org.pgpainless.key.generation.KeySpec @@ -262,26 +265,37 @@ interface SecretKeyRingEditorInterface { protector: SecretKeyRingProtector, revocationAttributes: RevocationAttributes? = null ): SecretKeyRingEditorInterface = - revokeSubKey(fingerprint.keyId, protector, revocationAttributes) + revokeSubKey(fingerprint.keyIdentifier, protector, revocationAttributes) + + @Deprecated("Pass in a KeyIdentifier instead of keyId") + fun revokeSubKey(subkeyId: Long, protector: SecretKeyRingProtector) = + revokeSubKey(KeyIdentifier(subkeyId), protector) /** * Revoke the subkey binding signature of a subkey. The subkey with the provided key-id will be * revoked. If no suitable subkey is found, a [NoSuchElementException] will be thrown. * - * @param subkeyId id of the subkey + * @param subkeyIdentifier id of the subkey * @param protector protector to unlock the primary key * @return the builder * @throws PGPException in case we cannot generate a revocation signature for the subkey */ @Throws(PGPException::class) - fun revokeSubKey(subkeyId: Long, protector: SecretKeyRingProtector) = - revokeSubKey(subkeyId, protector, null as RevocationAttributes?) + fun revokeSubKey(subkeyIdentifier: KeyIdentifier, protector: SecretKeyRingProtector) = + revokeSubKey(subkeyIdentifier, protector, null as RevocationAttributes?) + + @Deprecated("Pass in a KeyIdentifier instead of keyId") + fun revokeSubKey( + subkeyId: Long, + protector: SecretKeyRingProtector, + revocationAttributes: RevocationAttributes? = null + ) = revokeSubKey(KeyIdentifier(subkeyId), protector, revocationAttributes) /** * Revoke the subkey binding signature of a subkey. The subkey with the provided key-id will be * revoked. If no suitable subkey is found, a [NoSuchElementException] will be thrown. * - * @param subkeyId id of the subkey + * @param subkeyIdentifier id of the subkey * @param protector protector to unlock the primary key * @param revocationAttributes reason for the revocation * @return the builder @@ -289,18 +303,25 @@ interface SecretKeyRingEditorInterface { */ @Throws(PGPException::class) fun revokeSubKey( - subkeyId: Long, + subkeyIdentifier: KeyIdentifier, protector: SecretKeyRingProtector, revocationAttributes: RevocationAttributes? = null ): SecretKeyRingEditorInterface + @Deprecated("Pass in a KeyIdentifier instead of keyId.") + fun revokeSubKey( + keyId: Long, + protector: SecretKeyRingProtector, + callback: RevocationSignatureSubpackets.Callback? + ) = revokeSubKey(KeyIdentifier(keyId), protector, callback) + /** * Revoke the subkey binding signature of a subkey. The subkey with the provided key-id will be * revoked. If no suitable subkey is found, a [NoSuchElementException] will be thrown. * * The provided subpackets callback is used to modify the revocation signatures subpackets. * - * @param subkeyId id of the subkey + * @param subkeyIdentifier id of the subkey * @param protector protector to unlock the secret key ring * @param callback callback which can be used to modify the subpackets of the revocation * signature @@ -309,7 +330,7 @@ interface SecretKeyRingEditorInterface { */ @Throws(PGPException::class) fun revokeSubKey( - subkeyId: Long, + subkeyIdentifier: KeyIdentifier, protector: SecretKeyRingProtector, callback: RevocationSignatureSubpackets.Callback? ): SecretKeyRingEditorInterface @@ -470,6 +491,14 @@ interface SecretKeyRingEditorInterface { protector: SecretKeyRingProtector ): SecretKeyRingEditorInterface + @Deprecated("Pass in a KeyIdentifier instead of keyId") + @Throws(PGPException::class) + fun setExpirationDateOfSubkey( + expiration: Date?, + keyId: Long, + protector: SecretKeyRingProtector + ) = setExpirationDateOfSubkey(expiration, KeyIdentifier(keyId), protector) + /** * Set the expiration date for the subkey identified by the given keyId to the given expiration * date. If the key is supposed to never expire, then an expiration date of null is expected. @@ -484,7 +513,7 @@ interface SecretKeyRingEditorInterface { @Throws(PGPException::class) fun setExpirationDateOfSubkey( expiration: Date?, - keyId: Long, + keyId: KeyIdentifier, protector: SecretKeyRingProtector ): SecretKeyRingEditorInterface @@ -502,7 +531,7 @@ interface SecretKeyRingEditorInterface { fun createMinimalRevocationCertificate( protector: SecretKeyRingProtector, revocationAttributes: RevocationAttributes? - ): PGPPublicKeyRing + ): OpenPGPCertificate /** * Create a detached revocation certificate, which can be used to revoke the whole key. The @@ -517,13 +546,21 @@ interface SecretKeyRingEditorInterface { fun createRevocation( protector: SecretKeyRingProtector, revocationAttributes: RevocationAttributes? - ): PGPSignature + ): OpenPGPSignature + + @Throws(PGPException::class) + @Deprecated("Pass in a KeyIdentifier instead of a keyId") + fun createRevocation( + subkeyId: Long, + protector: SecretKeyRingProtector, + revocationAttributes: RevocationAttributes? + ) = createRevocation(KeyIdentifier(subkeyId), protector, revocationAttributes) /** * Create a detached revocation certificate, which can be used to revoke the specified subkey. * The original key will not be modified by this method. * - * @param subkeyId id of the subkey to be revoked + * @param subkeyIdentifier id of the subkey to be revoked * @param protector protector to unlock the primary key. * @param revocationAttributes reason for the revocation * @return revocation certificate @@ -531,16 +568,24 @@ interface SecretKeyRingEditorInterface { */ @Throws(PGPException::class) fun createRevocation( - subkeyId: Long, + subkeyIdentifier: KeyIdentifier, protector: SecretKeyRingProtector, revocationAttributes: RevocationAttributes? - ): PGPSignature + ): OpenPGPSignature + + @Deprecated("Pass in a KeyIdentifier instead of keyId") + @Throws(PGPException::class) + fun createRevocation( + subkeyId: Long, + protector: SecretKeyRingProtector, + callback: RevocationSignatureSubpackets.Callback? + ) = createRevocation(KeyIdentifier(subkeyId), protector, callback) /** * Create a detached revocation certificate, which can be used to revoke the specified subkey. * The original key will not be modified by this method. * - * @param subkeyId id of the subkey to be revoked + * @param subkeyIdentifier id of the subkey to be revoked * @param protector protector to unlock the primary key. * @param callback callback to modify the subpackets of the revocation certificate. * @return revocation certificate @@ -548,10 +593,10 @@ interface SecretKeyRingEditorInterface { */ @Throws(PGPException::class) fun createRevocation( - subkeyId: Long, + subkeyIdentifier: KeyIdentifier, protector: SecretKeyRingProtector, callback: RevocationSignatureSubpackets.Callback? - ): PGPSignature + ): OpenPGPSignature /** * Create a detached revocation certificate, which can be used to revoke the specified subkey. @@ -568,7 +613,7 @@ interface SecretKeyRingEditorInterface { subkeyFingerprint: OpenPgpFingerprint, protector: SecretKeyRingProtector, revocationAttributes: RevocationAttributes? - ): PGPSignature + ): OpenPGPSignature /** * Change the passphrase of the whole key ring. @@ -676,7 +721,7 @@ interface SecretKeyRingEditorInterface { * * @return the key */ - fun done(): PGPSecretKeyRing + fun done(): OpenPGPKey fun addSubKey( keySpec: KeySpec, diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/PasswordBasedSecretKeyRingProtector.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/PasswordBasedSecretKeyRingProtector.kt index a4f9d2bb..1a1125e6 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/PasswordBasedSecretKeyRingProtector.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/PasswordBasedSecretKeyRingProtector.kt @@ -7,6 +7,7 @@ package org.pgpainless.key.protection import org.bouncycastle.bcpg.KeyIdentifier import org.bouncycastle.openpgp.PGPKeyRing import org.bouncycastle.openpgp.PGPSecretKey +import org.bouncycastle.openpgp.api.OpenPGPCertificate import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider import org.pgpainless.util.Passphrase @@ -32,6 +33,25 @@ class PasswordBasedSecretKeyRingProtector : BaseSecretKeyRingProtector { ) : super(passphraseProvider, settings) companion object { + + @JvmStatic + fun forKey( + cert: OpenPGPCertificate, + passphrase: Passphrase + ): PasswordBasedSecretKeyRingProtector { + return object : SecretKeyPassphraseProvider { + + override fun getPassphraseFor(keyIdentifier: KeyIdentifier): Passphrase? { + return if (hasPassphrase(keyIdentifier)) passphrase else null + } + + override fun hasPassphrase(keyIdentifier: KeyIdentifier): Boolean { + return cert.getKey(keyIdentifier) != null + } + } + .let { PasswordBasedSecretKeyRingProtector(it) } + } + @JvmStatic fun forKey( keyRing: PGPKeyRing, diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/SecretKeyRingProtector.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/SecretKeyRingProtector.kt index 9fe2ea8f..23f455e7 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/SecretKeyRingProtector.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/SecretKeyRingProtector.kt @@ -12,6 +12,7 @@ import org.bouncycastle.openpgp.PGPSecretKey import org.bouncycastle.openpgp.PGPSecretKeyRing import org.bouncycastle.openpgp.api.KeyPassphraseProvider import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey +import org.bouncycastle.openpgp.api.OpenPGPKey import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider @@ -105,6 +106,10 @@ interface SecretKeyRingProtector : KeyPassphraseProvider { KeyRingProtectionSettings.secureDefaultSettings(), missingPassphraseCallback) + @JvmStatic + fun unlockEachKeyWith(passphrase: Passphrase, keys: OpenPGPKey): SecretKeyRingProtector = + fromPassphraseMap(keys.secretKeys.keys.associateWith { passphrase }) + /** * Use the provided passphrase to lock/unlock all keys in the provided key ring. * diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/PrimaryKeyBindingSignatureBuilder.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/PrimaryKeyBindingSignatureBuilder.kt index 8c610930..6fde2686 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/PrimaryKeyBindingSignatureBuilder.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/PrimaryKeyBindingSignatureBuilder.kt @@ -8,6 +8,8 @@ import java.util.function.Predicate import org.bouncycastle.openpgp.PGPException import org.bouncycastle.openpgp.PGPPublicKey import org.bouncycastle.openpgp.PGPSignature +import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentSignature +import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPPrimaryKey import org.bouncycastle.openpgp.api.OpenPGPKey import org.pgpainless.PGPainless import org.pgpainless.algorithm.HashAlgorithm @@ -63,4 +65,7 @@ class PrimaryKeyBindingSignatureBuilder : fun build(primaryKey: PGPPublicKey): PGPSignature = buildAndInitSignatureGenerator() .generateCertification(primaryKey, signingKey.publicKey.pgpPublicKey) + + fun build(primaryKey: OpenPGPPrimaryKey): OpenPGPComponentSignature = + OpenPGPComponentSignature(build(primaryKey.pgpPublicKey), primaryKey, primaryKey) } diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/RevocationSignatureBuilder.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/RevocationSignatureBuilder.kt index 60879ebc..e41e4308 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/RevocationSignatureBuilder.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/builder/RevocationSignatureBuilder.kt @@ -8,7 +8,11 @@ import java.util.function.Predicate import org.bouncycastle.openpgp.PGPException import org.bouncycastle.openpgp.PGPPublicKey import org.bouncycastle.openpgp.PGPSignature +import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey +import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentSignature +import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPUserId 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 @@ -59,6 +63,11 @@ constructor( } } + fun build(revokeeKey: OpenPGPComponentKey): OpenPGPSignature { + return OpenPGPComponentSignature( + build(revokeeKey.pgpPublicKey), signingKey.publicKey, revokeeKey) + } + @Throws(PGPException::class) fun build(revokeeUserId: CharSequence): PGPSignature = buildAndInitSignatureGenerator() @@ -69,6 +78,11 @@ constructor( } .generateCertification(revokeeUserId.toString(), signingKey.publicKey.pgpPublicKey) + fun build(revokeeUserId: OpenPGPUserId): OpenPGPComponentSignature { + return OpenPGPComponentSignature( + build(revokeeUserId.userId), signingKey.publicKey, revokeeUserId) + } + init { hashedSubpackets.setRevocable(false) } 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 9816ee29..1dcfa966 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 @@ -8,6 +8,8 @@ import java.util.function.Predicate import org.bouncycastle.openpgp.PGPException import org.bouncycastle.openpgp.PGPPublicKey import org.bouncycastle.openpgp.PGPSignature +import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey +import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentSignature import org.bouncycastle.openpgp.api.OpenPGPKey import org.pgpainless.PGPainless import org.pgpainless.algorithm.HashAlgorithm @@ -77,4 +79,7 @@ class SubkeyBindingSignatureBuilder : AbstractSignatureBuilder, (String) -> Boolean { @@ -72,6 +73,14 @@ abstract class SelectUserId : Predicate, (String) -> Boolean { @JvmStatic fun byEmail(email: CharSequence) = or(exactMatch(email), containsEmailAddress(email)) + @JvmStatic + fun validUserId(key: OpenPGPCertificate) = + object : SelectUserId() { + private val info = PGPainless.getInstance().inspect(key) + + override fun invoke(userId: String): Boolean = info.isUserIdValid(userId) + } + @JvmStatic fun validUserId(keyRing: PGPKeyRing) = object : SelectUserId() { diff --git a/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/SigningTest.java b/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/SigningTest.java index 2356be1f..6fb0192b 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/SigningTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/SigningTest.java @@ -23,6 +23,7 @@ import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.bouncycastle.util.io.Streams; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; @@ -130,16 +131,16 @@ public class SigningTest { @ExtendWith(TestAllImplementations.class) public void testSignWithRevokedUserIdFails() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("alice", "password123") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("alice", "password123"); SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAnyKeyWith( Passphrase.fromPassword("password123")); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .revokeUserId("alice", protector) .done(); - final PGPSecretKeyRing fSecretKeys = secretKeys; + final OpenPGPKey fSecretKeys = secretKeys; SigningOptions opts = SigningOptions.get(); // "alice" has been revoked diff --git a/pgpainless-core/src/test/java/org/pgpainless/example/ModifyKeys.java b/pgpainless-core/src/test/java/org/pgpainless/example/ModifyKeys.java index 696a17ae..487a8817 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/example/ModifyKeys.java +++ b/pgpainless-core/src/test/java/org/pgpainless/example/ModifyKeys.java @@ -9,14 +9,14 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.io.IOException; import java.util.Date; import java.util.List; import org.bouncycastle.bcpg.KeyIdentifier; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPPublicKeyRing; -import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.api.OpenPGPCertificate; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; @@ -34,25 +34,25 @@ import org.pgpainless.util.Passphrase; /** * PGPainless offers a simple API to modify keys by adding and replacing signatures and/or subkeys. - * The main entry point to this API is {@link PGPainless#modifyKeyRing(PGPSecretKeyRing)}. + * The main entry point to this API is {@link PGPainless#modify(OpenPGPKey)}. */ public class ModifyKeys { private final String userId = "alice@pgpainless.org"; private final String originalPassphrase = "p4ssw0rd"; - private PGPSecretKeyRing secretKey; - private long primaryKeyId; + private OpenPGPKey secretKey; + private KeyIdentifier primaryKeyId; private KeyIdentifier encryptionSubkeyId; private KeyIdentifier signingSubkeyId; @BeforeEach public void generateKey() { - secretKey = PGPainless.generateKeyRing() - .modernKeyRing(userId, originalPassphrase) - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + secretKey = api.generateKey() + .modernKeyRing(userId, originalPassphrase); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKey); - primaryKeyId = info.getKeyIdentifier().getKeyId(); + KeyRingInfo info = api.inspect(secretKey); + primaryKeyId = info.getKeyIdentifier(); encryptionSubkeyId = info.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0).getKeyIdentifier(); signingSubkeyId = info.getSigningSubkeys().get(0).getKeyIdentifier(); } @@ -63,9 +63,9 @@ public class ModifyKeys { @Test public void extractPublicKey() { // the certificate consists of only the public keys - PGPPublicKeyRing certificate = PGPainless.extractCertificate(secretKey); + OpenPGPCertificate certificate = secretKey.toCertificate(); - KeyRingInfo info = PGPainless.inspectKeyRing(certificate); + KeyRingInfo info = PGPainless.getInstance().inspect(certificate); assertFalse(info.isSecretKey()); } @@ -73,11 +73,11 @@ public class ModifyKeys { * This example demonstrates how to export a secret key or certificate to an ASCII armored string. */ @Test - public void toAsciiArmoredString() { - PGPPublicKeyRing certificate = PGPainless.extractCertificate(secretKey); + public void toAsciiArmoredString() throws IOException { + OpenPGPCertificate certificate = secretKey.toCertificate(); - String asciiArmoredSecretKey = PGPainless.asciiArmor(secretKey); - String asciiArmoredCertificate = PGPainless.asciiArmor(certificate); + String asciiArmoredSecretKey = secretKey.toAsciiArmoredString(); + String asciiArmoredCertificate = certificate.toAsciiArmoredString(); assertTrue(asciiArmoredSecretKey.startsWith("-----BEGIN PGP PRIVATE KEY BLOCK-----")); assertTrue(asciiArmoredCertificate.startsWith("-----BEGIN PGP PUBLIC KEY BLOCK-----")); @@ -88,7 +88,8 @@ public class ModifyKeys { */ @Test public void changePassphrase() throws PGPException { - secretKey = PGPainless.modifyKeyRing(secretKey) + PGPainless api = PGPainless.getInstance(); + secretKey = api.modify(secretKey) .changePassphraseFromOldPassphrase(Passphrase.fromPassword(originalPassphrase)) .withSecureDefaultSettings() .toNewPassphrase(Passphrase.fromPassword("n3wP4ssW0rD")) @@ -96,9 +97,9 @@ public class ModifyKeys { // Old passphrase no longer works assertThrows(WrongPassphraseException.class, () -> - UnlockSecretKey.unlockSecretKey(secretKey.getSecretKey(), Passphrase.fromPassword(originalPassphrase))); + UnlockSecretKey.unlockSecretKey(secretKey.getPGPSecretKeyRing().getSecretKey(), Passphrase.fromPassword(originalPassphrase))); // But the new one does - UnlockSecretKey.unlockSecretKey(secretKey.getSecretKey(), Passphrase.fromPassword("n3wP4ssW0rD")); + UnlockSecretKey.unlockSecretKey(secretKey.getPGPSecretKeyRing().getSecretKey(), Passphrase.fromPassword("n3wP4ssW0rD")); } /** @@ -107,9 +108,10 @@ public class ModifyKeys { */ @Test public void changeSingleSubkeyPassphrase() throws PGPException { - secretKey = PGPainless.modifyKeyRing(secretKey) + PGPainless api = PGPainless.getInstance(); + secretKey = api.modify(secretKey) // Here we change the passphrase of the encryption subkey - .changeSubKeyPassphraseFromOldPassphrase(encryptionSubkeyId.getKeyId(), Passphrase.fromPassword(originalPassphrase)) + .changeSubKeyPassphraseFromOldPassphrase(encryptionSubkeyId, Passphrase.fromPassword(originalPassphrase)) .withSecureDefaultSettings() .toNewPassphrase(Passphrase.fromPassword("cryptP4ssphr4s3")) .done(); @@ -117,12 +119,12 @@ public class ModifyKeys { // encryption key can now only be unlocked using the new passphrase assertThrows(WrongPassphraseException.class, () -> UnlockSecretKey.unlockSecretKey( - secretKey.getSecretKey(encryptionSubkeyId), Passphrase.fromPassword(originalPassphrase))); + secretKey.getSecretKey(encryptionSubkeyId).getPGPSecretKey(), Passphrase.fromPassword(originalPassphrase))); UnlockSecretKey.unlockSecretKey( - secretKey.getSecretKey(encryptionSubkeyId), Passphrase.fromPassword("cryptP4ssphr4s3")); + secretKey.getSecretKey(encryptionSubkeyId).getPGPSecretKey(), Passphrase.fromPassword("cryptP4ssphr4s3")); // primary key remains unchanged UnlockSecretKey.unlockSecretKey( - secretKey.getSecretKey(primaryKeyId), Passphrase.fromPassword(originalPassphrase)); + secretKey.getSecretKey(primaryKeyId).getPGPSecretKey(), Passphrase.fromPassword(originalPassphrase)); } /** @@ -130,13 +132,14 @@ public class ModifyKeys { */ @Test public void addUserId() throws PGPException { + PGPainless api = PGPainless.getInstance(); SecretKeyRingProtector protector = SecretKeyRingProtector.unlockEachKeyWith(Passphrase.fromPassword(originalPassphrase), secretKey); - secretKey = PGPainless.modifyKeyRing(secretKey) + secretKey = api.modify(secretKey) .addUserId("additional@user.id", protector) .done(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKey); + KeyRingInfo info = api.inspect(secretKey); assertTrue(info.isUserIdValid("additional@user.id")); assertFalse(info.isUserIdValid("another@user.id")); } @@ -156,11 +159,12 @@ public class ModifyKeys { */ @Test public void addSubkey() { + PGPainless api = PGPainless.getInstance(); // Protector for unlocking the existing secret key SecretKeyRingProtector protector = SecretKeyRingProtector.unlockEachKeyWith(Passphrase.fromPassword(originalPassphrase), secretKey); Passphrase subkeyPassphrase = Passphrase.fromPassword("subk3yP4ssphr4s3"); - secretKey = PGPainless.modifyKeyRing(secretKey) + secretKey = api.modify(secretKey) .addSubKey( KeySpec.getBuilder(KeyType.ECDH(EllipticCurve._BRAINPOOLP512R1), KeyFlag.ENCRYPT_COMMS) .build(), @@ -168,7 +172,7 @@ public class ModifyKeys { protector) .done(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKey); + KeyRingInfo info = api.inspect(secretKey); assertEquals(4, info.getSecretKeys().size()); assertEquals(4, info.getPublicKeys().size()); List encryptionSubkeys = info.getEncryptionSubkeys(EncryptionPurpose.COMMUNICATIONS); @@ -176,7 +180,7 @@ public class ModifyKeys { OpenPGPCertificate.OpenPGPComponentKey addedKey = encryptionSubkeys.stream() .filter(it -> !it.getKeyIdentifier().matches(encryptionSubkeyId)).findFirst() .get(); - UnlockSecretKey.unlockSecretKey(secretKey.getSecretKey(addedKey.getKeyIdentifier()), subkeyPassphrase); + UnlockSecretKey.unlockSecretKey(secretKey.getSecretKey(addedKey.getKeyIdentifier()).getPGPSecretKey(), subkeyPassphrase); } /** @@ -185,15 +189,16 @@ public class ModifyKeys { */ @Test public void setKeyExpirationDate() { + PGPainless api = PGPainless.getInstance(); Date expirationDate = DateUtil.parseUTCDate("2030-06-24 12:44:56 UTC"); SecretKeyRingProtector protector = SecretKeyRingProtector .unlockEachKeyWith(Passphrase.fromPassword(originalPassphrase), secretKey); - secretKey = PGPainless.modifyKeyRing(secretKey) + secretKey = api.modify(secretKey) .setExpirationDate(expirationDate, protector) .done(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKey); + KeyRingInfo info = api.inspect(secretKey); assertEquals(DateUtil.formatUTCDate(expirationDate), DateUtil.formatUTCDate(info.getPrimaryKeyExpirationDate())); assertEquals(DateUtil.formatUTCDate(expirationDate), @@ -207,19 +212,20 @@ public class ModifyKeys { */ @Test public void revokeUserId() throws PGPException { + PGPainless api = PGPainless.getInstance(); SecretKeyRingProtector protector = SecretKeyRingProtector.unlockEachKeyWith( Passphrase.fromPassword(originalPassphrase), secretKey); - secretKey = PGPainless.modifyKeyRing(secretKey) + secretKey = api.modify(secretKey) .addUserId("alcie@pgpainless.org", protector) .done(); // Initially the user-id is valid - assertTrue(PGPainless.inspectKeyRing(secretKey).isUserIdValid("alcie@pgpainless.org")); + assertTrue(api.inspect(secretKey).isUserIdValid("alcie@pgpainless.org")); // Revoke the second user-id - secretKey = PGPainless.modifyKeyRing(secretKey) + secretKey = api.modify(secretKey) .revokeUserId("alcie@pgpainless.org", protector) .done(); // Now the user-id is no longer valid - assertFalse(PGPainless.inspectKeyRing(secretKey).isUserIdValid("alcie@pgpainless.org")); + assertFalse(api.inspect(secretKey).isUserIdValid("alcie@pgpainless.org")); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/TestKeys.java b/pgpainless-core/src/test/java/org/pgpainless/key/TestKeys.java index cd4c7319..38ba2a2d 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/TestKeys.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/TestKeys.java @@ -14,8 +14,11 @@ import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPUtil; +import org.bouncycastle.openpgp.api.OpenPGPCertificate; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator; import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator; +import org.pgpainless.PGPainless; import org.pgpainless.util.Passphrase; public class TestKeys { @@ -265,6 +268,10 @@ public class TestKeys { "=1d67\n" + "-----END PGP PRIVATE KEY BLOCK-----"; + public static OpenPGPKey getJulietKey() throws PGPException, IOException { + return PGPainless.getInstance().toKey(getJulietSecretKeyRing()); + } + public static PGPSecretKeyRing getJulietSecretKeyRing() throws IOException, PGPException { if (julietSecretKeyRing == null) { julietSecretKeyRing = new PGPSecretKeyRing( @@ -281,6 +288,10 @@ public class TestKeys { return julietSecretKeyRingCollection; } + public static OpenPGPCertificate getJulietCertificate() throws IOException { + return PGPainless.getInstance().toCertificate(getJulietPublicKeyRing()); + } + public static PGPPublicKeyRing getJulietPublicKeyRing() throws IOException { if (julietPublicKeyRing == null) { julietPublicKeyRing = new PGPPublicKeyRing( @@ -297,6 +308,10 @@ public class TestKeys { return julietPublicKeyRingCollection; } + public static OpenPGPKey getRomeoKey() throws PGPException, IOException { + return PGPainless.getInstance().toKey(getRomeoSecretKeyRing()); + } + public static PGPSecretKeyRing getRomeoSecretKeyRing() throws IOException, PGPException { if (romeoSecretKeyRing == null) { romeoSecretKeyRing = new PGPSecretKeyRing( @@ -313,6 +328,10 @@ public class TestKeys { return romeoSecretKeyRingCollection; } + public static OpenPGPCertificate getRomeoCertificate() throws IOException { + return PGPainless.getInstance().toCertificate(getRomeoPublicKeyRing()); + } + public static PGPPublicKeyRing getRomeoPublicKeyRing() throws IOException { if (romeoPublicKeyRing == null) { romeoPublicKeyRing = new PGPPublicKeyRing( @@ -329,6 +348,10 @@ public class TestKeys { return romeoPublicKeyRingCollection; } + public static OpenPGPKey getEmilKey() throws PGPException, IOException { + return PGPainless.getInstance().toKey(getEmilSecretKeyRing()); + } + public static PGPSecretKeyRing getEmilSecretKeyRing() throws IOException, PGPException { if (emilSecretKeyRing == null) { emilSecretKeyRing = new PGPSecretKeyRing( @@ -345,6 +368,10 @@ public class TestKeys { return emilSecretKeyRingCollection; } + public static OpenPGPCertificate getEmilCertificate() throws IOException { + return PGPainless.getInstance().toCertificate(getEmilPublicKeyRing()); + } + public static PGPPublicKeyRing getEmilPublicKeyRing() throws IOException { if (emilPublicKeyRing == null) { emilPublicKeyRing = new PGPPublicKeyRing( @@ -361,6 +388,10 @@ public class TestKeys { return emilPublicKeyRingCollection; } + public static OpenPGPKey getCryptieKey() throws PGPException, IOException { + return PGPainless.getInstance().toKey(getCryptieSecretKeyRing()); + } + public static PGPSecretKeyRing getCryptieSecretKeyRing() throws IOException, PGPException { if (cryptieSecretKeyRing == null) { cryptieSecretKeyRing = new PGPSecretKeyRing( @@ -377,6 +408,10 @@ public class TestKeys { return cryptieSecretKeyRingCollection; } + public static OpenPGPCertificate getCryptieCertificate() throws IOException { + return PGPainless.getInstance().toCertificate(getCryptiePublicKeyRing()); + } + public static PGPPublicKeyRing getCryptiePublicKeyRing() throws IOException { if (cryptiePublicKeyRing == null) { cryptiePublicKeyRing = new PGPPublicKeyRing( diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/generation/KeyGenerationSubpacketsTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/generation/KeyGenerationSubpacketsTest.java index b5c5a3a3..c8b86159 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/generation/KeyGenerationSubpacketsTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/generation/KeyGenerationSubpacketsTest.java @@ -18,10 +18,10 @@ import java.util.List; import org.bouncycastle.bcpg.sig.IssuerFingerprint; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPSignatureSubpacketVector; 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.HashAlgorithm; @@ -39,10 +39,10 @@ public class KeyGenerationSubpacketsTest { @Test public void verifyDefaultSubpacketsForUserIdSignatures() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice") - .getPGPSecretKeyRing(); - Date plus1Sec = new Date(secretKeys.getPublicKey().getCreationTime().getTime() + 1000); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice"); + Date plus1Sec = new Date(secretKeys.getPrimarySecretKey().getCreationTime().getTime() + 1000); + KeyRingInfo info = api.inspect(secretKeys); PGPSignature userIdSig = info.getLatestUserIdCertification("Alice"); assertNotNull(userIdSig); int keyFlags = userIdSig.getHashedSubPackets().getKeyFlags(); @@ -54,7 +54,7 @@ public class KeyGenerationSubpacketsTest { assertEquals("Alice", info.getPrimaryUserId()); - secretKeys = PGPainless.modifyKeyRing(secretKeys, plus1Sec) + secretKeys = api.modify(secretKeys, plus1Sec) .addUserId("Bob", new SelfSignatureSubpackets.Callback() { @Override @@ -66,7 +66,7 @@ public class KeyGenerationSubpacketsTest { .addUserId("Alice", SecretKeyRingProtector.unprotectedKeys()) .done(); - info = PGPainless.inspectKeyRing(secretKeys, plus1Sec); + info = api.inspect(secretKeys, plus1Sec); userIdSig = info.getLatestUserIdCertification("Alice"); assertNotNull(userIdSig); @@ -89,7 +89,7 @@ public class KeyGenerationSubpacketsTest { Date now = plus1Sec; Date t1 = new Date(now.getTime() + 1000 * 60 * 60); - secretKeys = PGPainless.modifyKeyRing(secretKeys, t1) + secretKeys = api.modify(secretKeys, t1) .addUserId("Alice", new SelfSignatureSubpackets.Callback() { @Override public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) { @@ -98,7 +98,7 @@ public class KeyGenerationSubpacketsTest { } }, SecretKeyRingProtector.unprotectedKeys()) .done(); - info = PGPainless.inspectKeyRing(secretKeys, t1); + info = api.inspect(secretKeys, t1); assertEquals("Alice", info.getPrimaryUserId()); assertEquals(Collections.singleton(HashAlgorithm.SHA1), info.getPreferredHashAlgorithms("Alice")); } @@ -106,29 +106,29 @@ public class KeyGenerationSubpacketsTest { @Test public void verifyDefaultSubpacketsForSubkeyBindingSignatures() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice") - .getPGPSecretKeyRing(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice"); + KeyRingInfo info = api.inspect(secretKeys); List keysBefore = info.getPublicKeys(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .addSubKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.SIGN_DATA).build(), Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys()) .done(); - info = PGPainless.inspectKeyRing(secretKeys); + info = api.inspect(secretKeys); List keysAfter = new ArrayList<>(info.getPublicKeys()); keysAfter.removeAll(keysBefore); assertEquals(1, keysAfter.size()); OpenPGPCertificate.OpenPGPComponentKey newSigningKey = keysAfter.get(0); - PGPSignature bindingSig = info.getCurrentSubkeyBindingSignature(newSigningKey.getKeyIdentifier().getKeyId()); + PGPSignature bindingSig = info.getCurrentSubkeyBindingSignature(newSigningKey.getKeyIdentifier()); assertNotNull(bindingSig); assureSignatureHasDefaultSubpackets(bindingSig, secretKeys, KeyFlag.SIGN_DATA); assertNotNull(bindingSig.getHashedSubPackets().getEmbeddedSignatures().get(0)); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .addSubKey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS).build(), Passphrase.emptyPassphrase(), new SelfSignatureSubpackets.Callback() { @@ -139,24 +139,24 @@ public class KeyGenerationSubpacketsTest { }, SecretKeyRingProtector.unprotectedKeys()) .done(); - info = PGPainless.inspectKeyRing(secretKeys); + info = api.inspect(secretKeys); keysAfter = new ArrayList<>(info.getPublicKeys()); keysAfter.removeAll(keysBefore); keysAfter.remove(newSigningKey); assertEquals(1, keysAfter.size()); OpenPGPCertificate.OpenPGPComponentKey newEncryptionKey = keysAfter.get(0); - bindingSig = info.getCurrentSubkeyBindingSignature(newEncryptionKey.getKeyIdentifier().getKeyId()); + bindingSig = info.getCurrentSubkeyBindingSignature(newEncryptionKey.getKeyIdentifier()); assertNotNull(bindingSig); assertNull(bindingSig.getHashedSubPackets().getIssuerFingerprint()); assertEquals(KeyFlag.toBitmask(KeyFlag.ENCRYPT_COMMS), bindingSig.getHashedSubPackets().getKeyFlags()); } - private void assureSignatureHasDefaultSubpackets(PGPSignature signature, PGPSecretKeyRing secretKeys, KeyFlag... keyFlags) { + private void assureSignatureHasDefaultSubpackets(PGPSignature signature, OpenPGPKey secretKeys, KeyFlag... keyFlags) { PGPSignatureSubpacketVector hashedSubpackets = signature.getHashedSubPackets(); assertNotNull(hashedSubpackets.getIssuerFingerprint()); - assertEquals(secretKeys.getPublicKey().getKeyID(), hashedSubpackets.getIssuerKeyID()); + assertEquals(secretKeys.getKeyIdentifier().getKeyId(), hashedSubpackets.getIssuerKeyID()); assertArrayEquals( - secretKeys.getPublicKey().getFingerprint(), + secretKeys.getFingerprint(), hashedSubpackets.getIssuerFingerprint().getFingerprint()); assertEquals(hashedSubpackets.getKeyFlags(), KeyFlag.toBitmask(keyFlags)); } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/info/KeyRingInfoTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/info/KeyRingInfoTest.java index e79e03ae..c7d20491 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/info/KeyRingInfoTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/info/KeyRingInfoTest.java @@ -24,9 +24,7 @@ import java.util.Set; import org.bouncycastle.bcpg.KeyIdentifier; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSecretKey; -import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.api.OpenPGPCertificate; import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.JUtils; @@ -50,7 +48,6 @@ import org.pgpainless.key.generation.type.ecc.EllipticCurve; import org.pgpainless.key.generation.type.eddsa_legacy.EdDSALegacyCurve; import org.pgpainless.key.protection.SecretKeyRingProtector; import org.pgpainless.key.protection.UnprotectedKeysProtector; -import org.pgpainless.key.util.KeyRingUtils; import org.pgpainless.key.util.RevocationAttributes; import org.pgpainless.key.util.UserId; import org.pgpainless.util.DateUtil; @@ -62,11 +59,12 @@ public class KeyRingInfoTest { @TestTemplate @ExtendWith(TestAllImplementations.class) public void testWithEmilsKeys() throws IOException, PGPException { + PGPainless api = PGPainless.getInstance(); - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); - PGPPublicKeyRing publicKeys = TestKeys.getEmilPublicKeyRing(); - KeyRingInfo sInfo = PGPainless.inspectKeyRing(secretKeys); - KeyRingInfo pInfo = PGPainless.inspectKeyRing(publicKeys); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); + OpenPGPCertificate publicKeys = TestKeys.getEmilCertificate(); + KeyRingInfo sInfo = api.inspect(secretKeys); + KeyRingInfo pInfo = api.inspect(publicKeys); assertEquals(TestKeys.EMIL_KEY_ID, sInfo.getKeyIdentifier().getKeyId()); assertEquals(TestKeys.EMIL_KEY_ID, pInfo.getKeyIdentifier().getKeyId()); @@ -108,13 +106,13 @@ public class KeyRingInfoTest { assertNull(sInfo.getRevocationDate()); assertNull(pInfo.getRevocationDate()); Date revocationDate = DateUtil.now(); - PGPSecretKeyRing revoked = PGPainless.modifyKeyRing(secretKeys).revoke( + OpenPGPKey revoked = api.modify(secretKeys).revoke( new UnprotectedKeysProtector(), RevocationAttributes.createKeyRevocation() .withReason(RevocationAttributes.Reason.KEY_RETIRED) .withoutDescription() ).done(); - KeyRingInfo rInfo = PGPainless.inspectKeyRing(revoked); + KeyRingInfo rInfo = api.inspect(revoked); assertNotNull(rInfo.getRevocationDate()); assertEquals(revocationDate.getTime(), rInfo.getRevocationDate().getTime(), 5); assertEquals(revocationDate.getTime(), rInfo.getLastModified().getTime(), 5); @@ -125,32 +123,34 @@ public class KeyRingInfoTest { @Test public void testIsFullyDecrypted() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); + KeyRingInfo info = api.inspect(secretKeys); assertTrue(info.isFullyDecrypted()); - secretKeys = encryptSecretKeys(secretKeys); - info = PGPainless.inspectKeyRing(secretKeys); + secretKeys = encryptSecretKeys(secretKeys, api); + info = api.inspect(secretKeys); assertFalse(info.isFullyDecrypted()); } @Test public void testIsFullyEncrypted() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); + KeyRingInfo info = api.inspect(secretKeys); assertFalse(info.isFullyEncrypted()); - secretKeys = encryptSecretKeys(secretKeys); - info = PGPainless.inspectKeyRing(secretKeys); + secretKeys = encryptSecretKeys(secretKeys, api); + info = api.inspect(secretKeys); assertTrue(info.isFullyEncrypted()); } - private static PGPSecretKeyRing encryptSecretKeys(PGPSecretKeyRing secretKeys) throws PGPException { - return PGPainless.modifyKeyRing(secretKeys) + private static OpenPGPKey encryptSecretKeys(OpenPGPKey secretKeys, PGPainless api) throws PGPException { + return api.modify(secretKeys) .changePassphraseFromOldPassphrase(Passphrase.emptyPassphrase()) .withSecureDefaultSettings() .toNewPassphrase(Passphrase.fromPassword("sw0rdf1sh")) @@ -160,27 +160,29 @@ public class KeyRingInfoTest { @Test public void testGetSecretKey() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing(); - PGPPublicKeyRing publicKeys = KeyRingUtils.publicKeyRingFrom(secretKeys); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getCryptieKey(); + OpenPGPCertificate publicKeys = secretKeys.toCertificate(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); OpenPGPKey.OpenPGPSecretKey primarySecretKey = info.getSecretKey(); assertNotNull(primarySecretKey); - assertEquals(KeyRingUtils.requirePrimarySecretKeyFrom(secretKeys), primarySecretKey.getPGPSecretKey()); + assertEquals(secretKeys.getPrimarySecretKey().getPGPSecretKey(), primarySecretKey.getPGPSecretKey()); - info = PGPainless.inspectKeyRing(publicKeys); + info = api.inspect(publicKeys); assertNull(info.getSecretKey()); } @Test public void testGetPublicKey() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getCryptieKey(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); - assertEquals(KeyRingUtils.requirePrimaryPublicKeyFrom(secretKeys), info.getPrimaryKey().getPGPPublicKey()); + KeyRingInfo info = api.inspect(secretKeys); + assertEquals(secretKeys.getPrimaryKey().getPGPPublicKey(), info.getPrimaryKey().getPGPPublicKey()); - assertEquals(KeyRingUtils.requirePrimarySecretKeyFrom(secretKeys), - KeyRingUtils.requireSecretKeyFrom(secretKeys, secretKeys.getPublicKey().getKeyID())); + assertEquals(secretKeys.getPrimarySecretKey().getPGPSecretKey(), + secretKeys.getPGPSecretKeyRing().getSecretKey(secretKeys.getKeyIdentifier())); } @TestTemplate @@ -224,8 +226,8 @@ public class KeyRingInfoTest { @TestTemplate @ExtendWith(TestAllImplementations.class) public void testGetKeysWithFlagsAndExpiry() { - - PGPSecretKeyRing secretKeys = PGPainless.buildKeyRing() + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = PGPainless.buildKeyRing() .setPrimaryKey(KeySpec.getBuilder( KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.CERTIFY_OTHER)) .addSubkey(KeySpec.getBuilder( @@ -234,10 +236,9 @@ public class KeyRingInfoTest { .addSubkey(KeySpec.getBuilder( KeyType.ECDSA(EllipticCurve._BRAINPOOLP384R1), KeyFlag.SIGN_DATA)) .addUserId(UserId.builder().withName("Alice").withEmail("alice@pgpainless.org").build()) - .build() - .getPGPSecretKeyRing(); + .build(); - Iterator keys = secretKeys.iterator(); + Iterator keys = secretKeys.getPGPSecretKeyRing().iterator(); Date now = DateUtil.now(); Calendar calendar = Calendar.getInstance(); @@ -255,11 +256,11 @@ public class KeyRingInfoTest { PGPSecretKey signingKey = keys.next(); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .setExpirationDate(primaryKeyExpiration, protector) .done(); - KeyRingInfo info = new KeyRingInfo(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); List encryptionKeys = info.getKeysWithKeyFlag(KeyFlag.ENCRYPT_STORAGE); assertEquals(1, encryptionKeys.size()); @@ -354,9 +355,10 @@ public class KeyRingInfoTest { "crH02GDG8CotAnEHkLTz9GPO80q8mowzBV0EtHsXb4TeAFw5T5Qd0a5I+wk=\n" + "=Vcb3\n" + "-----END PGP ARMORED FILE-----\n"; - OpenPGPCertificate certificate = PGPainless.getInstance().readKey().parseCertificate(KEY); + PGPainless api = PGPainless.getInstance(); + OpenPGPCertificate certificate = api.readKey().parseCertificate(KEY); - KeyRingInfo info = PGPainless.inspectKeyRing(certificate, DateUtil.parseUTCDate("2021-10-10 00:00:00 UTC")); + KeyRingInfo info = api.inspect(certificate, DateUtil.parseUTCDate("2021-10-10 00:00:00 UTC")); // Subkey is hard revoked assertFalse(info.isKeyValidlyBound(new KeyIdentifier(5364407983539305061L))); } @@ -434,14 +436,15 @@ public class KeyRingInfoTest { "=7Feh\n" + "-----END PGP ARMORED FILE-----\n"; - OpenPGPCertificate certificate = PGPainless.getInstance().readKey().parseCertificate(KEY); + PGPainless api = PGPainless.getInstance(); + OpenPGPCertificate certificate = api.readKey().parseCertificate(KEY); final KeyIdentifier subkeyId = new KeyIdentifier(5364407983539305061L); - KeyRingInfo inspectDuringRevokedPeriod = PGPainless.inspectKeyRing(certificate, DateUtil.parseUTCDate("2019-01-02 00:00:00 UTC")); + KeyRingInfo inspectDuringRevokedPeriod = api.inspect(certificate, DateUtil.parseUTCDate("2019-01-02 00:00:00 UTC")); assertFalse(inspectDuringRevokedPeriod.isKeyValidlyBound(subkeyId)); assertNotNull(inspectDuringRevokedPeriod.getSubkeyRevocationSignature(subkeyId)); - KeyRingInfo inspectAfterRebinding = PGPainless.inspectKeyRing(certificate, DateUtil.parseUTCDate("2020-01-02 00:00:00 UTC")); + KeyRingInfo inspectAfterRebinding = api.inspect(certificate, DateUtil.parseUTCDate("2020-01-02 00:00:00 UTC")); assertTrue(inspectAfterRebinding.isKeyValidlyBound(subkeyId)); } @@ -518,9 +521,10 @@ public class KeyRingInfoTest { "=MhJL\n" + "-----END PGP ARMORED FILE-----\n"; - OpenPGPCertificate keys = PGPainless.getInstance().readKey().parseCertificate(KEY); + PGPainless api = PGPainless.getInstance(); + OpenPGPCertificate keys = api.readKey().parseCertificate(KEY); - KeyRingInfo info = PGPainless.inspectKeyRing(keys); + KeyRingInfo info = api.inspect(keys); // Primary key is hard revoked assertFalse(info.isKeyValidlyBound(keys.getKeyIdentifier())); assertFalse(info.isFullyEncrypted()); @@ -528,49 +532,48 @@ public class KeyRingInfoTest { @Test public void getSecretKeyTest() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice") - .getPGPSecretKeyRing(); - OpenPGPKey key = new OpenPGPKey(secretKeys); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice"); + KeyRingInfo info = api.inspect(secretKeys); OpenPgpV4Fingerprint primaryKeyFingerprint = new OpenPgpV4Fingerprint(secretKeys); OpenPGPKey.OpenPGPSecretKey primaryKey = info.getSecretKey(primaryKeyFingerprint); assertNotNull(primaryKey); - assertEquals(key.getPrimarySecretKey().getKeyIdentifier(), primaryKey.getKeyIdentifier()); + assertEquals(secretKeys.getPrimarySecretKey().getKeyIdentifier(), primaryKey.getKeyIdentifier()); } @Test public void testGetLatestKeyCreationDate() throws PGPException, IOException { - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); Date latestCreationDate = DateUtil.parseUTCDate("2020-01-12 18:01:44 UTC"); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = PGPainless.getInstance().inspect(secretKeys); JUtils.assertDateEquals(latestCreationDate, info.getLatestKeyCreationDate()); } @Test public void testGetExpirationDateForUse_SPLIT() throws PGPException, IOException { - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); + KeyRingInfo info = PGPainless.getInstance().inspect(secretKeys); assertThrows(IllegalArgumentException.class, () -> info.getExpirationDateForUse(KeyFlag.SPLIT)); } @Test public void testGetExpirationDateForUse_SHARED() throws PGPException, IOException { - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); + KeyRingInfo info = PGPainless.getInstance().inspect(secretKeys); assertThrows(IllegalArgumentException.class, () -> info.getExpirationDateForUse(KeyFlag.SHARED)); } @Test public void testGetExpirationDateForUse_NoSuchKey() { - PGPSecretKeyRing secretKeys = PGPainless.buildKeyRing() + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = PGPainless.buildKeyRing() .addUserId("Alice") .setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.CERTIFY_OTHER)) - .build() - .getPGPSecretKeyRing(); + .build(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); assertThrows(NoSuchElementException.class, () -> info.getExpirationDateForUse(KeyFlag.ENCRYPT_COMMS)); } @@ -600,8 +603,8 @@ public class KeyRingInfoTest { "/+XL+qMMgLHaQ25aA11GVAkC\n" + "=7gbt\n" + "-----END PGP PRIVATE KEY BLOCK-----"; - - OpenPGPKey secretKeys = PGPainless.getInstance().readKey().parseKey(KEY); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.readKey().parseKey(KEY); final KeyIdentifier pkid = new KeyIdentifier(6643807985200014832L); final KeyIdentifier skid1 = new KeyIdentifier(-2328413746552029063L); final KeyIdentifier skid2 = new KeyIdentifier(-3276877650571760552L); @@ -611,7 +614,7 @@ public class KeyRingInfoTest { Arrays.asList(CompressionAlgorithm.ZLIB, CompressionAlgorithm.BZIP2, CompressionAlgorithm.ZIP, CompressionAlgorithm.UNCOMPRESSED)); Set preferredSymmetricAlgorithms = new LinkedHashSet<>( Arrays.asList(SymmetricKeyAlgorithm.AES_256, SymmetricKeyAlgorithm.AES_192, SymmetricKeyAlgorithm.AES_128)); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); // Bob is an invalid userId assertThrows(NoSuchElementException.class, () -> info.getPreferredSymmetricKeyAlgorithms("Bob")); @@ -694,10 +697,10 @@ public class KeyRingInfoTest { "C9h35EjDuD+1COXUOoW2B8LX6m2yf8cY72K70QgtGemj7UWhXL5u/wARAQAB\n" + "=A3B8\n" + "-----END PGP PUBLIC KEY BLOCK-----\n"; - - OpenPGPCertificate certificate = PGPainless.getInstance().readKey().parseCertificate(KEY); + PGPainless api = PGPainless.getInstance(); + OpenPGPCertificate certificate = api.readKey().parseCertificate(KEY); OpenPgpV4Fingerprint unboundKey = new OpenPgpV4Fingerprint("D622C916384E0F6D364907E55D918BBD521CCD10"); - KeyRingInfo info = PGPainless.inspectKeyRing(certificate); + KeyRingInfo info = api.inspect(certificate); assertFalse(info.isKeyValidlyBound(unboundKey.getKeyIdentifier())); @@ -773,9 +776,9 @@ public class KeyRingInfoTest { "qDzPRwEAhdVBeryRUcwjgwHX0xmMFK7vLkdonn8BR2++nXBO2g8=\n" + "=ZRAy\n" + "-----END PGP PRIVATE KEY BLOCK-----\n"; - - OpenPGPKey secretKeys = PGPainless.getInstance().readKey().parseKey(KEY); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.readKey().parseKey(KEY); + KeyRingInfo info = api.inspect(secretKeys); List emails = info.getEmailAddresses(); assertEquals(emails, Arrays.asList("alice@email.tld", "alice@pgpainless.org", "alice@openpgp.org", "alice@rfc4880.spec")); @@ -805,9 +808,9 @@ public class KeyRingInfoTest { "J5wP\n" + "=nFoO\n" + "-----END PGP PUBLIC KEY BLOCK-----"; - - OpenPGPCertificate cert = PGPainless.getInstance().readKey().parseCertificate(CERT); - KeyRingInfo info = PGPainless.inspectKeyRing(cert); + PGPainless api = PGPainless.getInstance(); + OpenPGPCertificate cert = api.readKey().parseCertificate(CERT); + KeyRingInfo info = api.inspect(cert); assertTrue(info.isUsableForEncryption()); } @@ -833,9 +836,9 @@ public class KeyRingInfoTest { "2XO/hpB2T8VXFfFKwj7U9LGkX+ciLg==\n" + "=etPP\n" + "-----END PGP PUBLIC KEY BLOCK-----"; - - OpenPGPCertificate publicKeys = PGPainless.getInstance().readKey().parseCertificate(CERT); - KeyRingInfo info = PGPainless.inspectKeyRing(publicKeys); + PGPainless api = PGPainless.getInstance(); + OpenPGPCertificate publicKeys = api.readKey().parseCertificate(CERT); + KeyRingInfo info = api.inspect(publicKeys); assertTrue(info.isUsableForEncryption(EncryptionPurpose.COMMUNICATIONS)); assertTrue(info.isUsableForEncryption(EncryptionPurpose.ANY)); @@ -870,8 +873,9 @@ public class KeyRingInfoTest { "AQCjeV+3VT+u1movwIYv4XkzB6gB+B2C+DK9nvG5sXZhBg==\n" + "=uqmO\n" + "-----END PGP PUBLIC KEY BLOCK-----"; - OpenPGPCertificate publicKeys = PGPainless.getInstance().readKey().parseCertificate(CERT); - KeyRingInfo info = PGPainless.inspectKeyRing(publicKeys); + PGPainless api = PGPainless.getInstance(); + OpenPGPCertificate publicKeys = api.readKey().parseCertificate(CERT); + KeyRingInfo info = api.inspect(publicKeys); assertFalse(info.isUsableForEncryption()); assertFalse(info.isUsableForEncryption(EncryptionPurpose.ANY)); diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/info/PrimaryUserIdTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/info/PrimaryUserIdTest.java index a8d412ad..2a3895b5 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/info/PrimaryUserIdTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/info/PrimaryUserIdTest.java @@ -7,7 +7,7 @@ package org.pgpainless.key.info; import static org.junit.jupiter.api.Assertions.assertEquals; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; import org.pgpainless.key.protection.SecretKeyRingProtector; @@ -16,13 +16,13 @@ public class PrimaryUserIdTest { @Test public void testGetPrimaryUserId() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("alice@wonderland.lit") - .getPGPSecretKeyRing(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().simpleEcKeyRing("alice@wonderland.lit"); + secretKeys = api.modify(secretKeys) .addUserId("mad_alice@wonderland.lit", SecretKeyRingProtector.unprotectedKeys()) .done(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); assertEquals("alice@wonderland.lit", info.getPrimaryUserId()); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/info/UserIdRevocationTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/info/UserIdRevocationTest.java index cf34f9fe..301daed5 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/info/UserIdRevocationTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/info/UserIdRevocationTest.java @@ -15,11 +15,12 @@ import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; +import org.bouncycastle.bcpg.KeyIdentifier; import org.bouncycastle.bcpg.SignatureSubpacketTags; import org.bouncycastle.bcpg.sig.RevocationReason; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; import org.pgpainless.algorithm.KeyFlag; @@ -37,7 +38,8 @@ public class UserIdRevocationTest { @Test public void testRevocationWithoutRevocationAttributes() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.buildKeyRing() + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = PGPainless.buildKeyRing() .setPrimaryKey(KeySpec.getBuilder( KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER)) @@ -45,28 +47,27 @@ public class UserIdRevocationTest { KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS)) .addUserId("primary@key.id") .addUserId("secondary@key.id") - .build() - .getPGPSecretKeyRing(); + .build(); // make a copy with revoked subkey - PGPSecretKeyRing revoked = PGPainless.modifyKeyRing(secretKeys) + OpenPGPKey revoked = api.modify(secretKeys) .revokeUserId("secondary@key.id", new UnprotectedKeysProtector()) .done(); - KeyRingInfo info = PGPainless.inspectKeyRing(revoked); + KeyRingInfo info = api.inspect(revoked); List userIds = info.getUserIds(); assertEquals(Arrays.asList("primary@key.id", "secondary@key.id"), userIds); assertTrue(info.isUserIdValid("primary@key.id")); assertFalse(info.isUserIdValid("sedondary@key.id")); assertFalse(info.isUserIdValid("tertiary@key.id")); - info = PGPainless.inspectKeyRing(secretKeys); + info = api.inspect(secretKeys); assertTrue(info.isUserIdValid("secondary@key.id")); // key on original secret key ring is still valid - revoked = PGPainless.modifyKeyRing(secretKeys) + revoked = api.modify(secretKeys) .revokeUserId("secondary@key.id", new UnprotectedKeysProtector()) .done(); - info = PGPainless.inspectKeyRing(revoked); + info = api.inspect(revoked); userIds = info.getUserIds(); assertEquals(Arrays.asList("primary@key.id", "secondary@key.id"), userIds); assertTrue(info.isUserIdValid("primary@key.id")); @@ -76,23 +77,23 @@ public class UserIdRevocationTest { @Test public void testRevocationWithRevocationReason() { - PGPSecretKeyRing secretKeys = PGPainless.buildKeyRing() + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = PGPainless.buildKeyRing() .setPrimaryKey(KeySpec.getBuilder( KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER)) .addSubkey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS)) .addUserId("primary@key.id") .addUserId("secondary@key.id") - .build() - .getPGPSecretKeyRing(); + .build(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .revokeUserId("secondary@key.id", new UnprotectedKeysProtector(), RevocationAttributes.createCertificateRevocation() .withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID) .withDescription("I lost my mail password")) .done(); - KeyRingInfo info = new KeyRingInfo(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); PGPSignature signature = info.getUserIdRevocation("secondary@key.id"); assertNotNull(signature); @@ -104,31 +105,31 @@ public class UserIdRevocationTest { @Test public void unknownKeyThrowsIllegalArgumentException() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing(); + OpenPGPKey secretKeys = TestKeys.getCryptieKey(); SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector - .forKey(secretKeys.getSecretKey(), TestKeys.CRYPTIE_PASSPHRASE); + .forKey(secretKeys, TestKeys.CRYPTIE_PASSPHRASE); - assertThrows(NoSuchElementException.class, () -> PGPainless.modifyKeyRing(secretKeys) - .revokeSubKey(1L, protector)); + assertThrows(NoSuchElementException.class, () -> PGPainless.getInstance().modify(secretKeys) + .revokeSubKey(new KeyIdentifier(1L), protector)); } @Test public void unknownUserIdThrowsNoSuchElementException() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing(); + OpenPGPKey secretKeys = TestKeys.getCryptieKey(); SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector - .forKey(secretKeys.getSecretKey(), TestKeys.CRYPTIE_PASSPHRASE); + .forKey(secretKeys, TestKeys.CRYPTIE_PASSPHRASE); - assertThrows(NoSuchElementException.class, () -> PGPainless.modifyKeyRing(secretKeys) + assertThrows(NoSuchElementException.class, () -> PGPainless.getInstance().modify(secretKeys) .revokeUserId("invalid@user.id", protector)); } @Test public void invalidRevocationReasonThrowsIllegalArgumentException() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing(); + OpenPGPKey secretKeys = TestKeys.getCryptieKey(); SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector - .forKey(secretKeys.getSecretKey(), TestKeys.CRYPTIE_PASSPHRASE); + .forKey(secretKeys, TestKeys.CRYPTIE_PASSPHRASE); - assertThrows(IllegalArgumentException.class, () -> PGPainless.modifyKeyRing(secretKeys) + assertThrows(IllegalArgumentException.class, () -> PGPainless.getInstance().modify(secretKeys) .revokeUserId("cryptie@encrypted.key", protector, RevocationAttributes.createKeyRevocation().withReason(RevocationAttributes.Reason.KEY_RETIRED) .withDescription("This is not a valid certification revocation reason."))); diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddSubKeyTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddSubKeyTest.java index 02967ad3..7e2d8a38 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddSubKeyTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddSubKeyTest.java @@ -16,8 +16,7 @@ import java.util.List; import org.bouncycastle.bcpg.KeyIdentifier; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKey; -import org.bouncycastle.openpgp.PGPSecretKey; -import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; import org.pgpainless.PGPainless; @@ -39,14 +38,15 @@ public class AddSubKeyTest { @ExtendWith(TestAllImplementations.class) public void testAddSubKey() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getCryptieKey(); List keyIdentifiersBefore = new ArrayList<>(); - for (Iterator it = secretKeys.getPublicKeys(); it.hasNext(); ) { + for (Iterator it = secretKeys.getPGPSecretKeyRing().getPublicKeys(); it.hasNext(); ) { keyIdentifiersBefore.add(it.next().getKeyIdentifier()); } - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .addSubKey( KeySpec.getBuilder(ECDSA.fromCurve(EllipticCurve._P256), KeyFlag.SIGN_DATA).build(), Passphrase.fromPassword("subKeyPassphrase"), @@ -54,7 +54,7 @@ public class AddSubKeyTest { .done(); List keyIdentifiersAfter = new ArrayList<>(); - for (Iterator it = secretKeys.getPublicKeys(); it.hasNext(); ) { + for (Iterator it = secretKeys.getPGPSecretKeyRing().getPublicKeys(); it.hasNext(); ) { keyIdentifiersAfter.add(it.next().getKeyIdentifier()); } assertNotEquals(keyIdentifiersAfter, keyIdentifiersBefore); @@ -62,12 +62,12 @@ public class AddSubKeyTest { keyIdentifiersAfter.removeAll(keyIdentifiersBefore); KeyIdentifier subKeyIdentifier = keyIdentifiersAfter.get(0); - PGPSecretKey subKey = secretKeys.getSecretKey(subKeyIdentifier); + OpenPGPKey.OpenPGPSecretKey subKey = secretKeys.getSecretKey(subKeyIdentifier); SecretKeyRingProtector protector = SecretKeyRingProtector.unlockEachKeyWith( Passphrase.fromPassword("subKeyPassphrase"), secretKeys); UnlockSecretKey.unlockSecretKey(subKey, protector); - KeyRingInfo info = new KeyRingInfo(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); assertEquals(Collections.singletonList(KeyFlag.SIGN_DATA), info.getKeyFlagsOf(subKeyIdentifier)); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddSubkeyWithModifiedBindingSignatureSubpacketsTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddSubkeyWithModifiedBindingSignatureSubpacketsTest.java index a3aea2f0..86bcd54e 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddSubkeyWithModifiedBindingSignatureSubpacketsTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddSubkeyWithModifiedBindingSignatureSubpacketsTest.java @@ -14,9 +14,9 @@ import java.util.List; import org.bouncycastle.bcpg.sig.NotationData; import org.bouncycastle.openpgp.PGPKeyPair; -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.JUtils; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; @@ -38,11 +38,11 @@ public class AddSubkeyWithModifiedBindingSignatureSubpacketsTest { @Test public void bindEncryptionSubkeyAndModifyBindingSignatureHashedSubpackets() { + PGPainless api = PGPainless.getInstance(); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("Alice ") - .getPGPSecretKeyRing(); - KeyRingInfo before = PGPainless.inspectKeyRing(secretKeys); + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("Alice "); + KeyRingInfo before = api.inspect(secretKeys); List signingKeysBefore = before.getSigningSubkeys(); PGPKeyPair secretSubkey = KeyRingBuilder.generateKeyPair( @@ -50,7 +50,7 @@ public class AddSubkeyWithModifiedBindingSignatureSubpacketsTest { OpenPGPKeyVersion.v4); long secondsUntilExpiration = 1000; - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .addSubKey(secretSubkey, new SelfSignatureSubpackets.Callback() { @Override public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) { @@ -60,7 +60,7 @@ public class AddSubkeyWithModifiedBindingSignatureSubpacketsTest { }, SecretKeyRingProtector.unprotectedKeys(), protector, KeyFlag.SIGN_DATA) .done(); - KeyRingInfo after = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo after = api.inspect(secretKeys); List signingKeysAfter = after.getSigningSubkeys(); signingKeysAfter.removeAll(signingKeysBefore); assertFalse(signingKeysAfter.isEmpty()); diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddUserIdTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddUserIdTest.java index f070c9fa..48875ebf 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddUserIdTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/AddUserIdTest.java @@ -37,31 +37,31 @@ public class AddUserIdTest { @ExtendWith(TestAllImplementations.class) public void addUserIdToExistingKeyRing() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .simpleEcKeyRing("alice@wonderland.lit", "rabb1th0le") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .simpleEcKeyRing("alice@wonderland.lit", "rabb1th0le"); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); Iterator userIds = info.getValidUserIds().iterator(); assertEquals("alice@wonderland.lit", userIds.next()); assertFalse(userIds.hasNext()); SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector.forKey(secretKeys, Passphrase.fromPassword("rabb1th0le")); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .addUserId("cheshirecat@wonderland.lit", protector) .done(); - info = PGPainless.inspectKeyRing(secretKeys); + info = api.inspect(secretKeys); userIds = info.getValidUserIds().iterator(); assertEquals("alice@wonderland.lit", userIds.next()); assertEquals("cheshirecat@wonderland.lit", userIds.next()); assertFalse(userIds.hasNext()); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .revokeUserId("cheshirecat@wonderland.lit", protector) .done(); - info = PGPainless.inspectKeyRing(secretKeys); + info = api.inspect(secretKeys); userIds = info.getValidUserIds().iterator(); assertEquals("alice@wonderland.lit", userIds.next()); assertFalse(userIds.hasNext()); @@ -96,20 +96,21 @@ public class AddUserIdTest { "=bk4o\r\n" + "-----END PGP PRIVATE KEY BLOCK-----\r\n"; - OpenPGPKey key = PGPainless.getInstance().readKey().parseKey(ARMORED_PRIVATE_KEY); - PGPSecretKeyRing secretKeys = key.getPGPSecretKeyRing(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + PGPainless api = PGPainless.getInstance(); + + OpenPGPKey key = api.readKey().parseKey(ARMORED_PRIVATE_KEY); + KeyRingInfo info = api.inspect(key); Iterator userIds = info.getValidUserIds().iterator(); assertEquals("", userIds.next()); assertFalse(userIds.hasNext()); SecretKeyRingProtector protector = new UnprotectedKeysProtector(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + key = api.modify(key) .revokeUserId("", protector) .addUserId("cheshirecat@wonderland.lit", protector) .done(); - info = PGPainless.inspectKeyRing(secretKeys); + info = api.inspect(key); userIds = info.getValidUserIds().iterator(); assertEquals("cheshirecat@wonderland.lit", userIds.next()); assertFalse(userIds.hasNext()); @@ -118,17 +119,17 @@ public class AddUserIdTest { @Test public void addNewPrimaryUserIdTest() { Date now = new Date(); - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("Alice") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("Alice"); UserId bob = UserId.builder().withName("Bob").noEmail().noComment().build(); - assertNotEquals("Bob", PGPainless.inspectKeyRing(secretKeys).getPrimaryUserId()); + assertNotEquals("Bob", api.inspect(secretKeys).getPrimaryUserId()); - secretKeys = PGPainless.modifyKeyRing(secretKeys, DateExtensionsKt.plusSeconds(now, 1)) + secretKeys = api.modify(secretKeys, DateExtensionsKt.plusSeconds(now, 1)) .addPrimaryUserId(bob, SecretKeyRingProtector.unprotectedKeys()) .done(); - assertEquals("Bob", PGPainless.inspectKeyRing(secretKeys, DateExtensionsKt.plusSeconds(now, 2)).getPrimaryUserId()); + assertEquals("Bob", api.inspect(secretKeys, DateExtensionsKt.plusSeconds(now, 2)).getPrimaryUserId()); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeExpirationOnKeyWithDifferentSignatureTypesTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeExpirationOnKeyWithDifferentSignatureTypesTest.java index 2eac921b..48bda2a2 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeExpirationOnKeyWithDifferentSignatureTypesTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeExpirationOnKeyWithDifferentSignatureTypesTest.java @@ -7,7 +7,7 @@ package org.pgpainless.key.modification; import java.io.IOException; import java.util.Date; -import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.JUtils; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; @@ -138,7 +138,8 @@ public class ChangeExpirationOnKeyWithDifferentSignatureTypesTest { @ExtendWith(TestAllImplementations.class) public void setExpirationDate_keyHasSigClass10() throws IOException { - PGPSecretKeyRing keys = PGPainless.readKeyRing().secretKeyRing(keyWithGenericCertification); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey keys = api.readKey().parseKey(keyWithGenericCertification); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); executeTestForKeys(keys, protector); } @@ -147,20 +148,23 @@ public class ChangeExpirationOnKeyWithDifferentSignatureTypesTest { @ExtendWith(TestAllImplementations.class) public void setExpirationDate_keyHasSigClass12() throws IOException { - PGPSecretKeyRing keys = PGPainless.readKeyRing().secretKeyRing(keyWithCasualCertification); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey keys = api.readKey().parseKey(keyWithCasualCertification); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); executeTestForKeys(keys, protector); } - private void executeTestForKeys(PGPSecretKeyRing keys, SecretKeyRingProtector protector) { + private void executeTestForKeys(OpenPGPKey keys, SecretKeyRingProtector protector) { + PGPainless api = PGPainless.getInstance(); + Date expirationDate = new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 14); // round date for test stability expirationDate = DateUtil.toSecondsPrecision(expirationDate); - PGPSecretKeyRing modded = PGPainless.modifyKeyRing(keys) + OpenPGPKey modded = api.modify(keys) .setExpirationDate(expirationDate, protector) .done(); - JUtils.assertDateEquals(expirationDate, PGPainless.inspectKeyRing(modded).getPrimaryKeyExpirationDate()); + JUtils.assertDateEquals(expirationDate, api.inspect(modded).getPrimaryKeyExpirationDate()); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeExpirationTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeExpirationTest.java index 7ddb2a27..ccef1d19 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeExpirationTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeExpirationTest.java @@ -14,7 +14,7 @@ import java.util.Calendar; import java.util.Date; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.JUtils; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; @@ -35,27 +35,28 @@ public class ChangeExpirationTest { @ExtendWith(TestAllImplementations.class) public void setExpirationDateAndThenUnsetIt_OnPrimaryKey() throws PGPException, IOException { - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); - KeyRingInfo sInfo = PGPainless.inspectKeyRing(secretKeys); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); + KeyRingInfo sInfo = api.inspect(secretKeys); assertNull(sInfo.getPrimaryKeyExpirationDate()); assertNull(sInfo.getSubkeyExpirationDate(subKeyFingerprint)); Date now = new Date(); Date date = DateUtil.parseUTCDate("2020-11-27 16:10:32 UTC"); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .setExpirationDate(date, new UnprotectedKeysProtector()).done(); - sInfo = PGPainless.inspectKeyRing(secretKeys); + sInfo = api.inspect(secretKeys); assertNotNull(sInfo.getPrimaryKeyExpirationDate()); assertEquals(date.getTime(), sInfo.getPrimaryKeyExpirationDate().getTime()); // subkey unchanged assertNull(sInfo.getSubkeyExpirationDate(subKeyFingerprint)); Date t1 = new Date(now.getTime() + 1000 * 60 * 60); - secretKeys = PGPainless.modifyKeyRing(secretKeys, t1) + secretKeys = api.modify(secretKeys, t1) .setExpirationDate(null, new UnprotectedKeysProtector()).done(); - sInfo = PGPainless.inspectKeyRing(secretKeys, t1); + sInfo = api.inspect(secretKeys, t1); assertNull(sInfo.getPrimaryKeyExpirationDate()); assertNull(sInfo.getSubkeyExpirationDate(subKeyFingerprint)); } @@ -64,9 +65,9 @@ public class ChangeExpirationTest { @ExtendWith(TestAllImplementations.class) public void setExpirationDateAndThenUnsetIt_OnSubkey() throws PGPException, IOException { - - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); - KeyRingInfo sInfo = PGPainless.inspectKeyRing(secretKeys); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); + KeyRingInfo sInfo = api.inspect(secretKeys); assertNull(sInfo.getPrimaryKeyExpirationDate()); @@ -76,42 +77,43 @@ public class ChangeExpirationTest { calendar.add(Calendar.DATE, 5); Date expiration = calendar.getTime(); // in 5 days - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .setExpirationDate(expiration, new UnprotectedKeysProtector()).done(); - sInfo = PGPainless.inspectKeyRing(secretKeys); + sInfo = api.inspect(secretKeys); assertNotNull(sInfo.getPrimaryKeyExpirationDate()); JUtils.assertDateEquals(expiration, sInfo.getPrimaryKeyExpirationDate()); Date t1 = new Date(now.getTime() + 1000 * 60 * 60); - secretKeys = PGPainless.modifyKeyRing(secretKeys, t1) + secretKeys = api.modify(secretKeys, t1) .setExpirationDate(null, new UnprotectedKeysProtector()).done(); - sInfo = PGPainless.inspectKeyRing(secretKeys, t1); + sInfo = api.inspect(secretKeys, t1); assertNull(sInfo.getPrimaryKeyExpirationDate()); } @TestTemplate @ExtendWith(TestAllImplementations.class) public void testExtremeExpirationDates() throws PGPException, IOException { - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); // seconds from 2021 to 2199 will overflow 32bit integers Date farAwayExpiration = DateUtil.parseUTCDate("2199-01-01 00:00:00 UTC"); - final PGPSecretKeyRing finalKeys = secretKeys; + final OpenPGPKey finalKeys = secretKeys; assertThrows(IllegalArgumentException.class, () -> - PGPainless.modifyKeyRing(finalKeys) + api.modify(finalKeys) .setExpirationDate(farAwayExpiration, protector) .done()); Date notSoFarAwayExpiration = DateUtil.parseUTCDate("2100-01-01 00:00:00 UTC"); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .setExpirationDate(notSoFarAwayExpiration, protector) .done(); - Date actualExpiration = PGPainless.inspectKeyRing(secretKeys) + Date actualExpiration = api.inspect(secretKeys) .getPrimaryKeyExpirationDate(); JUtils.assertDateEquals(notSoFarAwayExpiration, actualExpiration); } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangePrimaryUserIdAndExpirationDatesTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangePrimaryUserIdAndExpirationDatesTest.java index c7751434..a496594c 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangePrimaryUserIdAndExpirationDatesTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangePrimaryUserIdAndExpirationDatesTest.java @@ -5,8 +5,8 @@ package org.pgpainless.key.modification; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; import org.pgpainless.key.info.KeyRingInfo; @@ -26,13 +26,14 @@ public class ChangePrimaryUserIdAndExpirationDatesTest { @Test public void generateA_primaryB_revokeA_cantSecondaryA() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("A") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("A"); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); Date now = new Date(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys, now); + KeyRingInfo info = api.inspect(secretKeys, now); assertFalse(info.isHardRevoked("A")); assertFalse(info.isHardRevoked("B")); assertIsPrimaryUserId("A", info); @@ -41,10 +42,10 @@ public class ChangePrimaryUserIdAndExpirationDatesTest { // One hour later Date oneHourLater = new Date(now.getTime() + millisInHour); - secretKeys = PGPainless.modifyKeyRing(secretKeys, oneHourLater) + secretKeys = api.modify(secretKeys, oneHourLater) .addPrimaryUserId("B", protector) .done(); - info = PGPainless.inspectKeyRing(secretKeys, oneHourLater); + info = api.inspect(secretKeys, oneHourLater); assertIsPrimaryUserId("B", info); assertIsNotPrimaryUserId("A", info); @@ -52,10 +53,10 @@ public class ChangePrimaryUserIdAndExpirationDatesTest { // Two hours later Date twoHoursLater = new Date(now.getTime() + 2 * millisInHour); - secretKeys = PGPainless.modifyKeyRing(secretKeys, twoHoursLater) + secretKeys = api.modify(secretKeys, twoHoursLater) .revokeUserId("A", protector) // hard revoke A .done(); - info = PGPainless.inspectKeyRing(secretKeys, twoHoursLater); + info = api.inspect(secretKeys, twoHoursLater); assertTrue(info.isHardRevoked("A")); assertFalse(info.isHardRevoked("B")); @@ -65,71 +66,71 @@ public class ChangePrimaryUserIdAndExpirationDatesTest { // Three hours later Date threeHoursLater = new Date(now.getTime() + 3 * millisInHour); - PGPSecretKeyRing finalSecretKeys = secretKeys; + OpenPGPKey finalSecretKeys = secretKeys; assertThrows(IllegalArgumentException.class, () -> - PGPainless.modifyKeyRing(finalSecretKeys, threeHoursLater).addUserId("A", protector)); + api.modify(finalSecretKeys, threeHoursLater).addUserId("A", protector)); } @Test public void generateA_primaryExpire_isExpired() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("A") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("A"); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); assertIsPrimaryUserId("A", info); Date now = new Date(); Date later = new Date(now.getTime() + millisInHour); - secretKeys = PGPainless.modifyKeyRing(secretKeys, now) + secretKeys = api.modify(secretKeys, now) .setExpirationDate(later, protector) // expire the whole key .done(); Date evenLater = new Date(now.getTime() + 2 * millisInHour); - info = PGPainless.inspectKeyRing(secretKeys, evenLater); + info = api.inspect(secretKeys, evenLater); assertFalse(info.isUserIdValid("A")); // is expired by now } @Test public void generateA_primaryB_primaryExpire_bIsStillPrimary() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("A") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("A"); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); Date now = new Date(); // Generate key with primary user-id A - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); assertIsPrimaryUserId("A", info); // later set primary user-id to B Date t1 = new Date(now.getTime() + millisInHour); - secretKeys = PGPainless.modifyKeyRing(secretKeys, t1) + secretKeys = api.modify(secretKeys, t1) .addPrimaryUserId("B", protector) .done(); - info = PGPainless.inspectKeyRing(secretKeys, t1); + info = api.inspect(secretKeys, t1); assertIsPrimaryUserId("B", info); assertIsNotPrimaryUserId("A", info); // Even later expire the whole key Date t2 = new Date(now.getTime() + 2 * millisInHour); Date expiration = new Date(now.getTime() + 10 * millisInHour); - secretKeys = PGPainless.modifyKeyRing(secretKeys, t2) + secretKeys = api.modify(secretKeys, t2) .setExpirationDate(expiration, protector) // expire the whole key in 1 hour .done(); Date t3 = new Date(now.getTime() + 3 * millisInHour); - info = PGPainless.inspectKeyRing(secretKeys, t3); + info = api.inspect(secretKeys, t3); assertIsValid("A", info); assertIsValid("B", info); assertIsPrimaryUserId("B", info); assertIsNotPrimaryUserId("A", info); - info = PGPainless.inspectKeyRing(secretKeys, expiration); + info = api.inspect(secretKeys, expiration); assertIsPrimaryUserId("B", info); // B is still primary, even though assertFalse(info.isUserIdValid("A")); // key is expired by now assertFalse(info.isUserIdValid("B")); @@ -137,23 +138,23 @@ public class ChangePrimaryUserIdAndExpirationDatesTest { @Test public void generateA_expire_certify() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("A") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().modernKeyRing("A"); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); Date now = new Date(); Date t1 = new Date(now.getTime() + millisInHour); - secretKeys = PGPainless.modifyKeyRing(secretKeys, now) + secretKeys = api.modify(secretKeys, now) .setExpirationDate(t1, protector) .done(); Date t2 = new Date(now.getTime() + 2 * millisInHour); Date t4 = new Date(now.getTime() + 4 * millisInHour); - secretKeys = PGPainless.modifyKeyRing(secretKeys, t2) + secretKeys = api.modify(secretKeys, t2) .setExpirationDate(t4, protector) .done(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); assertIsValid("A", info); assertIsPrimaryUserId("A", info); } @@ -161,28 +162,28 @@ public class ChangePrimaryUserIdAndExpirationDatesTest { @Test public void generateA_expire_primaryB_expire_isPrimaryB() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("A") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().modernKeyRing("A"); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); Date now = new Date(); Date t1 = new Date(now.getTime() + millisInHour); - secretKeys = PGPainless.modifyKeyRing(secretKeys, t1) + secretKeys = api.modify(secretKeys, t1) .setExpirationDate(t1, protector) .done(); Date t2 = new Date(now.getTime() + 2 * millisInHour); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys, t2); + KeyRingInfo info = api.inspect(secretKeys, t2); assertIsPrimaryUserId("A", info); assertIsNotValid("A", info); // A is expired - secretKeys = PGPainless.modifyKeyRing(secretKeys, t2) + secretKeys = api.modify(secretKeys, t2) .addPrimaryUserId("B", protector) .done(); Date t3 = new Date(now.getTime() + 3 * millisInHour); - info = PGPainless.inspectKeyRing(secretKeys, t3); + info = api.inspect(secretKeys, t3); assertIsPrimaryUserId("B", info); assertIsNotValid("B", info); // A and B are still expired @@ -190,19 +191,19 @@ public class ChangePrimaryUserIdAndExpirationDatesTest { Date t4 = new Date(now.getTime() + 4 * millisInHour); Date t5 = new Date(now.getTime() + 5 * millisInHour); - secretKeys = PGPainless.modifyKeyRing(secretKeys, t3) + secretKeys = api.modify(secretKeys, t3) .setExpirationDate(t5, protector) .done(); - info = PGPainless.inspectKeyRing(secretKeys, t4); + info = api.inspect(secretKeys, t4); assertIsValid("B", info); assertIsValid("A", info); // A got re-validated when changing exp date assertIsPrimaryUserId("B", info); - secretKeys = PGPainless.modifyKeyRing(secretKeys, t4) + secretKeys = api.modify(secretKeys, t4) .addUserId("A", protector) // re-certify A as non-primary user-id .done(); - info = PGPainless.inspectKeyRing(secretKeys, t4); + info = api.inspect(secretKeys, t4); assertIsValid("B", info); assertIsValid("A", info); diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSecretKeyRingPassphraseTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSecretKeyRingPassphraseTest.java index 96f57303..8a2723db 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSecretKeyRingPassphraseTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSecretKeyRingPassphraseTest.java @@ -15,8 +15,8 @@ import java.util.Iterator; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPSecretKey; -import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.api.OpenPGPImplementation; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; import org.bouncycastle.util.io.Streams; import org.junit.jupiter.api.TestTemplate; @@ -35,8 +35,8 @@ import org.pgpainless.util.Passphrase; public class ChangeSecretKeyRingPassphraseTest { - private final PGPSecretKeyRing keyRing = PGPainless.generateKeyRing().simpleEcKeyRing("password@encryp.ted", "weakPassphrase") - .getPGPSecretKeyRing(); + private final OpenPGPKey keyRing = PGPainless.getInstance() + .generateKey().simpleEcKeyRing("password@encryp.ted", "weakPassphrase"); public ChangeSecretKeyRingPassphraseTest() { } @@ -44,66 +44,64 @@ public class ChangeSecretKeyRingPassphraseTest { @TestTemplate @ExtendWith(TestAllImplementations.class) public void changePassphraseOfWholeKeyRingTest() throws PGPException { - - PGPSecretKeyRing secretKeys = PGPainless.modifyKeyRing(keyRing) + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.modify(keyRing) .changePassphraseFromOldPassphrase(Passphrase.fromPassword("weakPassphrase")) .withSecureDefaultSettings() .toNewPassphrase(Passphrase.fromPassword("1337p455phr453")) .done(); - PGPSecretKeyRing changedPassphraseKeyRing = secretKeys; - assertEquals(KeyRingProtectionSettings.secureDefaultSettings().getEncryptionAlgorithm().getAlgorithmId(), - changedPassphraseKeyRing.getSecretKey().getKeyEncryptionAlgorithm()); + secretKeys.getPGPSecretKeyRing().getSecretKey().getKeyEncryptionAlgorithm()); assertThrows(PGPException.class, () -> - signDummyMessageWithKeysAndPassphrase(changedPassphraseKeyRing, Passphrase.emptyPassphrase()), + signDummyMessageWithKeysAndPassphrase(api, secretKeys, Passphrase.emptyPassphrase()), "Unlocking secret key ring with empty passphrase MUST fail."); assertThrows(PGPException.class, () -> - signDummyMessageWithKeysAndPassphrase(changedPassphraseKeyRing, Passphrase.fromPassword("weakPassphrase")), + signDummyMessageWithKeysAndPassphrase(api, secretKeys, Passphrase.fromPassword("weakPassphrase")), "Unlocking secret key ring with old passphrase MUST fail."); - assertDoesNotThrow(() -> signDummyMessageWithKeysAndPassphrase(changedPassphraseKeyRing, Passphrase.fromPassword("1337p455phr453")), + assertDoesNotThrow(() -> signDummyMessageWithKeysAndPassphrase(api, secretKeys, Passphrase.fromPassword("1337p455phr453")), "Unlocking the secret key ring with the new passphrase MUST succeed."); } @TestTemplate @ExtendWith(TestAllImplementations.class) public void changePassphraseOfWholeKeyRingToEmptyPassphrase() throws PGPException, IOException { - PGPSecretKeyRing secretKeys = PGPainless.modifyKeyRing(keyRing) + PGPainless api = PGPainless.getInstance(); + + OpenPGPKey changedPassphraseKeyRing = api.modify(keyRing) .changePassphraseFromOldPassphrase(Passphrase.fromPassword("weakPassphrase")) .withSecureDefaultSettings() .toNoPassphrase() .done(); - PGPSecretKeyRing changedPassphraseKeyRing = secretKeys; - assertEquals(SymmetricKeyAlgorithm.NULL.getAlgorithmId(), - changedPassphraseKeyRing.getSecretKey().getKeyEncryptionAlgorithm()); + changedPassphraseKeyRing.getPGPSecretKeyRing().getSecretKey().getKeyEncryptionAlgorithm()); - signDummyMessageWithKeysAndPassphrase(changedPassphraseKeyRing, Passphrase.emptyPassphrase()); + signDummyMessageWithKeysAndPassphrase(api, changedPassphraseKeyRing, Passphrase.emptyPassphrase()); } @TestTemplate @ExtendWith(TestAllImplementations.class) public void changePassphraseOfSingleSubkeyToNewPassphrase() throws PGPException { - - Iterator keys = keyRing.getSecretKeys(); + PGPainless api = PGPainless.getInstance(); + Iterator keys = keyRing.getPGPSecretKeyRing().getSecretKeys(); PGPSecretKey primaryKey = keys.next(); PGPSecretKey subKey = keys.next(); extractPrivateKey(primaryKey, Passphrase.fromPassword("weakPassphrase")); extractPrivateKey(subKey, Passphrase.fromPassword("weakPassphrase")); - PGPSecretKeyRing secretKeys = PGPainless.modifyKeyRing(keyRing) + OpenPGPKey secretKeys = api.modify(keyRing) .changeSubKeyPassphraseFromOldPassphrase(subKey.getPublicKey().getKeyIdentifier(), Passphrase.fromPassword("weakPassphrase")) .withSecureDefaultSettings() .toNewPassphrase(Passphrase.fromPassword("subKeyPassphrase")) .done(); - keys = secretKeys.getSecretKeys(); + keys = secretKeys.getPGPSecretKeyRing().getSecretKeys(); primaryKey = keys.next(); subKey = keys.next(); @@ -124,18 +122,18 @@ public class ChangeSecretKeyRingPassphraseTest { @TestTemplate @ExtendWith(TestAllImplementations.class) public void changePassphraseOfSingleSubkeyToEmptyPassphrase() throws PGPException { - - Iterator keys = keyRing.getSecretKeys(); + PGPainless api = PGPainless.getInstance(); + Iterator keys = keyRing.getPGPSecretKeyRing().getSecretKeys(); PGPSecretKey primaryKey = keys.next(); PGPSecretKey subKey = keys.next(); - PGPSecretKeyRing secretKeys = PGPainless.modifyKeyRing(keyRing) + OpenPGPKey secretKeys = api.modify(keyRing) .changeSubKeyPassphraseFromOldPassphrase(subKey.getKeyIdentifier(), Passphrase.fromPassword("weakPassphrase")) .withSecureDefaultSettings() .toNoPassphrase() .done(); - keys = secretKeys.getSecretKeys(); + keys = secretKeys.getPGPSecretKeyRing().getSecretKeys(); primaryKey = keys.next(); subKey = keys.next(); @@ -176,13 +174,13 @@ public class ChangeSecretKeyRingPassphraseTest { UnlockSecretKey.unlockSecretKey(secretKey, decryptor); } - private void signDummyMessageWithKeysAndPassphrase(PGPSecretKeyRing keyRing, Passphrase passphrase) throws IOException, PGPException { + private void signDummyMessageWithKeysAndPassphrase(PGPainless api, OpenPGPKey key, Passphrase passphrase) throws IOException, PGPException { String dummyMessage = "dummy"; ByteArrayOutputStream dummy = new ByteArrayOutputStream(); - EncryptionStream stream = PGPainless.encryptAndOrSign().onOutputStream(dummy) + EncryptionStream stream = api.generateMessage().onOutputStream(dummy) .withOptions(ProducerOptions.sign(SigningOptions.get() - .addInlineSignature(PasswordBasedSecretKeyRingProtector.forKey(keyRing, passphrase), - keyRing, DocumentSignatureType.BINARY_DOCUMENT))); + .addInlineSignature(PasswordBasedSecretKeyRingProtector.forKey(key, passphrase), + key, DocumentSignatureType.BINARY_DOCUMENT))); Streams.pipeAll(new ByteArrayInputStream(dummyMessage.getBytes()), stream); stream.close(); diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSubkeyExpirationTimeTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSubkeyExpirationTimeTest.java index d62f8ad8..9f1448d3 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSubkeyExpirationTimeTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSubkeyExpirationTimeTest.java @@ -4,8 +4,8 @@ package org.pgpainless.key.modification; -import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.api.OpenPGPCertificate; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.JUtils; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; @@ -25,26 +25,27 @@ public class ChangeSubkeyExpirationTimeTest { @Test public void changeExpirationTimeOfSubkey() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice") - .getPGPSecretKeyRing(); - Date now = secretKeys.getPublicKey().getCreationTime(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice"); + Date now = secretKeys.getPrimaryKey().getCreationTime(); Date inAnHour = new Date(now.getTime() + 1000 * 60 * 60); - OpenPGPCertificate.OpenPGPComponentKey encryptionKey = PGPainless.inspectKeyRing(secretKeys) + OpenPGPCertificate.OpenPGPComponentKey encryptionKey = api.inspect(secretKeys) .getEncryptionSubkeys(EncryptionPurpose.ANY).get(0); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .setExpirationDateOfSubkey( inAnHour, - encryptionKey.getKeyIdentifier().getKeyId(), + encryptionKey.getKeyIdentifier(), SecretKeyRingProtector.unprotectedKeys()) .done(); - JUtils.assertDateEquals(inAnHour, PGPainless.inspectKeyRing(secretKeys) + JUtils.assertDateEquals(inAnHour, api.inspect(secretKeys) .getSubkeyExpirationDate(OpenPgpFingerprint.of(encryptionKey.getPGPPublicKey()))); } @Test public void changeExpirationTimeOfExpiredSubkey() throws IOException { - PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing( + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.readKey().parseKey( "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" + "Version: PGPainless\n" + "Comment: CA52 4D5D E3D8 9CD9 105B BA45 3761 076B C6B5 3000\n" + @@ -79,13 +80,13 @@ public class ChangeSubkeyExpirationTimeTest { OpenPgpFingerprint encryptionSubkey = new OpenPgpV4Fingerprint("2E541354A23C9943375EC27A3EF133ED8720D636"); JUtils.assertDateEquals( DateUtil.parseUTCDate("2023-12-07 16:29:46 UTC"), - PGPainless.inspectKeyRing(secretKeys).getSubkeyExpirationDate(encryptionSubkey)); + api.inspect(secretKeys).getSubkeyExpirationDate(encryptionSubkey)); // re-validate the subkey by setting its expiry to null (no expiry) - secretKeys = PGPainless.modifyKeyRing(secretKeys) - .setExpirationDateOfSubkey(null, encryptionSubkey.getKeyId(), SecretKeyRingProtector.unprotectedKeys()) + secretKeys = api.modify(secretKeys) + .setExpirationDateOfSubkey(null, encryptionSubkey.getKeyIdentifier(), SecretKeyRingProtector.unprotectedKeys()) .done(); - assertNull(PGPainless.inspectKeyRing(secretKeys).getSubkeyExpirationDate(encryptionSubkey)); + assertNull(api.inspect(secretKeys).getSubkeyExpirationDate(encryptionSubkey)); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/FixUserIdDoesNotBreakEncryptionCapabilityTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/FixUserIdDoesNotBreakEncryptionCapabilityTest.java index ce851da3..ccf07e56 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/FixUserIdDoesNotBreakEncryptionCapabilityTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/FixUserIdDoesNotBreakEncryptionCapabilityTest.java @@ -17,9 +17,9 @@ import java.nio.charset.StandardCharsets; import java.util.NoSuchElementException; 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.util.io.Streams; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; @@ -73,9 +73,10 @@ public class FixUserIdDoesNotBreakEncryptionCapabilityTest { @Test public void manualReplaceUserIdWithFixedVersionDoesNotHinderEncryptionCapability() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(SECRET_KEY); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.readKey().parseKey(SECRET_KEY); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); - PGPSecretKeyRing modified = PGPainless.modifyKeyRing(secretKeys) + OpenPGPKey modified = api.modify(secretKeys) .addUserId(userIdAfter, new SelfSignatureSubpackets.Callback() { @Override public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) { @@ -85,8 +86,8 @@ public class FixUserIdDoesNotBreakEncryptionCapabilityTest { .removeUserId(userIdBefore, protector) .done(); - KeyRingInfo before = PGPainless.inspectKeyRing(secretKeys); - KeyRingInfo after = PGPainless.inspectKeyRing(modified); + KeyRingInfo before = api.inspect(secretKeys); + KeyRingInfo after = api.inspect(modified); assertEquals(userIdBefore, before.getPrimaryUserId()); assertEquals(userIdAfter, after.getPrimaryUserId()); @@ -104,34 +105,38 @@ public class FixUserIdDoesNotBreakEncryptionCapabilityTest { @Test public void testReplaceUserId_missingOldUserIdThrows() throws IOException { - PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(SECRET_KEY); - assertThrows(NoSuchElementException.class, () -> PGPainless.modifyKeyRing(secretKeys) + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.readKey().parseKey(SECRET_KEY); + assertThrows(NoSuchElementException.class, () -> api.modify(secretKeys) .replaceUserId("missing", userIdAfter, SecretKeyRingProtector.unprotectedKeys())); } @Test public void testReplaceUserId_emptyOldUserIdThrows() throws IOException { - PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(SECRET_KEY); - assertThrows(IllegalArgumentException.class, () -> PGPainless.modifyKeyRing(secretKeys) + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.readKey().parseKey(SECRET_KEY); + assertThrows(IllegalArgumentException.class, () -> api.modify(secretKeys) .replaceUserId(" ", userIdAfter, SecretKeyRingProtector.unprotectedKeys())); } @Test public void testReplaceUserId_emptyNewUserIdThrows() throws IOException { - PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(SECRET_KEY); - assertThrows(IllegalArgumentException.class, () -> PGPainless.modifyKeyRing(secretKeys) + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.readKey().parseKey(SECRET_KEY); + assertThrows(IllegalArgumentException.class, () -> api.modify(secretKeys) .replaceUserId(userIdBefore, " ", SecretKeyRingProtector.unprotectedKeys())); } @Test public void testReplaceImplicitUserIdDoesNotBreakStuff() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(SECRET_KEY); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.readKey().parseKey(SECRET_KEY); - PGPSecretKeyRing edited = PGPainless.modifyKeyRing(secretKeys) + OpenPGPKey edited = api.modify(secretKeys) .replaceUserId(userIdBefore, userIdAfter, SecretKeyRingProtector.unprotectedKeys()) .done(); - KeyRingInfo info = PGPainless.inspectKeyRing(edited); + KeyRingInfo info = api.inspect(edited); assertTrue(info.isUserIdValid(userIdAfter)); assertEquals(userIdAfter, info.getPrimaryUserId()); @@ -139,10 +144,10 @@ public class FixUserIdDoesNotBreakEncryptionCapabilityTest { assertNotNull(latestCertification); assertTrue(latestCertification.getHashedSubPackets().isPrimaryUserID()); - PGPPublicKeyRing cert = PGPainless.extractCertificate(edited); + OpenPGPCertificate cert = edited.toCertificate(); ByteArrayOutputStream out = new ByteArrayOutputStream(); - EncryptionStream encryptionStream = PGPainless.encryptAndOrSign() + EncryptionStream encryptionStream = api.generateMessage() .onOutputStream(out) .withOptions(ProducerOptions.encrypt(EncryptionOptions.get() .addRecipient(cert))); @@ -151,7 +156,7 @@ public class FixUserIdDoesNotBreakEncryptionCapabilityTest { encryptionStream.close(); EncryptionResult result = encryptionStream.getResult(); - assertTrue(result.isEncryptedFor(cert)); + assertTrue(result.isEncryptedFor(cert.getPGPPublicKeyRing())); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); ByteArrayOutputStream plain = new ByteArrayOutputStream(); diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/GnuDummyS2KChangePassphraseTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/GnuDummyS2KChangePassphraseTest.java index 64439775..d9198e31 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/GnuDummyS2KChangePassphraseTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/GnuDummyS2KChangePassphraseTest.java @@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; import org.pgpainless.util.Passphrase; @@ -166,17 +166,18 @@ public class GnuDummyS2KChangePassphraseTest { @Test public void testChangePassphraseToNoPassphraseIgnoresGnuDummyS2KKeys() throws PGPException, IOException { - PGPSecretKeyRing secretKey = PGPainless.readKeyRing().secretKeyRing(KEY_WITH_GNU_DUMMY_S2K_PRIMARY_KEY); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKey = api.readKey().parseKey(KEY_WITH_GNU_DUMMY_S2K_PRIMARY_KEY); - assertFalse(PGPainless.inspectKeyRing(secretKey).isFullyDecrypted()); + assertFalse(api.inspect(secretKey).isFullyDecrypted()); - secretKey = PGPainless.modifyKeyRing(secretKey) + secretKey = api.modify(secretKey) .changePassphraseFromOldPassphrase(passphrase) .withSecureDefaultSettings() .toNoPassphrase() .done(); - assertTrue(PGPainless.inspectKeyRing(secretKey).isFullyDecrypted()); + assertTrue(api.inspect(secretKey).isFullyDecrypted()); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/OldSignatureSubpacketsArePreservedOnNewSigTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/OldSignatureSubpacketsArePreservedOnNewSigTest.java index afea503c..c99739b5 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/OldSignatureSubpacketsArePreservedOnNewSigTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/OldSignatureSubpacketsArePreservedOnNewSigTest.java @@ -10,9 +10,9 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import java.util.Date; -import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPSignatureSubpacketVector; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; import org.pgpainless.PGPainless; @@ -26,11 +26,11 @@ public class OldSignatureSubpacketsArePreservedOnNewSigTest { @TestTemplate @ExtendWith(TestAllImplementations.class) public void verifyOldSignatureSubpacketsArePreservedOnNewExpirationDateSig() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .simpleEcKeyRing("Alice ") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .simpleEcKeyRing("Alice "); - PGPSignature oldSignature = PGPainless.inspectKeyRing(secretKeys).getLatestUserIdCertification("Alice "); + PGPSignature oldSignature = api.inspect(secretKeys).getLatestUserIdCertification("Alice "); assertNotNull(oldSignature); PGPSignatureSubpacketVector oldPackets = oldSignature.getHashedSubPackets(); @@ -40,10 +40,10 @@ public class OldSignatureSubpacketsArePreservedOnNewSigTest { Date t1 = new Date(now.getTime() + millisInHour); Date expiration = new Date(now.getTime() + 5 * 24 * millisInHour); // in 5 days - secretKeys = PGPainless.modifyKeyRing(secretKeys, t1) + secretKeys = api.modify(secretKeys, t1) .setExpirationDate(expiration, new UnprotectedKeysProtector()) .done(); - PGPSignature newSignature = PGPainless.inspectKeyRing(secretKeys, t1).getLatestUserIdCertification("Alice "); + PGPSignature newSignature = api.inspect(secretKeys, t1).getLatestUserIdCertification("Alice "); assertNotNull(newSignature); PGPSignatureSubpacketVector newPackets = newSignature.getHashedSubPackets(); diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RefuseToAddWeakSubkeyTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RefuseToAddWeakSubkeyTest.java index 925b4426..c1019679 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RefuseToAddWeakSubkeyTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RefuseToAddWeakSubkeyTest.java @@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.EnumMap; import java.util.Map; -import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; import org.pgpainless.algorithm.EncryptionPurpose; @@ -28,31 +28,31 @@ public class RefuseToAddWeakSubkeyTest { @Test public void testEditorRefusesToAddWeakSubkey() { + PGPainless api = PGPainless.getInstance(); // ensure default policy is set - Policy oldPolicy = PGPainless.getPolicy(); + Policy oldPolicy = api.getAlgorithmPolicy(); Policy adjusted = oldPolicy.copy().withPublicKeyAlgorithmPolicy( Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy() ).build(); - PGPainless.getInstance().setAlgorithmPolicy(adjusted); + api.setAlgorithmPolicy(adjusted); - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("Alice") - .getPGPSecretKeyRing(); - SecretKeyRingEditorInterface editor = PGPainless.modifyKeyRing(secretKeys); + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("Alice"); + SecretKeyRingEditorInterface editor = api.modify(secretKeys); KeySpec spec = KeySpec.getBuilder(KeyType.RSA(RsaLength._1024), KeyFlag.ENCRYPT_COMMS).build(); assertThrows(IllegalArgumentException.class, () -> editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys())); - PGPainless.getInstance().setAlgorithmPolicy(oldPolicy); + api.setAlgorithmPolicy(oldPolicy); } @Test public void testEditorAllowsToAddWeakSubkeyIfCompliesToPublicKeyAlgorithmPolicy() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("Alice") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("Alice"); - Policy oldPolicy = PGPainless.getPolicy(); + Policy oldPolicy = api.getAlgorithmPolicy(); // set weak policy Map minimalBitStrengths = new EnumMap<>(PublicKeyAlgorithm.class); @@ -75,11 +75,11 @@ public class RefuseToAddWeakSubkeyTest { minimalBitStrengths.put(PublicKeyAlgorithm.DIFFIE_HELLMAN, 2000); // ยง7.2.2 minimalBitStrengths.put(PublicKeyAlgorithm.ECDH, 250); - PGPainless.getInstance().setAlgorithmPolicy(oldPolicy.copy() + api.setAlgorithmPolicy(oldPolicy.copy() .withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(minimalBitStrengths)) .build()); - SecretKeyRingEditorInterface editor = PGPainless.modifyKeyRing(secretKeys); + SecretKeyRingEditorInterface editor = api.modify(secretKeys); KeySpec spec = KeySpec.getBuilder(KeyType.RSA(RsaLength._1024), KeyFlag.ENCRYPT_COMMS) .setKeyCreationDate(editor.getReferenceTime()) // The key gets created after we instantiate the editor. .build(); @@ -87,9 +87,9 @@ public class RefuseToAddWeakSubkeyTest { secretKeys = editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys()) .done(); - assertEquals(2, PGPainless.inspectKeyRing(secretKeys).getEncryptionSubkeys(EncryptionPurpose.ANY).size()); + assertEquals(2, api.inspect(secretKeys).getEncryptionSubkeys(EncryptionPurpose.ANY).size()); // reset default policy - PGPainless.getInstance().setAlgorithmPolicy(oldPolicy); + api.setAlgorithmPolicy(oldPolicy); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevocationCertificateTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevocationCertificateTest.java index 6dbd7318..2ac4c87f 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevocationCertificateTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevocationCertificateTest.java @@ -15,9 +15,10 @@ import java.io.IOException; 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.junit.jupiter.api.Test; import org.pgpainless.PGPainless; import org.pgpainless.key.TestKeys; @@ -30,9 +31,10 @@ public class RevocationCertificateTest { @Test public void createRevocationCertificateTest() throws PGPException, IOException { - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); - PGPSignature revocation = PGPainless.modifyKeyRing(secretKeys) + OpenPGPSignature revocation = api.modify(secretKeys) .createRevocation(SecretKeyRingProtector.unprotectedKeys(), RevocationAttributes.createKeyRevocation() .withReason(RevocationAttributes.Reason.KEY_RETIRED) @@ -40,66 +42,68 @@ public class RevocationCertificateTest { assertNotNull(revocation); - assertTrue(PGPainless.inspectKeyRing(secretKeys).isKeyValidlyBound(secretKeys.getPublicKey().getKeyID())); + assertTrue(api.inspect(secretKeys).isKeyValidlyBound(secretKeys.getKeyIdentifier())); // merge key and revocation certificate PGPSecretKeyRing revokedKey = KeyRingUtils.keysPlusSecretKey( - secretKeys, - KeyRingUtils.secretKeyPlusSignature(secretKeys.getSecretKey(), revocation)); + secretKeys.getPGPSecretKeyRing(), + KeyRingUtils.secretKeyPlusSignature(secretKeys.getPrimarySecretKey().getPGPSecretKey(), revocation.getSignature())); - assertFalse(PGPainless.inspectKeyRing(revokedKey).isKeyValidlyBound(secretKeys.getPublicKey().getKeyID())); + assertFalse(api.inspect(api.toKey(revokedKey)).isKeyValidlyBound(secretKeys.getKeyIdentifier())); } @Test public void createMinimalRevocationCertificateTest() throws PGPException, IOException { - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); - PGPPublicKeyRing minimalRevocationCert = PGPainless.modifyKeyRing(secretKeys).createMinimalRevocationCertificate( + OpenPGPCertificate minimalRevocationCert = api.modify(secretKeys).createMinimalRevocationCertificate( SecretKeyRingProtector.unprotectedKeys(), RevocationAttributes.createKeyRevocation().withReason(RevocationAttributes.Reason.KEY_RETIRED).withoutDescription()); - assertEquals(1, minimalRevocationCert.size()); - PGPPublicKey key = minimalRevocationCert.getPublicKey(); - assertEquals(secretKeys.getPublicKey().getKeyID(), key.getKeyID()); + assertEquals(1, minimalRevocationCert.getPGPKeyRing().size()); + PGPPublicKey key = minimalRevocationCert.getPrimaryKey().getPGPPublicKey(); + assertEquals(secretKeys.getKeyIdentifier(), key.getKeyIdentifier()); assertEquals(1, CollectionUtils.iteratorToList(key.getSignatures()).size()); assertFalse(key.getUserIDs().hasNext()); assertFalse(key.getUserAttributes().hasNext()); assertNull(key.getTrustData()); - PGPPublicKeyRing originalCert = PGPainless.extractCertificate(secretKeys); - PGPPublicKeyRing mergedCert = PGPainless.mergeCertificate(originalCert, minimalRevocationCert); + OpenPGPCertificate originalCert = secretKeys.toCertificate(); + OpenPGPCertificate mergedCert = api.mergeCertificate(originalCert, minimalRevocationCert); - assertTrue(PGPainless.inspectKeyRing(mergedCert).getRevocationState().isSoftRevocation()); + assertTrue(api.inspect(mergedCert).getRevocationState().isSoftRevocation()); } @Test public void createMinimalRevocationCertificateForFreshKeyTest() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice ") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice "); - PGPPublicKeyRing minimalRevocationCert = PGPainless.modifyKeyRing(secretKeys).createMinimalRevocationCertificate( + OpenPGPCertificate minimalRevocationCert = api.modify(secretKeys).createMinimalRevocationCertificate( SecretKeyRingProtector.unprotectedKeys(), RevocationAttributes.createKeyRevocation().withReason(RevocationAttributes.Reason.KEY_RETIRED).withoutDescription()); - assertEquals(1, minimalRevocationCert.size()); - PGPPublicKey key = minimalRevocationCert.getPublicKey(); - assertEquals(secretKeys.getPublicKey().getKeyID(), key.getKeyID()); + assertEquals(1, minimalRevocationCert.getKeys().size()); + PGPPublicKey key = minimalRevocationCert.getPGPPublicKeyRing().getPublicKey(); + assertEquals(secretKeys.getKeyIdentifier(), key.getKeyIdentifier()); assertEquals(1, CollectionUtils.iteratorToList(key.getSignatures()).size()); assertFalse(key.getUserIDs().hasNext()); assertFalse(key.getUserAttributes().hasNext()); assertNull(key.getTrustData()); - PGPPublicKeyRing originalCert = PGPainless.extractCertificate(secretKeys); - PGPPublicKeyRing mergedCert = PGPainless.mergeCertificate(originalCert, minimalRevocationCert); + OpenPGPCertificate originalCert = secretKeys.toCertificate(); + OpenPGPCertificate mergedCert = api.mergeCertificate(originalCert, minimalRevocationCert); - assertTrue(PGPainless.inspectKeyRing(mergedCert).getRevocationState().isSoftRevocation()); + assertTrue(api.inspect(mergedCert).getRevocationState().isSoftRevocation()); } @Test public void createMinimalRevocationCertificate_wrongReason() throws PGPException, IOException { - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); assertThrows(IllegalArgumentException.class, - () -> PGPainless.modifyKeyRing(secretKeys).createMinimalRevocationCertificate( + () -> api.modify(secretKeys).createMinimalRevocationCertificate( SecretKeyRingProtector.unprotectedKeys(), RevocationAttributes.createCertificateRevocation() .withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID) diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeKeyWithGenericCertificationSignatureTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeKeyWithGenericCertificationSignatureTest.java index b2cd85fc..2d02dba2 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeKeyWithGenericCertificationSignatureTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeKeyWithGenericCertificationSignatureTest.java @@ -7,13 +7,14 @@ package org.pgpainless.key.modification; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.util.Arrays; +import java.util.Collections; import org.bouncycastle.bcpg.ArmoredOutputStream; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; import org.pgpainless.PGPainless; @@ -24,7 +25,7 @@ import org.pgpainless.util.TestAllImplementations; /** * Test that makes sure that PGPainless can deal with keys that carry a key * signature of type 0x10 (generic certification). - * + *

* Originally PGPainless would only handle keys with key signature type * 0x13 (positive certification) and would otherwise crash when negotiating * algorithms, esp. when revoking a key. @@ -70,23 +71,26 @@ public class RevokeKeyWithGenericCertificationSignatureTest { } private KeyPair revokeKey(String priv) throws IOException, PGPException { - byte[] armoredBytes = priv.getBytes(StandardCharsets.UTF_8); - PGPSecretKeyRing r = PGPainless.readKeyRing() - .secretKeyRing(armoredBytes); - PGPSecretKey secretKey = r.getSecretKey(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey key = api.readKey().parseKey(priv); + OpenPGPKey onlyPrimaryKey = api.toKey( + new PGPSecretKeyRing( + Collections.singletonList(key.getPrimarySecretKey().getPGPSecretKey()) + ) + ); // this is not ideal, but still valid usage - PGPSecretKeyRing secretKeyRing = - PGPainless.modifyKeyRing(new PGPSecretKeyRing(Arrays.asList(secretKey))) + OpenPGPKey revokedPrimaryKey = + api.modify(onlyPrimaryKey) .revoke(new UnprotectedKeysProtector()).done(); - PGPPublicKey pkr = secretKeyRing.getPublicKeys().next(); + PGPPublicKey pkr = revokedPrimaryKey.getPGPSecretKeyRing().getPublicKeys().next(); ByteArrayOutputStream pubOutBytes = new ByteArrayOutputStream(); try (ArmoredOutputStream pubOut = ArmoredOutputStreamFactory.get(pubOutBytes)) { pkr.encode(pubOut); } pubOutBytes.close(); - PGPSecretKey skr = secretKeyRing.getSecretKeys().next(); + PGPSecretKey skr = revokedPrimaryKey.getPGPSecretKeyRing().getSecretKeys().next(); ByteArrayOutputStream secOutBytes = new ByteArrayOutputStream(); try (ArmoredOutputStream privOut = ArmoredOutputStreamFactory.get(secOutBytes)) { skr.encode(privOut); diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeKeyWithoutPreferredAlgorithmsOnPrimaryKey.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeKeyWithoutPreferredAlgorithmsOnPrimaryKey.java index c4a177ed..0460b319 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeKeyWithoutPreferredAlgorithmsOnPrimaryKey.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeKeyWithoutPreferredAlgorithmsOnPrimaryKey.java @@ -7,7 +7,7 @@ package org.pgpainless.key.modification; import java.io.IOException; import java.util.Date; -import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.JUtils; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; @@ -99,16 +99,17 @@ public class RevokeKeyWithoutPreferredAlgorithmsOnPrimaryKey { @ExtendWith(TestAllImplementations.class) public void testChangingExpirationTimeWithKeyWithoutPrefAlgos() throws IOException { + PGPainless api = PGPainless.getInstance(); Date expirationDate = DateUtil.now(); - PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(KEY); + OpenPGPKey secretKeys = api.readKey().parseKey(KEY); SecretKeyRingProtector protector = new UnprotectedKeysProtector(); - SecretKeyRingEditorInterface modify = PGPainless.modifyKeyRing(secretKeys) + SecretKeyRingEditorInterface modify = api.modify(secretKeys) .setExpirationDate(expirationDate, protector); secretKeys = modify.done(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); JUtils.assertDateEquals(expirationDate, info.getPrimaryKeyExpirationDate()); } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeSubKeyTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeSubKeyTest.java index 729c2151..0843e368 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeSubKeyTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeSubKeyTest.java @@ -19,8 +19,9 @@ import org.bouncycastle.bcpg.sig.IssuerFingerprint; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPSecretKey; -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.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; @@ -33,7 +34,6 @@ import org.pgpainless.key.modification.secretkeyring.SecretKeyRingEditorInterfac import org.pgpainless.key.protection.PasswordBasedSecretKeyRingProtector; import org.pgpainless.key.protection.SecretKeyRingProtector; import org.pgpainless.key.util.RevocationAttributes; -import org.pgpainless.signature.SignatureUtils; import org.pgpainless.signature.subpackets.RevocationSignatureSubpackets; import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil; import org.pgpainless.util.TestAllImplementations; @@ -43,10 +43,11 @@ public class RevokeSubKeyTest { @TestTemplate @ExtendWith(TestAllImplementations.class) - public void revokeSukeyTest() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing(); + public void revokeSubkeyTest() throws IOException, PGPException { + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getCryptieKey(); - Iterator keysIterator = secretKeys.iterator(); + Iterator keysIterator = secretKeys.getPGPSecretKeyRing().iterator(); PGPSecretKey primaryKey = keysIterator.next(); PGPSecretKey subKey = keysIterator.next(); @@ -55,10 +56,10 @@ public class RevokeSubKeyTest { SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector .forKey(secretKeys, Passphrase.fromPassword("password123")); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .revokeSubKey(new OpenPgpV4Fingerprint(subKey), protector) .done(); - keysIterator = secretKeys.iterator(); + keysIterator = secretKeys.getPGPSecretKeyRing().iterator(); primaryKey = keysIterator.next(); subKey = keysIterator.next(); @@ -68,19 +69,20 @@ public class RevokeSubKeyTest { @TestTemplate @ExtendWith(TestAllImplementations.class) public void detachedRevokeSubkeyTest() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getCryptieKey(); OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(secretKeys); SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector.forKey(secretKeys, Passphrase.fromPassword("password123")); - PGPSignature revocationCertificate = PGPainless.modifyKeyRing(secretKeys) + OpenPGPSignature revocationCertificate = api.modify(secretKeys) .createRevocation(fingerprint, protector, RevocationAttributes.createKeyRevocation() .withReason(RevocationAttributes.Reason.KEY_RETIRED) .withDescription("Key no longer used.")); - PGPPublicKey publicKey = secretKeys.getPublicKey(); + PGPPublicKey publicKey = secretKeys.getPGPSecretKeyRing().getPublicKey(); assertFalse(publicKey.hasRevocation()); - publicKey = PGPPublicKey.addCertification(publicKey, revocationCertificate); + publicKey = PGPPublicKey.addCertification(publicKey, revocationCertificate.getSignature()); assertTrue(publicKey.hasRevocation()); } @@ -88,19 +90,20 @@ public class RevokeSubKeyTest { @TestTemplate @ExtendWith(TestAllImplementations.class) public void testRevocationSignatureTypeCorrect() throws IOException, PGPException { - PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing(); - Iterator keysIterator = secretKeys.getPublicKeys(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = TestKeys.getCryptieKey(); + Iterator keysIterator = secretKeys.getPGPKeyRing().getPublicKeys(); PGPPublicKey primaryKey = keysIterator.next(); PGPPublicKey subKey = keysIterator.next(); SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector .forKey(secretKeys, Passphrase.fromPassword("password123")); - SecretKeyRingEditorInterface editor = PGPainless.modifyKeyRing(secretKeys); - PGPSignature keyRevocation = editor.createRevocation(primaryKey.getKeyID(), protector, (RevocationAttributes) null); - PGPSignature subkeyRevocation = editor.createRevocation(subKey.getKeyID(), protector, (RevocationAttributes) null); + SecretKeyRingEditorInterface editor = api.modify(secretKeys); + OpenPGPSignature keyRevocation = editor.createRevocation(primaryKey.getKeyIdentifier(), protector, (RevocationAttributes) null); + OpenPGPSignature subkeyRevocation = editor.createRevocation(subKey.getKeyIdentifier(), protector, (RevocationAttributes) null); - assertEquals(SignatureType.KEY_REVOCATION.getCode(), keyRevocation.getSignatureType()); - assertEquals(SignatureType.SUBKEY_REVOCATION.getCode(), subkeyRevocation.getSignatureType()); + assertEquals(SignatureType.KEY_REVOCATION.getCode(), keyRevocation.getSignature().getSignatureType()); + assertEquals(SignatureType.SUBKEY_REVOCATION.getCode(), subkeyRevocation.getSignature().getSignatureType()); } @Test @@ -126,39 +129,39 @@ public class RevokeSubKeyTest { @Test public void inspectSubpacketsOnDefaultRevocationSignature() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice"); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); - PGPPublicKey encryptionSubkey = PGPainless.inspectKeyRing(secretKeys) + PGPPublicKey encryptionSubkey = api.inspect(secretKeys) .getEncryptionSubkeys(EncryptionPurpose.ANY).get(0).getPGPPublicKey(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) - .revokeSubKey(encryptionSubkey.getKeyID(), protector) + secretKeys = api.modify(secretKeys) + .revokeSubKey(encryptionSubkey.getKeyIdentifier(), protector) .done(); - encryptionSubkey = secretKeys.getPublicKey(encryptionSubkey.getKeyID()); + encryptionSubkey = secretKeys.getPGPSecretKeyRing().getPublicKey(encryptionSubkey.getKeyIdentifier()); PGPSignature revocation = encryptionSubkey.getSignaturesOfType(SignatureType.SUBKEY_REVOCATION.getCode()).next(); assertNotNull(revocation); assertArrayEquals( - secretKeys.getPublicKey().getFingerprint(), + secretKeys.getPGPSecretKeyRing().getPublicKey().getFingerprint(), revocation.getHashedSubPackets().getIssuerFingerprint().getFingerprint()); - assertEquals(secretKeys.getPublicKey().getKeyID(), + assertEquals(secretKeys.getPGPSecretKeyRing().getPublicKey().getKeyID(), revocation.getHashedSubPackets().getIssuerKeyID()); assertNull(SignatureSubpacketsUtil.getRevocationReason(revocation)); - assertTrue(SignatureUtils.isHardRevocation(revocation)); + assertTrue(revocation.isHardRevocation()); } @Test public void inspectSubpacketsOnModifiedRevocationSignature() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice"); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); - PGPPublicKey encryptionSubkey = PGPainless.inspectKeyRing(secretKeys) + PGPPublicKey encryptionSubkey = api.inspect(secretKeys) .getEncryptionSubkeys(EncryptionPurpose.ANY).get(0).getPGPPublicKey(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) - .revokeSubKey(encryptionSubkey.getKeyID(), protector, new RevocationSignatureSubpackets.Callback() { + secretKeys = api.modify(secretKeys) + .revokeSubKey(encryptionSubkey.getKeyIdentifier(), protector, new RevocationSignatureSubpackets.Callback() { @Override public void modifyHashedSubpackets(RevocationSignatureSubpackets hashedSubpackets) { hashedSubpackets.setRevocationReason( @@ -171,14 +174,14 @@ public class RevokeSubKeyTest { }) .done(); - encryptionSubkey = secretKeys.getPublicKey(encryptionSubkey.getKeyID()); + encryptionSubkey = secretKeys.getPGPSecretKeyRing().getPublicKey(encryptionSubkey.getKeyIdentifier()); PGPSignature revocation = encryptionSubkey.getSignaturesOfType(SignatureType.SUBKEY_REVOCATION.getCode()).next(); assertNotNull(revocation); assertNull(revocation.getHashedSubPackets().getIssuerFingerprint()); - assertEquals(secretKeys.getPublicKey().getKeyID(), + assertEquals(secretKeys.getKeyIdentifier().getKeyId(), revocation.getHashedSubPackets().getIssuerKeyID()); assertNotNull(SignatureSubpacketsUtil.getRevocationReason(revocation)); - assertFalse(SignatureUtils.isHardRevocation(revocation)); + assertFalse(revocation.isHardRevocation()); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeUserIdsTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeUserIdsTest.java index e06f2065..f39c030f 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeUserIdsTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RevokeUserIdsTest.java @@ -13,46 +13,45 @@ import java.util.Date; import java.util.NoSuchElementException; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; import org.pgpainless.key.info.KeyRingInfo; import org.pgpainless.key.protection.SecretKeyRingProtector; import org.pgpainless.key.util.RevocationAttributes; -import org.pgpainless.util.selection.userid.SelectUserId; public class RevokeUserIdsTest { @Test public void revokeWithSelectUserId() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("Alice ") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("Alice "); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .addUserId("Allice ", protector) .addUserId("Alice ", protector) .done(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); assertTrue(info.isUserIdValid("Alice ")); assertTrue(info.isUserIdValid("Allice ")); assertTrue(info.isUserIdValid("Alice ")); Date n1 = new Date(info.getCreationDate().getTime() + 1000); // 1 sec later - secretKeys = PGPainless.modifyKeyRing(secretKeys, n1) + secretKeys = api.modify(secretKeys, n1) .revokeUserIds( - SelectUserId.containsEmailAddress("alice@example.org"), protector, RevocationAttributes.createCertificateRevocation() .withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID) - .withoutDescription()) + .withoutDescription(), + uid -> uid.contains("alice@example.org")) .done(); - info = PGPainless.inspectKeyRing(secretKeys, n1); + info = api.inspect(secretKeys, n1); assertTrue(info.isUserIdValid("Alice ")); assertFalse(info.isUserIdValid("Allice ")); assertFalse(info.isUserIdValid("Alice ")); @@ -60,28 +59,28 @@ public class RevokeUserIdsTest { @Test public void removeUserId() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("Alice ") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("Alice "); SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .addUserId("Allice ", protector) .addUserId("Alice ", protector) .done(); - KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + KeyRingInfo info = api.inspect(secretKeys); assertTrue(info.isUserIdValid("Alice ")); assertTrue(info.isUserIdValid("Allice ")); assertTrue(info.isUserIdValid("Alice ")); Date n1 = new Date(info.getCreationDate().getTime() + 1000); - secretKeys = PGPainless.modifyKeyRing(secretKeys, n1) + secretKeys = api.modify(secretKeys, n1) .removeUserId("Allice ", protector) .done(); - info = PGPainless.inspectKeyRing(secretKeys, n1); + info = api.inspect(secretKeys, n1); assertTrue(info.isUserIdValid("Alice ")); assertFalse(info.isUserIdValid("Allice ")); assertTrue(info.isUserIdValid("Alice ")); @@ -95,14 +94,14 @@ public class RevokeUserIdsTest { @Test public void emptySelectionYieldsNoSuchElementException() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("Alice ") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("Alice "); assertThrows(NoSuchElementException.class, () -> - PGPainless.modifyKeyRing(secretKeys).revokeUserIds( - SelectUserId.containsEmailAddress("alice@example.org"), + api.modify(secretKeys).revokeUserIds( SecretKeyRingProtector.unprotectedKeys(), - (RevocationAttributes) null)); + (RevocationAttributes) null, + uid -> uid.contains("alice@example.org"))); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/protection/fixes/S2KUsageFixTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/protection/fixes/S2KUsageFixTest.java index f13f8ab0..0fd98622 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/protection/fixes/S2KUsageFixTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/protection/fixes/S2KUsageFixTest.java @@ -16,6 +16,7 @@ import org.bouncycastle.bcpg.SecretKeyPacket; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.bouncycastle.util.io.Streams; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; @@ -67,27 +68,27 @@ public class S2KUsageFixTest { @Test public void verifyOutFixInChangePassphraseWorks() throws PGPException { - PGPSecretKeyRing before = PGPainless.generateKeyRing().modernKeyRing("Alice", "before") - .getPGPSecretKeyRing(); - for (PGPSecretKey key : before) { + PGPainless api = PGPainless.getInstance(); + OpenPGPKey before = api.generateKey().modernKeyRing("Alice", "before"); + for (PGPSecretKey key : before.getPGPSecretKeyRing()) { assertEquals(SecretKeyPacket.USAGE_SHA1, key.getS2KUsage()); } - PGPSecretKeyRing unprotected = PGPainless.modifyKeyRing(before) + OpenPGPKey unprotected = api.modify(before) .changePassphraseFromOldPassphrase(Passphrase.fromPassword("before")) .withSecureDefaultSettings() .toNoPassphrase() .done(); - for (PGPSecretKey key : unprotected) { + for (PGPSecretKey key : unprotected.getPGPSecretKeyRing()) { assertEquals(SecretKeyPacket.USAGE_NONE, key.getS2KUsage()); } - PGPSecretKeyRing after = PGPainless.modifyKeyRing(unprotected) + OpenPGPKey after = api.modify(unprotected) .changePassphraseFromOldPassphrase(Passphrase.emptyPassphrase()) .withSecureDefaultSettings() .toNewPassphrase(Passphrase.fromPassword("after")) .done(); - for (PGPSecretKey key : after) { + for (PGPSecretKey key : after.getPGPSecretKeyRing()) { assertEquals(SecretKeyPacket.USAGE_SHA1, key.getS2KUsage()); } } @@ -95,18 +96,19 @@ public class S2KUsageFixTest { @Test public void testFixS2KUsageFrom_USAGE_CHECKSUM_to_USAGE_SHA1() throws IOException, PGPException { - PGPSecretKeyRing keys = PGPainless.readKeyRing().secretKeyRing(KEY_WITH_USAGE_CHECKSUM); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey keys = api.readKey().parseKey(KEY_WITH_USAGE_CHECKSUM); SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword("after")); - PGPSecretKeyRing fixed = S2KUsageFix.replaceUsageChecksumWithUsageSha1(keys, protector); + PGPSecretKeyRing fixed = S2KUsageFix.replaceUsageChecksumWithUsageSha1(keys.getPGPSecretKeyRing(), protector); for (PGPSecretKey key : fixed) { assertEquals(SecretKeyPacket.USAGE_SHA1, key.getS2KUsage()); } - testCanStillDecrypt(keys, protector); + testCanStillDecrypt(api.toKey(fixed), protector); } - private void testCanStillDecrypt(PGPSecretKeyRing keys, SecretKeyRingProtector protector) + private void testCanStillDecrypt(OpenPGPKey keys, SecretKeyRingProtector protector) throws PGPException, IOException { ByteArrayInputStream in = new ByteArrayInputStream(MESSAGE.getBytes(StandardCharsets.UTF_8)); DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify() diff --git a/pgpainless-core/src/test/java/org/pgpainless/signature/SignatureSubpacketsUtilTest.java b/pgpainless-core/src/test/java/org/pgpainless/signature/SignatureSubpacketsUtilTest.java index 3fcf712e..a377ed82 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/signature/SignatureSubpacketsUtilTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/signature/SignatureSubpacketsUtilTest.java @@ -34,6 +34,7 @@ import org.bouncycastle.openpgp.PGPSignatureGenerator; import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator; import org.bouncycastle.openpgp.api.OpenPGPCertificate; import org.bouncycastle.openpgp.api.OpenPGPImplementation; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; import org.pgpainless.algorithm.CompressionAlgorithm; @@ -43,7 +44,6 @@ import org.pgpainless.algorithm.SignatureType; import org.pgpainless.key.TestKeys; import org.pgpainless.key.protection.SecretKeyRingProtector; import org.pgpainless.key.protection.UnlockSecretKey; -import org.pgpainless.policy.Policy; import org.pgpainless.signature.consumer.SignaturePicker; import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil; @@ -51,17 +51,17 @@ public class SignatureSubpacketsUtilTest { @Test public void testGetKeyExpirationTimeAsDate() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("Expire") - .getPGPSecretKeyRing(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .modernKeyRing("Expire"); Date expiration = Date.from(new Date().toInstant().plus(365, ChronoUnit.DAYS)); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .setExpirationDate(expiration, SecretKeyRingProtector.unprotectedKeys()) .done(); PGPSignature expirationSig = SignaturePicker.pickCurrentUserIdCertificationSignature( - secretKeys, "Expire", Policy.getInstance(), new Date()); - OpenPGPCertificate.OpenPGPComponentKey notTheRightKey = PGPainless.inspectKeyRing(secretKeys).getSigningSubkeys().get(0); + secretKeys.getPGPSecretKeyRing(), "Expire", api.getAlgorithmPolicy(), new Date()); + OpenPGPCertificate.OpenPGPComponentKey notTheRightKey = api.inspect(secretKeys).getSigningSubkeys().get(0); assertThrows(IllegalArgumentException.class, () -> SignatureSubpacketsUtil.getKeyExpirationTimeAsDate(expirationSig, notTheRightKey.getPGPPublicKey())); @@ -69,18 +69,19 @@ public class SignatureSubpacketsUtilTest { @Test public void testGetRevocable() throws PGPException, IOException { - PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing(); - PGPPrivateKey certKey = UnlockSecretKey.unlockSecretKey(secretKeys.getSecretKey(), SecretKeyRingProtector.unprotectedKeys()); + OpenPGPKey secretKeys = TestKeys.getEmilKey(); + PGPPrivateKey certKey = UnlockSecretKey.unlockSecretKey(secretKeys.getPrimarySecretKey().getPGPSecretKey(), + SecretKeyRingProtector.unprotectedKeys()); PGPSignatureGenerator generator = getSignatureGenerator(certKey, SignatureType.CASUAL_CERTIFICATION); - PGPSignature withoutRevocable = generator.generateCertification(secretKeys.getPublicKey()); + PGPSignature withoutRevocable = generator.generateCertification(secretKeys.getPrimaryKey().getPGPPublicKey()); assertNull(SignatureSubpacketsUtil.getRevocable(withoutRevocable)); generator = getSignatureGenerator(certKey, SignatureType.CASUAL_CERTIFICATION); PGPSignatureSubpacketGenerator hashed = new PGPSignatureSubpacketGenerator(); hashed.setRevocable(true, true); generator.setHashedSubpackets(hashed.generate()); - PGPSignature withRevocable = generator.generateCertification(secretKeys.getPublicKey()); + PGPSignature withRevocable = generator.generateCertification(secretKeys.getPrimaryKey().getPGPPublicKey()); assertNotNull(SignatureSubpacketsUtil.getRevocable(withRevocable)); } diff --git a/pgpainless-core/src/test/java/org/pgpainless/util/selection/userid/SelectUserIdTest.java b/pgpainless-core/src/test/java/org/pgpainless/util/selection/userid/SelectUserIdTest.java index d45594e6..b8eccd95 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/util/selection/userid/SelectUserIdTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/util/selection/userid/SelectUserIdTest.java @@ -14,7 +14,7 @@ import java.util.List; import java.util.stream.Collectors; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; import org.pgpainless.key.protection.SecretKeyRingProtector; @@ -24,17 +24,17 @@ public class SelectUserIdTest { @Test public void testSelectUserIds() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .simpleEcKeyRing("") - .getPGPSecretKeyRing(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey() + .simpleEcKeyRing(""); + secretKeys = api.modify(secretKeys) .addUserId( UserId.builder().withName("Alice Liddell").noComment() .withEmail("crazy@the-rabbit.hole").build(), SecretKeyRingProtector.unprotectedKeys()) .done(); - List userIds = PGPainless.inspectKeyRing(secretKeys).getValidUserIds(); + List userIds = api.inspect(secretKeys).getValidUserIds(); List validEmail = userIds.stream().filter(SelectUserId.and( SelectUserId.validUserId(secretKeys), SelectUserId.containsEmailAddress("alice@wonderland.lit") @@ -54,14 +54,14 @@ public class SelectUserIdTest { @Test public void testContainsSubstring() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("wine drinker") - .getPGPSecretKeyRing(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().simpleEcKeyRing("wine drinker"); + secretKeys = api.modify(secretKeys) .addUserId("this is not a quine", SecretKeyRingProtector.unprotectedKeys()) .addUserId("this is not a crime", SecretKeyRingProtector.unprotectedKeys()) .done(); - List userIds = PGPainless.inspectKeyRing(secretKeys).getValidUserIds(); + List userIds = api.inspect(secretKeys).getValidUserIds(); List containSubstring = userIds.stream().filter(SelectUserId.containsSubstring("ine")).collect(Collectors.toList()); assertEquals(Arrays.asList("wine drinker", "this is not a quine"), containSubstring); @@ -69,9 +69,9 @@ public class SelectUserIdTest { @Test public void testContainsEmailAddress() { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("Alice ") - .getPGPSecretKeyRing(); - List userIds = PGPainless.inspectKeyRing(secretKeys).getValidUserIds(); + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().simpleEcKeyRing("Alice "); + List userIds = api.inspect(secretKeys).getValidUserIds(); assertEquals("Alice ", userIds.stream().filter( SelectUserId.containsEmailAddress("alice@wonderland.lit")).findFirst().get()); @@ -83,15 +83,15 @@ public class SelectUserIdTest { @Test public void testAndOrNot() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("Alice ") - .getPGPSecretKeyRing(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().simpleEcKeyRing("Alice "); + secretKeys = api.modify(secretKeys) .addUserId("Alice ", SecretKeyRingProtector.unprotectedKeys()) .addUserId("", SecretKeyRingProtector.unprotectedKeys()) .addUserId("Crazy Girl ", SecretKeyRingProtector.unprotectedKeys()) .done(); - List userIds = PGPainless.inspectKeyRing(secretKeys).getValidUserIds(); + List userIds = api.inspect(secretKeys).getValidUserIds(); List or = userIds.stream().filter(SelectUserId.or( SelectUserId.containsEmailAddress("alice@wonderland.lit"), @@ -110,12 +110,12 @@ public class SelectUserIdTest { @Test public void testFirstMatch() throws PGPException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("First UserID") - .getPGPSecretKeyRing(); - secretKeys = PGPainless.modifyKeyRing(secretKeys) + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = api.generateKey().simpleEcKeyRing("First UserID"); + secretKeys = api.modify(secretKeys) .addUserId("Second UserID", SecretKeyRingProtector.unprotectedKeys()) .done(); - List userIds = PGPainless.inspectKeyRing(secretKeys).getValidUserIds(); + List userIds = api.inspect(secretKeys).getValidUserIds(); assertEquals("First UserID", userIds.stream().filter(SelectUserId.validUserId(secretKeys)).findFirst().get()); assertEquals("Second UserID", userIds.stream().filter(SelectUserId.containsSubstring("Second")).findFirst().get()); } diff --git a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/RevokeKeyImpl.kt b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/RevokeKeyImpl.kt index ecc87e62..f53338ee 100644 --- a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/RevokeKeyImpl.kt +++ b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/RevokeKeyImpl.kt @@ -9,10 +9,11 @@ import java.io.InputStream import java.io.OutputStream import java.lang.RuntimeException import org.bouncycastle.openpgp.PGPException -import org.bouncycastle.openpgp.PGPPublicKeyRing import org.bouncycastle.openpgp.PGPPublicKeyRingCollection +import org.bouncycastle.openpgp.api.OpenPGPCertificate import org.pgpainless.PGPainless import org.pgpainless.bouncycastle.extensions.openPgpFingerprint +import org.pgpainless.bouncycastle.extensions.toOpenPGPCertificate import org.pgpainless.exception.WrongPassphraseException import org.pgpainless.key.util.KeyRingUtils import org.pgpainless.key.util.RevocationAttributes @@ -38,7 +39,7 @@ class RevokeKeyImpl : RevokeKey { secretKeyRings.forEach { protector.addSecretKey(it) } - val revocationCertificates = mutableListOf() + val revocationCertificates = mutableListOf() secretKeyRings.forEach { secretKeys -> val editor = PGPainless.modifyKeyRing(secretKeys) try { @@ -53,7 +54,8 @@ class RevokeKeyImpl : RevokeKey { val certificate = PGPainless.extractCertificate(secretKeys) val revocation = editor.createRevocation(protector, attributes) revocationCertificates.add( - KeyRingUtils.injectCertification(certificate, revocation)) + KeyRingUtils.injectCertification(certificate, revocation.signature) + .toOpenPGPCertificate()) } } catch (e: WrongPassphraseException) { throw SOPGPException.KeyIsProtected( @@ -67,7 +69,8 @@ class RevokeKeyImpl : RevokeKey { return object : Ready() { override fun writeTo(outputStream: OutputStream) { - val collection = PGPPublicKeyRingCollection(revocationCertificates) + val collection = + PGPPublicKeyRingCollection(revocationCertificates.map { it.pgpPublicKeyRing }) if (armor) { val armorOut = ArmoredOutputStreamFactory.get(outputStream) collection.encode(armorOut) diff --git a/pgpainless-sop/src/test/java/sop/testsuite/pgpainless/operation/PGPainlessChangeKeyPasswordTest.java b/pgpainless-sop/src/test/java/sop/testsuite/pgpainless/operation/PGPainlessChangeKeyPasswordTest.java index cb45551d..6756300a 100644 --- a/pgpainless-sop/src/test/java/sop/testsuite/pgpainless/operation/PGPainlessChangeKeyPasswordTest.java +++ b/pgpainless-sop/src/test/java/sop/testsuite/pgpainless/operation/PGPainlessChangeKeyPasswordTest.java @@ -7,7 +7,7 @@ package sop.testsuite.pgpainless.operation; import org.bouncycastle.bcpg.KeyIdentifier; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKey; -import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.api.OpenPGPKey; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.pgpainless.PGPainless; @@ -32,13 +32,13 @@ public class PGPainlessChangeKeyPasswordTest extends ChangeKeyPasswordTest { @ParameterizedTest @MethodSource("provideInstances") public void changePasswordOfKeyWithSeparateSubkeyPasswords(SOP sop) throws IOException, PGPException { - PGPSecretKeyRing secretKeys = PGPainless.buildKeyRing() + PGPainless api = PGPainless.getInstance(); + OpenPGPKey secretKeys = PGPainless.buildKeyRing() .setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.CERTIFY_OTHER)) .addSubkey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.SIGN_DATA)) .addSubkey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)) - .build() - .getPGPSecretKeyRing(); - Iterator keys = secretKeys.getPublicKeys(); + .build(); + Iterator keys = secretKeys.getPGPSecretKeyRing().getPublicKeys(); KeyIdentifier primaryKeyId = keys.next().getKeyIdentifier(); KeyIdentifier signingKeyId = keys.next().getKeyIdentifier(); KeyIdentifier encryptKeyId = keys.next().getKeyIdentifier(); @@ -47,7 +47,7 @@ public class PGPainlessChangeKeyPasswordTest extends ChangeKeyPasswordTest { String p2 = "0r4ng3"; String p3 = "dr4g0n"; - secretKeys = PGPainless.modifyKeyRing(secretKeys) + secretKeys = api.modify(secretKeys) .changeSubKeyPassphraseFromOldPassphrase(primaryKeyId, Passphrase.emptyPassphrase()) .withSecureDefaultSettings() .toNewPassphrase(Passphrase.fromPassword(p1))