mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-10 18:59:39 +02:00
Port SecretKeyRingEditor, replace Singleton usage with API instance calls
This commit is contained in:
parent
9041a6c601
commit
261838dd2a
43 changed files with 811 additions and 611 deletions
|
@ -67,9 +67,14 @@ class PGPainless(
|
||||||
* @param referenceTime reference time for evaluation
|
* @param referenceTime reference time for evaluation
|
||||||
* @return [KeyRingInfo] wrapper
|
* @return [KeyRingInfo] wrapper
|
||||||
*/
|
*/
|
||||||
|
@JvmOverloads
|
||||||
fun inspect(keyOrCertificate: OpenPGPCertificate, referenceTime: Date = Date()): KeyRingInfo =
|
fun inspect(keyOrCertificate: OpenPGPCertificate, referenceTime: Date = Date()): KeyRingInfo =
|
||||||
KeyRingInfo(keyOrCertificate, this, referenceTime)
|
KeyRingInfo(keyOrCertificate, this, referenceTime)
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
fun modify(key: OpenPGPKey, referenceTime: Date = Date()): SecretKeyRingEditor =
|
||||||
|
SecretKeyRingEditor(key, this, referenceTime)
|
||||||
|
|
||||||
fun readKey(): OpenPGPKeyReader = api.readKeyOrCertificate()
|
fun readKey(): OpenPGPKeyReader = api.readKeyOrCertificate()
|
||||||
|
|
||||||
fun toKey(secretKeyRing: PGPSecretKeyRing): OpenPGPKey =
|
fun toKey(secretKeyRing: PGPSecretKeyRing): OpenPGPKey =
|
||||||
|
|
|
@ -694,7 +694,7 @@ class OpenPgpMessageInputStream(
|
||||||
private fun getDecryptionKey(pkesk: PGPPublicKeyEncryptedData): OpenPGPKey? =
|
private fun getDecryptionKey(pkesk: PGPPublicKeyEncryptedData): OpenPGPKey? =
|
||||||
options.getDecryptionKeys().firstOrNull {
|
options.getDecryptionKeys().firstOrNull {
|
||||||
it.pgpSecretKeyRing.getSecretKeyFor(pkesk) != null &&
|
it.pgpSecretKeyRing.getSecretKeyFor(pkesk) != null &&
|
||||||
PGPainless.inspectKeyRing(it).decryptionSubkeys.any { subkey ->
|
api.inspect(it).decryptionSubkeys.any { subkey ->
|
||||||
pkesk.keyIdentifier.matches(subkey.keyIdentifier)
|
pkesk.keyIdentifier.matches(subkey.keyIdentifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -702,7 +702,7 @@ class OpenPgpMessageInputStream(
|
||||||
private fun getDecryptionKeys(pkesk: PGPPublicKeyEncryptedData): List<OpenPGPKey> =
|
private fun getDecryptionKeys(pkesk: PGPPublicKeyEncryptedData): List<OpenPGPKey> =
|
||||||
options.getDecryptionKeys().filter {
|
options.getDecryptionKeys().filter {
|
||||||
it.pgpSecretKeyRing.getSecretKeyFor(pkesk) != null &&
|
it.pgpSecretKeyRing.getSecretKeyFor(pkesk) != null &&
|
||||||
PGPainless.inspectKeyRing(it).decryptionSubkeys.any { subkey ->
|
api.inspect(it).decryptionSubkeys.any { subkey ->
|
||||||
pkesk.keyIdentifier.matches(subkey.keyIdentifier)
|
pkesk.keyIdentifier.matches(subkey.keyIdentifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -713,7 +713,7 @@ class OpenPgpMessageInputStream(
|
||||||
val algorithm = pkesk.algorithm
|
val algorithm = pkesk.algorithm
|
||||||
val candidates = mutableListOf<OpenPGPSecretKey>()
|
val candidates = mutableListOf<OpenPGPSecretKey>()
|
||||||
options.getDecryptionKeys().forEach {
|
options.getDecryptionKeys().forEach {
|
||||||
val info = PGPainless.inspectKeyRing(it)
|
val info = api.inspect(it)
|
||||||
for (key in info.decryptionSubkeys) {
|
for (key in info.decryptionSubkeys) {
|
||||||
if (key.pgpPublicKey.algorithm == algorithm &&
|
if (key.pgpPublicKey.algorithm == algorithm &&
|
||||||
info.isSecretKeyAvailable(key.keyIdentifier)) {
|
info.isSecretKeyAvailable(key.keyIdentifier)) {
|
||||||
|
|
|
@ -10,7 +10,6 @@ import org.bouncycastle.openpgp.api.OpenPGPCertificate
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey
|
||||||
import org.bouncycastle.openpgp.operator.PGPKeyEncryptionMethodGenerator
|
import org.bouncycastle.openpgp.operator.PGPKeyEncryptionMethodGenerator
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.PGPainless.Companion.inspectKeyRing
|
|
||||||
import org.pgpainless.algorithm.EncryptionPurpose
|
import org.pgpainless.algorithm.EncryptionPurpose
|
||||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm
|
||||||
import org.pgpainless.algorithm.negotiation.SymmetricKeyAlgorithmNegotiator.Companion.byPopularity
|
import org.pgpainless.algorithm.negotiation.SymmetricKeyAlgorithmNegotiator.Companion.byPopularity
|
||||||
|
@ -191,7 +190,7 @@ class EncryptionOptions(private val purpose: EncryptionPurpose, private val api:
|
||||||
userId: CharSequence,
|
userId: CharSequence,
|
||||||
encryptionKeySelector: EncryptionKeySelector
|
encryptionKeySelector: EncryptionKeySelector
|
||||||
) = apply {
|
) = apply {
|
||||||
val info = inspectKeyRing(cert, evaluationDate)
|
val info = api.inspect(cert, evaluationDate)
|
||||||
val subkeys =
|
val subkeys =
|
||||||
encryptionKeySelector.selectEncryptionSubkeys(
|
encryptionKeySelector.selectEncryptionSubkeys(
|
||||||
info.getEncryptionSubkeys(userId, purpose))
|
info.getEncryptionSubkeys(userId, purpose))
|
||||||
|
@ -289,7 +288,7 @@ class EncryptionOptions(private val purpose: EncryptionPurpose, private val api:
|
||||||
selector: EncryptionKeySelector,
|
selector: EncryptionKeySelector,
|
||||||
wildcardKeyId: Boolean
|
wildcardKeyId: Boolean
|
||||||
) = apply {
|
) = apply {
|
||||||
val info = inspectKeyRing(cert, evaluationDate)
|
val info = api.inspect(cert, evaluationDate)
|
||||||
val primaryKeyExpiration =
|
val primaryKeyExpiration =
|
||||||
try {
|
try {
|
||||||
info.primaryKeyExpirationDate
|
info.primaryKeyExpirationDate
|
||||||
|
|
|
@ -8,6 +8,7 @@ import java.util.*
|
||||||
import org.bouncycastle.openpgp.PGPLiteralData
|
import org.bouncycastle.openpgp.PGPLiteralData
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing
|
import org.bouncycastle.openpgp.PGPPublicKeyRing
|
||||||
import org.bouncycastle.openpgp.PGPSignature
|
import org.bouncycastle.openpgp.PGPSignature
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate
|
||||||
import org.pgpainless.algorithm.CompressionAlgorithm
|
import org.pgpainless.algorithm.CompressionAlgorithm
|
||||||
import org.pgpainless.algorithm.StreamEncoding
|
import org.pgpainless.algorithm.StreamEncoding
|
||||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm
|
||||||
|
@ -34,6 +35,9 @@ data class EncryptionResult(
|
||||||
val isForYourEyesOnly: Boolean
|
val isForYourEyesOnly: Boolean
|
||||||
get() = PGPLiteralData.CONSOLE == fileName
|
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.
|
* Returns true, if the message was encrypted for at least one subkey of the given certificate.
|
||||||
*
|
*
|
||||||
|
|
|
@ -12,7 +12,6 @@ import org.bouncycastle.openpgp.api.OpenPGPKey
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPPrivateKey
|
import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPPrivateKey
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPSecretKey
|
import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPSecretKey
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.PGPainless.Companion.inspectKeyRing
|
|
||||||
import org.pgpainless.algorithm.DocumentSignatureType
|
import org.pgpainless.algorithm.DocumentSignatureType
|
||||||
import org.pgpainless.algorithm.HashAlgorithm
|
import org.pgpainless.algorithm.HashAlgorithm
|
||||||
import org.pgpainless.algorithm.PublicKeyAlgorithm.Companion.requireFromId
|
import org.pgpainless.algorithm.PublicKeyAlgorithm.Companion.requireFromId
|
||||||
|
@ -138,6 +137,7 @@ class SigningOptions(private val api: PGPainless) {
|
||||||
signatureType: DocumentSignatureType
|
signatureType: DocumentSignatureType
|
||||||
) = addInlineSignature(signingKeyProtector, api.toKey(signingKey), signatureType)
|
) = addInlineSignature(signingKeyProtector, api.toKey(signingKey), signatureType)
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
fun addInlineSignature(
|
fun addInlineSignature(
|
||||||
signingKeyProtector: SecretKeyRingProtector,
|
signingKeyProtector: SecretKeyRingProtector,
|
||||||
signingKey: OpenPGPKey,
|
signingKey: OpenPGPKey,
|
||||||
|
@ -145,7 +145,7 @@ class SigningOptions(private val api: PGPainless) {
|
||||||
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
||||||
subpacketsCallback: Callback? = null
|
subpacketsCallback: Callback? = null
|
||||||
) = apply {
|
) = apply {
|
||||||
val keyRingInfo = inspectKeyRing(signingKey, evaluationDate)
|
val keyRingInfo = api.inspect(signingKey, evaluationDate)
|
||||||
if (userId != null && !keyRingInfo.isUserIdValid(userId)) {
|
if (userId != null && !keyRingInfo.isUserIdValid(userId)) {
|
||||||
throw UnboundUserIdException(
|
throw UnboundUserIdException(
|
||||||
of(signingKey),
|
of(signingKey),
|
||||||
|
@ -212,7 +212,7 @@ class SigningOptions(private val api: PGPainless) {
|
||||||
subpacketsCallback: Callback? = null
|
subpacketsCallback: Callback? = null
|
||||||
): SigningOptions = apply {
|
): SigningOptions = apply {
|
||||||
val openPGPKey = signingKey.openPGPKey
|
val openPGPKey = signingKey.openPGPKey
|
||||||
val keyRingInfo = inspectKeyRing(openPGPKey, evaluationDate)
|
val keyRingInfo = api.inspect(openPGPKey, evaluationDate)
|
||||||
val signingPubKeys = keyRingInfo.signingSubkeys
|
val signingPubKeys = keyRingInfo.signingSubkeys
|
||||||
if (signingPubKeys.isEmpty()) {
|
if (signingPubKeys.isEmpty()) {
|
||||||
throw UnacceptableSigningKeyException(openPGPKey)
|
throw UnacceptableSigningKeyException(openPGPKey)
|
||||||
|
@ -319,7 +319,7 @@ class SigningOptions(private val api: PGPainless) {
|
||||||
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
||||||
subpacketCallback: Callback? = null
|
subpacketCallback: Callback? = null
|
||||||
): SigningOptions = apply {
|
): SigningOptions = apply {
|
||||||
val keyRingInfo = inspectKeyRing(signingKey, evaluationDate)
|
val keyRingInfo = api.inspect(signingKey, evaluationDate)
|
||||||
if (userId != null && !keyRingInfo.isUserIdValid(userId)) {
|
if (userId != null && !keyRingInfo.isUserIdValid(userId)) {
|
||||||
throw UnboundUserIdException(
|
throw UnboundUserIdException(
|
||||||
of(signingKey),
|
of(signingKey),
|
||||||
|
@ -380,7 +380,7 @@ class SigningOptions(private val api: PGPainless) {
|
||||||
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
||||||
subpacketCallback: Callback? = null
|
subpacketCallback: Callback? = null
|
||||||
): SigningOptions = apply {
|
): SigningOptions = apply {
|
||||||
val keyRingInfo = inspectKeyRing(signingKey.openPGPKey, evaluationDate)
|
val keyRingInfo = api.inspect(signingKey.openPGPKey, evaluationDate)
|
||||||
val signingPrivKey: OpenPGPPrivateKey = signingKey.unlock(signingKeyProtector)
|
val signingPrivKey: OpenPGPPrivateKey = signingKey.unlock(signingKeyProtector)
|
||||||
val hashAlgorithms =
|
val hashAlgorithms =
|
||||||
if (userId != null) keyRingInfo.getPreferredHashAlgorithms(userId)
|
if (userId != null) keyRingInfo.getPreferredHashAlgorithms(userId)
|
||||||
|
|
|
@ -134,7 +134,7 @@ class CertifyCertificate(private val api: PGPainless) {
|
||||||
key: OpenPGPKey,
|
key: OpenPGPKey,
|
||||||
protector: SecretKeyRingProtector
|
protector: SecretKeyRingProtector
|
||||||
): CertificationOnUserIdWithSubpackets {
|
): CertificationOnUserIdWithSubpackets {
|
||||||
val secretKey = getCertifyingSecretKey(key)
|
val secretKey = getCertifyingSecretKey(key, api)
|
||||||
val sigBuilder =
|
val sigBuilder =
|
||||||
ThirdPartyCertificationSignatureBuilder(
|
ThirdPartyCertificationSignatureBuilder(
|
||||||
certificationType.asSignatureType(), secretKey, protector, api)
|
certificationType.asSignatureType(), secretKey, protector, api)
|
||||||
|
@ -220,7 +220,7 @@ class CertifyCertificate(private val api: PGPainless) {
|
||||||
key: OpenPGPKey,
|
key: OpenPGPKey,
|
||||||
protector: SecretKeyRingProtector
|
protector: SecretKeyRingProtector
|
||||||
): DelegationOnCertificateWithSubpackets {
|
): DelegationOnCertificateWithSubpackets {
|
||||||
val secretKey = getCertifyingSecretKey(key)
|
val secretKey = getCertifyingSecretKey(key, api)
|
||||||
val sigBuilder = ThirdPartyDirectKeySignatureBuilder(secretKey, protector, api)
|
val sigBuilder = ThirdPartyDirectKeySignatureBuilder(secretKey, protector, api)
|
||||||
if (trustworthiness != null) {
|
if (trustworthiness != null) {
|
||||||
sigBuilder.hashedSubpackets.setTrust(
|
sigBuilder.hashedSubpackets.setTrust(
|
||||||
|
@ -306,10 +306,11 @@ class CertifyCertificate(private val api: PGPainless) {
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
private fun getCertifyingSecretKey(
|
private fun getCertifyingSecretKey(
|
||||||
certificationKey: OpenPGPKey
|
certificationKey: OpenPGPKey,
|
||||||
|
api: PGPainless
|
||||||
): OpenPGPKey.OpenPGPSecretKey {
|
): OpenPGPKey.OpenPGPSecretKey {
|
||||||
val now = Date()
|
val now = Date()
|
||||||
val info = PGPainless.inspectKeyRing(certificationKey, now)
|
val info = api.inspect(certificationKey, now)
|
||||||
|
|
||||||
val fingerprint = info.fingerprint
|
val fingerprint = info.fingerprint
|
||||||
val certificationPubKey = info.getPublicKey(fingerprint)
|
val certificationPubKey = info.getPublicKey(fingerprint)
|
||||||
|
|
|
@ -8,10 +8,11 @@ import java.util.*
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
import javax.annotation.Nonnull
|
import javax.annotation.Nonnull
|
||||||
import kotlin.NoSuchElementException
|
import kotlin.NoSuchElementException
|
||||||
import openpgp.openPgpKeyId
|
|
||||||
import org.bouncycastle.bcpg.KeyIdentifier
|
import org.bouncycastle.bcpg.KeyIdentifier
|
||||||
import org.bouncycastle.bcpg.sig.KeyExpirationTime
|
import org.bouncycastle.bcpg.sig.KeyExpirationTime
|
||||||
import org.bouncycastle.openpgp.*
|
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.OpenPGPCertificate.OpenPGPSubkey
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPImplementation
|
import org.bouncycastle.openpgp.api.OpenPGPImplementation
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPKey
|
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.OpenPGPSignature
|
||||||
import org.bouncycastle.openpgp.api.SignatureParameters
|
import org.bouncycastle.openpgp.api.SignatureParameters
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.PGPainless.Companion.inspectKeyRing
|
|
||||||
import org.pgpainless.algorithm.AlgorithmSuite
|
import org.pgpainless.algorithm.AlgorithmSuite
|
||||||
import org.pgpainless.algorithm.KeyFlag
|
import org.pgpainless.algorithm.KeyFlag
|
||||||
import org.pgpainless.algorithm.OpenPGPKeyVersion
|
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.checksumCalculator
|
||||||
import org.pgpainless.bouncycastle.extensions.getKeyExpirationDate
|
import org.pgpainless.bouncycastle.extensions.getKeyExpirationDate
|
||||||
import org.pgpainless.bouncycastle.extensions.publicKeyAlgorithm
|
import org.pgpainless.bouncycastle.extensions.publicKeyAlgorithm
|
||||||
import org.pgpainless.bouncycastle.extensions.requirePublicKey
|
|
||||||
import org.pgpainless.key.OpenPgpFingerprint
|
import org.pgpainless.key.OpenPgpFingerprint
|
||||||
import org.pgpainless.key.generation.KeyRingBuilder
|
import org.pgpainless.key.generation.KeyRingBuilder
|
||||||
import org.pgpainless.key.generation.KeySpec
|
import org.pgpainless.key.generation.KeySpec
|
||||||
|
@ -50,8 +49,6 @@ class SecretKeyRingEditor(
|
||||||
override val referenceTime: Date = Date()
|
override val referenceTime: Date = Date()
|
||||||
) : SecretKeyRingEditorInterface {
|
) : SecretKeyRingEditorInterface {
|
||||||
|
|
||||||
private var secretKeyRing: PGPSecretKeyRing = key.pgpSecretKeyRing
|
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
constructor(
|
constructor(
|
||||||
secretKeyRing: PGPSecretKeyRing,
|
secretKeyRing: PGPSecretKeyRing,
|
||||||
|
@ -64,8 +61,7 @@ class SecretKeyRingEditor(
|
||||||
callback: SelfSignatureSubpackets.Callback?,
|
callback: SelfSignatureSubpackets.Callback?,
|
||||||
protector: SecretKeyRingProtector
|
protector: SecretKeyRingProtector
|
||||||
): SecretKeyRingEditorInterface {
|
): SecretKeyRingEditorInterface {
|
||||||
key = PGPainless.getInstance().toKey(secretKeyRing)
|
val info = api.inspect(key, referenceTime)
|
||||||
val info = inspectKeyRing(key, referenceTime)
|
|
||||||
require(!info.isHardRevoked(userId)) {
|
require(!info.isHardRevoked(userId)) {
|
||||||
"User-ID $userId is hard revoked and cannot be re-certified."
|
"User-ID $userId is hard revoked and cannot be re-certified."
|
||||||
}
|
}
|
||||||
|
@ -89,7 +85,7 @@ class SecretKeyRingEditor(
|
||||||
.setSignatureCreationTime(referenceTime)
|
.setSignatureCreationTime(referenceTime)
|
||||||
.setHashedSubpacketsFunction { subpacketGenerator ->
|
.setHashedSubpacketsFunction { subpacketGenerator ->
|
||||||
val subpackets = SignatureSubpackets(subpacketGenerator)
|
val subpackets = SignatureSubpackets(subpacketGenerator)
|
||||||
subpackets.setAppropriateIssuerInfo(secretKeyRing.publicKey)
|
subpackets.setAppropriateIssuerInfo(key.primaryKey.pgpPublicKey)
|
||||||
|
|
||||||
subpackets.setKeyFlags(info.getKeyFlagsOf(key.keyIdentifier))
|
subpackets.setKeyFlags(info.getKeyFlagsOf(key.keyIdentifier))
|
||||||
subpackets.setPreferredHashAlgorithms(hashAlgorithmPreferences)
|
subpackets.setPreferredHashAlgorithms(hashAlgorithmPreferences)
|
||||||
|
@ -111,7 +107,6 @@ class SecretKeyRingEditor(
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.done()
|
.done()
|
||||||
secretKeyRing = key.pgpSecretKeyRing
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,8 +115,8 @@ class SecretKeyRingEditor(
|
||||||
protector: SecretKeyRingProtector
|
protector: SecretKeyRingProtector
|
||||||
): SecretKeyRingEditorInterface {
|
): SecretKeyRingEditorInterface {
|
||||||
val uid = sanitizeUserId(userId)
|
val uid = sanitizeUserId(userId)
|
||||||
val primaryKey = secretKeyRing.publicKey
|
val primaryKey = key.primaryKey.pgpPublicKey
|
||||||
var info = inspectKeyRing(secretKeyRing, referenceTime)
|
var info = api.inspect(key, referenceTime)
|
||||||
val primaryUserId = info.primaryUserId
|
val primaryUserId = info.primaryUserId
|
||||||
val signature =
|
val signature =
|
||||||
if (primaryUserId == null) info.latestDirectKeySelfSignature
|
if (primaryUserId == null) info.latestDirectKeySelfSignature
|
||||||
|
@ -144,7 +139,7 @@ class SecretKeyRingEditor(
|
||||||
protector)
|
protector)
|
||||||
|
|
||||||
// unmark previous primary user-ids to be non-primary
|
// unmark previous primary user-ids to be non-primary
|
||||||
info = inspectKeyRing(secretKeyRing, referenceTime)
|
info = api.inspect(key, referenceTime)
|
||||||
info.validAndExpiredUserIds
|
info.validAndExpiredUserIds
|
||||||
.filterNot { it == uid }
|
.filterNot { it == uid }
|
||||||
.forEach { otherUserId ->
|
.forEach { otherUserId ->
|
||||||
|
@ -215,7 +210,7 @@ class SecretKeyRingEditor(
|
||||||
require(oldUID.isNotBlank()) { "Old user-ID cannot be empty." }
|
require(oldUID.isNotBlank()) { "Old user-ID cannot be empty." }
|
||||||
require(newUID.isNotBlank()) { "New 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)) {
|
if (!info.isUserIdValid(oldUID)) {
|
||||||
throw NoSuchElementException(
|
throw NoSuchElementException(
|
||||||
"Key does not carry user-ID '$oldUID', or it is not valid.")
|
"Key does not carry user-ID '$oldUID', or it is not valid.")
|
||||||
|
@ -244,7 +239,6 @@ class SecretKeyRingEditor(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
protector)
|
protector)
|
||||||
|
|
||||||
return revokeUserId(oldUID, protector)
|
return revokeUserId(oldUID, protector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +264,7 @@ class SecretKeyRingEditor(
|
||||||
callback: SelfSignatureSubpackets.Callback?,
|
callback: SelfSignatureSubpackets.Callback?,
|
||||||
protector: SecretKeyRingProtector
|
protector: SecretKeyRingProtector
|
||||||
): SecretKeyRingEditorInterface {
|
): SecretKeyRingEditorInterface {
|
||||||
val version = OpenPGPKeyVersion.from(secretKeyRing.publicKey.version)
|
val version = OpenPGPKeyVersion.from(key.primarySecretKey.version)
|
||||||
val keyPair = KeyRingBuilder.generateKeyPair(keySpec, version, api.implementation)
|
val keyPair = KeyRingBuilder.generateKeyPair(keySpec, version, api.implementation)
|
||||||
val subkeyProtector =
|
val subkeyProtector =
|
||||||
PasswordBasedSecretKeyRingProtector.forKeyId(keyPair.keyIdentifier, subkeyPassphrase)
|
PasswordBasedSecretKeyRingProtector.forKeyId(keyPair.keyIdentifier, subkeyPassphrase)
|
||||||
|
@ -303,8 +297,8 @@ class SecretKeyRingEditor(
|
||||||
"Public key algorithm policy violation: $subkeyAlgorithm with bit strength $bitStrength is not acceptable."
|
"Public key algorithm policy violation: $subkeyAlgorithm with bit strength $bitStrength is not acceptable."
|
||||||
}
|
}
|
||||||
|
|
||||||
val primaryKey = secretKeyRing.secretKey
|
val primaryKey = key.primarySecretKey.pgpSecretKey
|
||||||
val info = inspectKeyRing(secretKeyRing, referenceTime)
|
val info = api.inspect(key, referenceTime)
|
||||||
val hashAlgorithm =
|
val hashAlgorithm =
|
||||||
HashAlgorithmNegotiator.negotiateSignatureHashAlgorithm(api.algorithmPolicy)
|
HashAlgorithmNegotiator.negotiateSignatureHashAlgorithm(api.algorithmPolicy)
|
||||||
.negotiateHashAlgorithm(info.preferredHashAlgorithms)
|
.negotiateHashAlgorithm(info.preferredHashAlgorithms)
|
||||||
|
@ -341,7 +335,8 @@ class SecretKeyRingEditor(
|
||||||
secretSubkey =
|
secretSubkey =
|
||||||
KeyRingUtils.secretKeyPlusSignature(
|
KeyRingUtils.secretKeyPlusSignature(
|
||||||
secretSubkey, skBindingBuilder.build(secretSubkey.publicKey))
|
secretSubkey, skBindingBuilder.build(secretSubkey.publicKey))
|
||||||
secretKeyRing = KeyRingUtils.keysPlusSecretKey(secretKeyRing, secretSubkey)
|
val secretKeyRing = KeyRingUtils.keysPlusSecretKey(key.pgpSecretKeyRing, secretSubkey)
|
||||||
|
key = api.toKey(secretKeyRing)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,26 +351,33 @@ class SecretKeyRingEditor(
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
callback: RevocationSignatureSubpackets.Callback?
|
callback: RevocationSignatureSubpackets.Callback?
|
||||||
): SecretKeyRingEditorInterface {
|
): SecretKeyRingEditorInterface {
|
||||||
return revokeSubKey(secretKeyRing.secretKey.keyID, protector, callback)
|
return revokeSubKey(key.keyIdentifier, protector, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun revokeSubKey(
|
override fun revokeSubKey(
|
||||||
subkeyId: Long,
|
subkeyIdentifier: KeyIdentifier,
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revocationAttributes: RevocationAttributes?
|
revocationAttributes: RevocationAttributes?
|
||||||
): SecretKeyRingEditorInterface {
|
): SecretKeyRingEditorInterface {
|
||||||
return revokeSubKey(
|
return revokeSubKey(
|
||||||
subkeyId, protector, callbackFromRevocationAttributes(revocationAttributes))
|
subkeyIdentifier, protector, callbackFromRevocationAttributes(revocationAttributes))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun revokeSubKey(
|
override fun revokeSubKey(
|
||||||
subkeyId: Long,
|
subkeyIdentifier: KeyIdentifier,
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
callback: RevocationSignatureSubpackets.Callback?
|
callback: RevocationSignatureSubpackets.Callback?
|
||||||
): SecretKeyRingEditorInterface {
|
): 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)
|
val subkeyRevocation = generateRevocation(protector, revokeeSubKey, callback)
|
||||||
secretKeyRing = injectCertification(secretKeyRing, revokeeSubKey, subkeyRevocation)
|
secretKeyRing =
|
||||||
|
injectCertification(
|
||||||
|
secretKeyRing, revokeeSubKey.pgpPublicKey, subkeyRevocation.signature)
|
||||||
|
key = api.toKey(secretKeyRing)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,6 +453,7 @@ class SecretKeyRingEditor(
|
||||||
expiration: Date?,
|
expiration: Date?,
|
||||||
protector: SecretKeyRingProtector
|
protector: SecretKeyRingProtector
|
||||||
): SecretKeyRingEditorInterface {
|
): SecretKeyRingEditorInterface {
|
||||||
|
var secretKeyRing = key.pgpSecretKeyRing
|
||||||
require(secretKeyRing.secretKey.isMasterKey) {
|
require(secretKeyRing.secretKey.isMasterKey) {
|
||||||
"OpenPGP key does not appear to contain a primary secret key."
|
"OpenPGP key does not appear to contain a primary secret key."
|
||||||
}
|
}
|
||||||
|
@ -465,8 +468,9 @@ class SecretKeyRingEditor(
|
||||||
reissueDirectKeySignature(expiration, protector, prevDirectKeySig).signature)
|
reissueDirectKeySignature(expiration, protector, prevDirectKeySig).signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
val primaryUserId =
|
val info = api.inspect(key, referenceTime)
|
||||||
inspectKeyRing(secretKeyRing, referenceTime).getPossiblyExpiredPrimaryUserId()
|
|
||||||
|
val primaryUserId = info.getPossiblyExpiredPrimaryUserId()
|
||||||
if (primaryUserId != null) {
|
if (primaryUserId != null) {
|
||||||
val prevUserIdSig = getPreviousUserIdSignatures(primaryUserId)
|
val prevUserIdSig = getPreviousUserIdSignatures(primaryUserId)
|
||||||
val userIdSig =
|
val userIdSig =
|
||||||
|
@ -474,7 +478,6 @@ class SecretKeyRingEditor(
|
||||||
secretKeyRing = injectCertification(secretKeyRing, primaryUserId, userIdSig)
|
secretKeyRing = injectCertification(secretKeyRing, primaryUserId, userIdSig)
|
||||||
}
|
}
|
||||||
|
|
||||||
val info = inspectKeyRing(secretKeyRing, referenceTime)
|
|
||||||
for (userId in info.validUserIds) {
|
for (userId in info.validUserIds) {
|
||||||
if (userId == primaryUserId) {
|
if (userId == primaryUserId) {
|
||||||
continue
|
continue
|
||||||
|
@ -493,35 +496,40 @@ class SecretKeyRingEditor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
key = api.toKey(secretKeyRing)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setExpirationDateOfSubkey(
|
override fun setExpirationDateOfSubkey(
|
||||||
expiration: Date?,
|
expiration: Date?,
|
||||||
keyId: Long,
|
keyId: KeyIdentifier,
|
||||||
protector: SecretKeyRingProtector
|
protector: SecretKeyRingProtector
|
||||||
): SecretKeyRingEditorInterface = apply {
|
): SecretKeyRingEditorInterface = apply {
|
||||||
|
var secretKeyRing = key.pgpSecretKeyRing
|
||||||
|
|
||||||
// is primary key
|
// is primary key
|
||||||
if (keyId == secretKeyRing.publicKey.keyID) {
|
if (keyId.matches(key.keyIdentifier)) {
|
||||||
return setExpirationDate(expiration, protector)
|
return setExpirationDate(expiration, protector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// is subkey
|
// is subkey
|
||||||
val subkey =
|
val subkey =
|
||||||
secretKeyRing.getPublicKey(keyId)
|
key.getKey(keyId) ?: throw NoSuchElementException("No subkey with ID $keyId found.")
|
||||||
?: throw NoSuchElementException("No subkey with ID ${keyId.openPgpKeyId()} found.")
|
|
||||||
val prevBinding =
|
val prevBinding =
|
||||||
inspectKeyRing(secretKeyRing).getCurrentSubkeyBindingSignature(keyId)
|
api.inspect(key).getCurrentSubkeyBindingSignature(keyId)
|
||||||
?: throw NoSuchElementException(
|
?: 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)
|
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(
|
override fun createMinimalRevocationCertificate(
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revocationAttributes: RevocationAttributes?
|
revocationAttributes: RevocationAttributes?
|
||||||
): PGPPublicKeyRing {
|
): OpenPGPCertificate {
|
||||||
// Check reason
|
// Check reason
|
||||||
if (revocationAttributes != null) {
|
if (revocationAttributes != null) {
|
||||||
require(RevocationAttributes.Reason.isKeyRevocation(revocationAttributes.reason)) {
|
require(RevocationAttributes.Reason.isKeyRevocation(revocationAttributes.reason)) {
|
||||||
|
@ -530,49 +538,47 @@ class SecretKeyRingEditor(
|
||||||
}
|
}
|
||||||
|
|
||||||
val revocation = createRevocation(protector, revocationAttributes)
|
val revocation = createRevocation(protector, revocationAttributes)
|
||||||
var primaryKey = secretKeyRing.secretKey.publicKey
|
var primaryKey = key.primaryKey.pgpPublicKey
|
||||||
primaryKey = KeyRingUtils.getStrippedDownPublicKey(primaryKey)
|
primaryKey = KeyRingUtils.getStrippedDownPublicKey(primaryKey)
|
||||||
primaryKey = PGPPublicKey.addCertification(primaryKey, revocation)
|
primaryKey = PGPPublicKey.addCertification(primaryKey, revocation.signature)
|
||||||
return PGPPublicKeyRing(listOf(primaryKey))
|
return api.toCertificate(PGPPublicKeyRing(listOf(primaryKey)))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createRevocation(
|
override fun createRevocation(
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revocationAttributes: RevocationAttributes?
|
revocationAttributes: RevocationAttributes?
|
||||||
): PGPSignature {
|
): OpenPGPSignature {
|
||||||
return generateRevocation(
|
return generateRevocation(
|
||||||
protector,
|
protector, key.primaryKey, callbackFromRevocationAttributes(revocationAttributes))
|
||||||
secretKeyRing.publicKey,
|
|
||||||
callbackFromRevocationAttributes(revocationAttributes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createRevocation(
|
override fun createRevocation(
|
||||||
subkeyId: Long,
|
subkeyIdentifier: KeyIdentifier,
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revocationAttributes: RevocationAttributes?
|
revocationAttributes: RevocationAttributes?
|
||||||
): PGPSignature {
|
): OpenPGPSignature {
|
||||||
return generateRevocation(
|
return generateRevocation(
|
||||||
protector,
|
protector,
|
||||||
secretKeyRing.requirePublicKey(subkeyId),
|
key.getKey(subkeyIdentifier),
|
||||||
callbackFromRevocationAttributes(revocationAttributes))
|
callbackFromRevocationAttributes(revocationAttributes))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createRevocation(
|
override fun createRevocation(
|
||||||
subkeyId: Long,
|
subkeyIdentifier: KeyIdentifier,
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
callback: RevocationSignatureSubpackets.Callback?
|
callback: RevocationSignatureSubpackets.Callback?
|
||||||
): PGPSignature {
|
): OpenPGPSignature {
|
||||||
return generateRevocation(protector, secretKeyRing.requirePublicKey(subkeyId), callback)
|
return generateRevocation(protector, key.getKey(subkeyIdentifier), callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createRevocation(
|
override fun createRevocation(
|
||||||
subkeyFingerprint: OpenPgpFingerprint,
|
subkeyFingerprint: OpenPgpFingerprint,
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revocationAttributes: RevocationAttributes?
|
revocationAttributes: RevocationAttributes?
|
||||||
): PGPSignature {
|
): OpenPGPSignature {
|
||||||
return generateRevocation(
|
return generateRevocation(
|
||||||
protector,
|
protector,
|
||||||
secretKeyRing.requirePublicKey(subkeyFingerprint),
|
key.getKey(subkeyFingerprint.keyIdentifier),
|
||||||
callbackFromRevocationAttributes(revocationAttributes))
|
callbackFromRevocationAttributes(revocationAttributes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,8 +605,8 @@ class SecretKeyRingEditor(
|
||||||
mapOf(keyIdentifier to oldPassphrase), oldProtectionSettings, null))
|
mapOf(keyIdentifier to oldPassphrase), oldProtectionSettings, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun done(): PGPSecretKeyRing {
|
override fun done(): OpenPGPKey {
|
||||||
return secretKeyRing
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sanitizeUserId(userId: CharSequence): CharSequence =
|
private fun sanitizeUserId(userId: CharSequence): CharSequence =
|
||||||
|
@ -619,11 +625,11 @@ class SecretKeyRingEditor(
|
||||||
|
|
||||||
private fun generateRevocation(
|
private fun generateRevocation(
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revokeeSubkey: PGPPublicKey,
|
revokeeSubkey: OpenPGPComponentKey,
|
||||||
callback: RevocationSignatureSubpackets.Callback?
|
callback: RevocationSignatureSubpackets.Callback?
|
||||||
): PGPSignature {
|
): OpenPGPSignature {
|
||||||
val signatureType =
|
val signatureType =
|
||||||
if (revokeeSubkey.isMasterKey) SignatureType.KEY_REVOCATION
|
if (revokeeSubkey.isPrimaryKey) SignatureType.KEY_REVOCATION
|
||||||
else SignatureType.SUBKEY_REVOCATION
|
else SignatureType.SUBKEY_REVOCATION
|
||||||
|
|
||||||
return RevocationSignatureBuilder(signatureType, key.primarySecretKey, protector, api)
|
return RevocationSignatureBuilder(signatureType, key.primarySecretKey, protector, api)
|
||||||
|
@ -643,19 +649,20 @@ class SecretKeyRingEditor(
|
||||||
applyCallback(callback)
|
applyCallback(callback)
|
||||||
}
|
}
|
||||||
.let {
|
.let {
|
||||||
secretKeyRing =
|
val secretKeyRing =
|
||||||
injectCertification(secretKeyRing, userId, it.build(userId.toString()))
|
injectCertification(key.pgpSecretKeyRing, userId, it.build(userId.toString()))
|
||||||
|
key = api.toKey(secretKeyRing)
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPreviousDirectKeySignature(): PGPSignature? {
|
private fun getPreviousDirectKeySignature(): PGPSignature? {
|
||||||
val info = inspectKeyRing(secretKeyRing, referenceTime)
|
val info = api.inspect(key, referenceTime)
|
||||||
return info.latestDirectKeySelfSignature
|
return info.latestDirectKeySelfSignature
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPreviousUserIdSignatures(userId: String): PGPSignature? {
|
private fun getPreviousUserIdSignatures(userId: String): PGPSignature? {
|
||||||
val info = inspectKeyRing(secretKeyRing, referenceTime)
|
val info = api.inspect(key, referenceTime)
|
||||||
return info.getLatestUserIdCertification(userId)
|
return info.getLatestUserIdCertification(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,7 +703,7 @@ class SecretKeyRingEditor(
|
||||||
) {
|
) {
|
||||||
if (expiration != null) {
|
if (expiration != null) {
|
||||||
hashedSubpackets.setKeyExpirationTime(
|
hashedSubpackets.setKeyExpirationTime(
|
||||||
true, secretKeyRing.publicKey.creationTime, expiration)
|
true, key.primaryKey.creationTime, expiration)
|
||||||
} else {
|
} else {
|
||||||
hashedSubpackets.setKeyExpirationTime(KeyExpirationTime(true, 0))
|
hashedSubpackets.setKeyExpirationTime(KeyExpirationTime(true, 0))
|
||||||
}
|
}
|
||||||
|
@ -713,6 +720,7 @@ class SecretKeyRingEditor(
|
||||||
secretKeyRingProtector: SecretKeyRingProtector,
|
secretKeyRingProtector: SecretKeyRingProtector,
|
||||||
prevDirectKeySig: PGPSignature
|
prevDirectKeySig: PGPSignature
|
||||||
): OpenPGPSignature {
|
): OpenPGPSignature {
|
||||||
|
val secretKeyRing = key.pgpSecretKeyRing
|
||||||
return DirectKeySelfSignatureBuilder(
|
return DirectKeySelfSignatureBuilder(
|
||||||
secretKeyRing, secretKeyRingProtector, prevDirectKeySig, api)
|
secretKeyRing, secretKeyRingProtector, prevDirectKeySig, api)
|
||||||
.apply {
|
.apply {
|
||||||
|
@ -735,13 +743,13 @@ class SecretKeyRingEditor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun reissueSubkeyBindingSignature(
|
private fun reissueSubkeyBindingSignature(
|
||||||
subkey: PGPPublicKey,
|
subkey: OpenPGPComponentKey,
|
||||||
expiration: Date?,
|
expiration: Date?,
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
prevSubkeyBindingSignature: PGPSignature
|
prevSubkeyBindingSignature: PGPSignature
|
||||||
): PGPSignature {
|
): OpenPGPSignature {
|
||||||
val primaryKey = secretKeyRing.publicKey
|
val primaryKey = key.primaryKey
|
||||||
val secretSubkey: PGPSecretKey? = secretKeyRing.getSecretKey(subkey.keyID)
|
val secretSubkey: OpenPGPSecretKey? = key.getSecretKey(subkey)
|
||||||
|
|
||||||
val builder =
|
val builder =
|
||||||
SubkeyBindingSignatureBuilder(
|
SubkeyBindingSignatureBuilder(
|
||||||
|
@ -749,7 +757,7 @@ class SecretKeyRingEditor(
|
||||||
builder.hashedSubpackets.apply {
|
builder.hashedSubpackets.apply {
|
||||||
// set expiration
|
// set expiration
|
||||||
setSignatureCreationTime(referenceTime)
|
setSignatureCreationTime(referenceTime)
|
||||||
setKeyExpirationTime(subkey, expiration)
|
setKeyExpirationTime(subkey.pgpPublicKey, expiration)
|
||||||
setSignatureExpirationTime(null) // avoid copying sig exp time
|
setSignatureExpirationTime(null) // avoid copying sig exp time
|
||||||
|
|
||||||
// signing-capable subkeys need embedded primary key binding sig
|
// signing-capable subkeys need embedded primary key binding sig
|
||||||
|
@ -758,7 +766,7 @@ class SecretKeyRingEditor(
|
||||||
if (secretSubkey == null) {
|
if (secretSubkey == null) {
|
||||||
throw NoSuchElementException(
|
throw NoSuchElementException(
|
||||||
"Secret key does not contain secret-key" +
|
"Secret key does not contain secret-key" +
|
||||||
" component for subkey ${subkey.keyID.openPgpKeyId()}")
|
" component for subkey ${subkey.keyIdentifier}")
|
||||||
}
|
}
|
||||||
|
|
||||||
// create new embedded back-sig
|
// create new embedded back-sig
|
||||||
|
@ -766,7 +774,8 @@ class SecretKeyRingEditor(
|
||||||
addEmbeddedSignature(
|
addEmbeddedSignature(
|
||||||
PrimaryKeyBindingSignatureBuilder(
|
PrimaryKeyBindingSignatureBuilder(
|
||||||
key.getSecretKey(subkey.keyIdentifier), protector, api)
|
key.getSecretKey(subkey.keyIdentifier), protector, api)
|
||||||
.build(primaryKey))
|
.build(primaryKey)
|
||||||
|
.signature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -775,7 +784,7 @@ class SecretKeyRingEditor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun selectUserIds(predicate: Predicate<String>): List<String> =
|
private fun selectUserIds(predicate: Predicate<String>): List<String> =
|
||||||
inspectKeyRing(secretKeyRing).validUserIds.filter { predicate.test(it) }
|
key.validUserIds.map { it.userId }.filter { predicate.test(it) }.toList()
|
||||||
|
|
||||||
private class WithKeyRingEncryptionSettingsImpl(
|
private class WithKeyRingEncryptionSettingsImpl(
|
||||||
private val editor: SecretKeyRingEditor,
|
private val editor: SecretKeyRingEditor,
|
||||||
|
@ -805,15 +814,17 @@ class SecretKeyRingEditor(
|
||||||
val protector =
|
val protector =
|
||||||
PasswordBasedSecretKeyRingProtector(
|
PasswordBasedSecretKeyRingProtector(
|
||||||
newProtectionSettings, SolitaryPassphraseProvider(passphrase))
|
newProtectionSettings, SolitaryPassphraseProvider(passphrase))
|
||||||
val secretKeys = changePassphrase(keyId, editor.secretKeyRing, oldProtector, protector)
|
val secretKeys =
|
||||||
editor.secretKeyRing = secretKeys
|
changePassphrase(keyId, editor.key.pgpSecretKeyRing, oldProtector, protector)
|
||||||
|
editor.key = editor.api.toKey(secretKeys)
|
||||||
return editor
|
return editor
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toNoPassphrase(): SecretKeyRingEditorInterface {
|
override fun toNoPassphrase(): SecretKeyRingEditorInterface {
|
||||||
val protector = UnprotectedKeysProtector()
|
val protector = UnprotectedKeysProtector()
|
||||||
val secretKeys = changePassphrase(keyId, editor.secretKeyRing, oldProtector, protector)
|
val secretKeys =
|
||||||
editor.secretKeyRing = secretKeys
|
changePassphrase(keyId, editor.key.pgpSecretKeyRing, oldProtector, protector)
|
||||||
|
editor.key = editor.api.toKey(secretKeys)
|
||||||
return editor
|
return editor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,9 @@ import java.security.NoSuchAlgorithmException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import org.bouncycastle.bcpg.KeyIdentifier
|
import org.bouncycastle.bcpg.KeyIdentifier
|
||||||
import org.bouncycastle.openpgp.*
|
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.algorithm.KeyFlag
|
||||||
import org.pgpainless.key.OpenPgpFingerprint
|
import org.pgpainless.key.OpenPgpFingerprint
|
||||||
import org.pgpainless.key.generation.KeySpec
|
import org.pgpainless.key.generation.KeySpec
|
||||||
|
@ -262,26 +265,37 @@ interface SecretKeyRingEditorInterface {
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revocationAttributes: RevocationAttributes? = null
|
revocationAttributes: RevocationAttributes? = null
|
||||||
): SecretKeyRingEditorInterface =
|
): 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
|
* 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.
|
* 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 protector protector to unlock the primary key
|
||||||
* @return the builder
|
* @return the builder
|
||||||
* @throws PGPException in case we cannot generate a revocation signature for the subkey
|
* @throws PGPException in case we cannot generate a revocation signature for the subkey
|
||||||
*/
|
*/
|
||||||
@Throws(PGPException::class)
|
@Throws(PGPException::class)
|
||||||
fun revokeSubKey(subkeyId: Long, protector: SecretKeyRingProtector) =
|
fun revokeSubKey(subkeyIdentifier: KeyIdentifier, protector: SecretKeyRingProtector) =
|
||||||
revokeSubKey(subkeyId, protector, null as RevocationAttributes?)
|
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
|
* 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.
|
* 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 protector protector to unlock the primary key
|
||||||
* @param revocationAttributes reason for the revocation
|
* @param revocationAttributes reason for the revocation
|
||||||
* @return the builder
|
* @return the builder
|
||||||
|
@ -289,18 +303,25 @@ interface SecretKeyRingEditorInterface {
|
||||||
*/
|
*/
|
||||||
@Throws(PGPException::class)
|
@Throws(PGPException::class)
|
||||||
fun revokeSubKey(
|
fun revokeSubKey(
|
||||||
subkeyId: Long,
|
subkeyIdentifier: KeyIdentifier,
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revocationAttributes: RevocationAttributes? = null
|
revocationAttributes: RevocationAttributes? = null
|
||||||
): SecretKeyRingEditorInterface
|
): 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
|
* 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.
|
* revoked. If no suitable subkey is found, a [NoSuchElementException] will be thrown.
|
||||||
*
|
*
|
||||||
* The provided subpackets callback is used to modify the revocation signatures subpackets.
|
* 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 protector protector to unlock the secret key ring
|
||||||
* @param callback callback which can be used to modify the subpackets of the revocation
|
* @param callback callback which can be used to modify the subpackets of the revocation
|
||||||
* signature
|
* signature
|
||||||
|
@ -309,7 +330,7 @@ interface SecretKeyRingEditorInterface {
|
||||||
*/
|
*/
|
||||||
@Throws(PGPException::class)
|
@Throws(PGPException::class)
|
||||||
fun revokeSubKey(
|
fun revokeSubKey(
|
||||||
subkeyId: Long,
|
subkeyIdentifier: KeyIdentifier,
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
callback: RevocationSignatureSubpackets.Callback?
|
callback: RevocationSignatureSubpackets.Callback?
|
||||||
): SecretKeyRingEditorInterface
|
): SecretKeyRingEditorInterface
|
||||||
|
@ -470,6 +491,14 @@ interface SecretKeyRingEditorInterface {
|
||||||
protector: SecretKeyRingProtector
|
protector: SecretKeyRingProtector
|
||||||
): SecretKeyRingEditorInterface
|
): 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
|
* 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.
|
* 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)
|
@Throws(PGPException::class)
|
||||||
fun setExpirationDateOfSubkey(
|
fun setExpirationDateOfSubkey(
|
||||||
expiration: Date?,
|
expiration: Date?,
|
||||||
keyId: Long,
|
keyId: KeyIdentifier,
|
||||||
protector: SecretKeyRingProtector
|
protector: SecretKeyRingProtector
|
||||||
): SecretKeyRingEditorInterface
|
): SecretKeyRingEditorInterface
|
||||||
|
|
||||||
|
@ -502,7 +531,7 @@ interface SecretKeyRingEditorInterface {
|
||||||
fun createMinimalRevocationCertificate(
|
fun createMinimalRevocationCertificate(
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revocationAttributes: RevocationAttributes?
|
revocationAttributes: RevocationAttributes?
|
||||||
): PGPPublicKeyRing
|
): OpenPGPCertificate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a detached revocation certificate, which can be used to revoke the whole key. The
|
* Create a detached revocation certificate, which can be used to revoke the whole key. The
|
||||||
|
@ -517,13 +546,21 @@ interface SecretKeyRingEditorInterface {
|
||||||
fun createRevocation(
|
fun createRevocation(
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revocationAttributes: RevocationAttributes?
|
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.
|
* Create a detached revocation certificate, which can be used to revoke the specified subkey.
|
||||||
* The original key will not be modified by this method.
|
* 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 protector protector to unlock the primary key.
|
||||||
* @param revocationAttributes reason for the revocation
|
* @param revocationAttributes reason for the revocation
|
||||||
* @return revocation certificate
|
* @return revocation certificate
|
||||||
|
@ -531,16 +568,24 @@ interface SecretKeyRingEditorInterface {
|
||||||
*/
|
*/
|
||||||
@Throws(PGPException::class)
|
@Throws(PGPException::class)
|
||||||
fun createRevocation(
|
fun createRevocation(
|
||||||
subkeyId: Long,
|
subkeyIdentifier: KeyIdentifier,
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revocationAttributes: RevocationAttributes?
|
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.
|
* Create a detached revocation certificate, which can be used to revoke the specified subkey.
|
||||||
* The original key will not be modified by this method.
|
* 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 protector protector to unlock the primary key.
|
||||||
* @param callback callback to modify the subpackets of the revocation certificate.
|
* @param callback callback to modify the subpackets of the revocation certificate.
|
||||||
* @return revocation certificate
|
* @return revocation certificate
|
||||||
|
@ -548,10 +593,10 @@ interface SecretKeyRingEditorInterface {
|
||||||
*/
|
*/
|
||||||
@Throws(PGPException::class)
|
@Throws(PGPException::class)
|
||||||
fun createRevocation(
|
fun createRevocation(
|
||||||
subkeyId: Long,
|
subkeyIdentifier: KeyIdentifier,
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
callback: RevocationSignatureSubpackets.Callback?
|
callback: RevocationSignatureSubpackets.Callback?
|
||||||
): PGPSignature
|
): OpenPGPSignature
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a detached revocation certificate, which can be used to revoke the specified subkey.
|
* Create a detached revocation certificate, which can be used to revoke the specified subkey.
|
||||||
|
@ -568,7 +613,7 @@ interface SecretKeyRingEditorInterface {
|
||||||
subkeyFingerprint: OpenPgpFingerprint,
|
subkeyFingerprint: OpenPgpFingerprint,
|
||||||
protector: SecretKeyRingProtector,
|
protector: SecretKeyRingProtector,
|
||||||
revocationAttributes: RevocationAttributes?
|
revocationAttributes: RevocationAttributes?
|
||||||
): PGPSignature
|
): OpenPGPSignature
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the passphrase of the whole key ring.
|
* Change the passphrase of the whole key ring.
|
||||||
|
@ -676,7 +721,7 @@ interface SecretKeyRingEditorInterface {
|
||||||
*
|
*
|
||||||
* @return the key
|
* @return the key
|
||||||
*/
|
*/
|
||||||
fun done(): PGPSecretKeyRing
|
fun done(): OpenPGPKey
|
||||||
|
|
||||||
fun addSubKey(
|
fun addSubKey(
|
||||||
keySpec: KeySpec,
|
keySpec: KeySpec,
|
||||||
|
|
|
@ -7,6 +7,7 @@ package org.pgpainless.key.protection
|
||||||
import org.bouncycastle.bcpg.KeyIdentifier
|
import org.bouncycastle.bcpg.KeyIdentifier
|
||||||
import org.bouncycastle.openpgp.PGPKeyRing
|
import org.bouncycastle.openpgp.PGPKeyRing
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey
|
import org.bouncycastle.openpgp.PGPSecretKey
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate
|
||||||
import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider
|
import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider
|
||||||
import org.pgpainless.util.Passphrase
|
import org.pgpainless.util.Passphrase
|
||||||
|
|
||||||
|
@ -32,6 +33,25 @@ class PasswordBasedSecretKeyRingProtector : BaseSecretKeyRingProtector {
|
||||||
) : super(passphraseProvider, settings)
|
) : super(passphraseProvider, settings)
|
||||||
|
|
||||||
companion object {
|
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
|
@JvmStatic
|
||||||
fun forKey(
|
fun forKey(
|
||||||
keyRing: PGPKeyRing,
|
keyRing: PGPKeyRing,
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.bouncycastle.openpgp.PGPSecretKey
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing
|
import org.bouncycastle.openpgp.PGPSecretKeyRing
|
||||||
import org.bouncycastle.openpgp.api.KeyPassphraseProvider
|
import org.bouncycastle.openpgp.api.KeyPassphraseProvider
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey
|
||||||
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor
|
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor
|
||||||
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor
|
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor
|
||||||
import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider
|
import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider
|
||||||
|
@ -105,6 +106,10 @@ interface SecretKeyRingProtector : KeyPassphraseProvider {
|
||||||
KeyRingProtectionSettings.secureDefaultSettings(),
|
KeyRingProtectionSettings.secureDefaultSettings(),
|
||||||
missingPassphraseCallback)
|
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.
|
* Use the provided passphrase to lock/unlock all keys in the provided key ring.
|
||||||
*
|
*
|
||||||
|
|
|
@ -8,6 +8,8 @@ import java.util.function.Predicate
|
||||||
import org.bouncycastle.openpgp.PGPException
|
import org.bouncycastle.openpgp.PGPException
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey
|
import org.bouncycastle.openpgp.PGPPublicKey
|
||||||
import org.bouncycastle.openpgp.PGPSignature
|
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.bouncycastle.openpgp.api.OpenPGPKey
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.algorithm.HashAlgorithm
|
import org.pgpainless.algorithm.HashAlgorithm
|
||||||
|
@ -63,4 +65,7 @@ class PrimaryKeyBindingSignatureBuilder :
|
||||||
fun build(primaryKey: PGPPublicKey): PGPSignature =
|
fun build(primaryKey: PGPPublicKey): PGPSignature =
|
||||||
buildAndInitSignatureGenerator()
|
buildAndInitSignatureGenerator()
|
||||||
.generateCertification(primaryKey, signingKey.publicKey.pgpPublicKey)
|
.generateCertification(primaryKey, signingKey.publicKey.pgpPublicKey)
|
||||||
|
|
||||||
|
fun build(primaryKey: OpenPGPPrimaryKey): OpenPGPComponentSignature =
|
||||||
|
OpenPGPComponentSignature(build(primaryKey.pgpPublicKey), primaryKey, primaryKey)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,11 @@ import java.util.function.Predicate
|
||||||
import org.bouncycastle.openpgp.PGPException
|
import org.bouncycastle.openpgp.PGPException
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey
|
import org.bouncycastle.openpgp.PGPPublicKey
|
||||||
import org.bouncycastle.openpgp.PGPSignature
|
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.OpenPGPKey
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPSignature
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.algorithm.SignatureType
|
import org.pgpainless.algorithm.SignatureType
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector
|
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)
|
@Throws(PGPException::class)
|
||||||
fun build(revokeeUserId: CharSequence): PGPSignature =
|
fun build(revokeeUserId: CharSequence): PGPSignature =
|
||||||
buildAndInitSignatureGenerator()
|
buildAndInitSignatureGenerator()
|
||||||
|
@ -69,6 +78,11 @@ constructor(
|
||||||
}
|
}
|
||||||
.generateCertification(revokeeUserId.toString(), signingKey.publicKey.pgpPublicKey)
|
.generateCertification(revokeeUserId.toString(), signingKey.publicKey.pgpPublicKey)
|
||||||
|
|
||||||
|
fun build(revokeeUserId: OpenPGPUserId): OpenPGPComponentSignature {
|
||||||
|
return OpenPGPComponentSignature(
|
||||||
|
build(revokeeUserId.userId), signingKey.publicKey, revokeeUserId)
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
hashedSubpackets.setRevocable(false)
|
hashedSubpackets.setRevocable(false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import java.util.function.Predicate
|
||||||
import org.bouncycastle.openpgp.PGPException
|
import org.bouncycastle.openpgp.PGPException
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey
|
import org.bouncycastle.openpgp.PGPPublicKey
|
||||||
import org.bouncycastle.openpgp.PGPSignature
|
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.bouncycastle.openpgp.api.OpenPGPKey
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.algorithm.HashAlgorithm
|
import org.pgpainless.algorithm.HashAlgorithm
|
||||||
|
@ -77,4 +79,7 @@ class SubkeyBindingSignatureBuilder : AbstractSignatureBuilder<SubkeyBindingSign
|
||||||
fun build(subkey: PGPPublicKey): PGPSignature =
|
fun build(subkey: PGPPublicKey): PGPSignature =
|
||||||
buildAndInitSignatureGenerator()
|
buildAndInitSignatureGenerator()
|
||||||
.generateCertification(signingKey.publicKey.pgpPublicKey, subkey)
|
.generateCertification(signingKey.publicKey.pgpPublicKey, subkey)
|
||||||
|
|
||||||
|
fun build(subkey: OpenPGPComponentKey): OpenPGPComponentSignature =
|
||||||
|
OpenPGPComponentSignature(build(subkey.pgpPublicKey), signingKey.publicKey, subkey)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ package org.pgpainless.util.selection.userid
|
||||||
|
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
import org.bouncycastle.openpgp.PGPKeyRing
|
import org.bouncycastle.openpgp.PGPKeyRing
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
|
|
||||||
abstract class SelectUserId : Predicate<String>, (String) -> Boolean {
|
abstract class SelectUserId : Predicate<String>, (String) -> Boolean {
|
||||||
|
@ -72,6 +73,14 @@ abstract class SelectUserId : Predicate<String>, (String) -> Boolean {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun byEmail(email: CharSequence) = or(exactMatch(email), containsEmailAddress(email))
|
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
|
@JvmStatic
|
||||||
fun validUserId(keyRing: PGPKeyRing) =
|
fun validUserId(keyRing: PGPKeyRing) =
|
||||||
object : SelectUserId() {
|
object : SelectUserId() {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.bouncycastle.util.io.Streams;
|
import org.bouncycastle.util.io.Streams;
|
||||||
import org.junit.jupiter.api.TestTemplate;
|
import org.junit.jupiter.api.TestTemplate;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
@ -130,16 +131,16 @@ public class SigningTest {
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void testSignWithRevokedUserIdFails()
|
public void testSignWithRevokedUserIdFails()
|
||||||
throws PGPException {
|
throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.modernKeyRing("alice", "password123")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.modernKeyRing("alice", "password123");
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAnyKeyWith(
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAnyKeyWith(
|
||||||
Passphrase.fromPassword("password123"));
|
Passphrase.fromPassword("password123"));
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.revokeUserId("alice", protector)
|
.revokeUserId("alice", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
final PGPSecretKeyRing fSecretKeys = secretKeys;
|
final OpenPGPKey fSecretKeys = secretKeys;
|
||||||
|
|
||||||
SigningOptions opts = SigningOptions.get();
|
SigningOptions opts = SigningOptions.get();
|
||||||
// "alice" has been revoked
|
// "alice" has been revoked
|
||||||
|
|
|
@ -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.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.KeyIdentifier;
|
import org.bouncycastle.bcpg.KeyIdentifier;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
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.OpenPGPCertificate;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
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.
|
* 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 {
|
public class ModifyKeys {
|
||||||
|
|
||||||
private final String userId = "alice@pgpainless.org";
|
private final String userId = "alice@pgpainless.org";
|
||||||
private final String originalPassphrase = "p4ssw0rd";
|
private final String originalPassphrase = "p4ssw0rd";
|
||||||
private PGPSecretKeyRing secretKey;
|
private OpenPGPKey secretKey;
|
||||||
private long primaryKeyId;
|
private KeyIdentifier primaryKeyId;
|
||||||
private KeyIdentifier encryptionSubkeyId;
|
private KeyIdentifier encryptionSubkeyId;
|
||||||
private KeyIdentifier signingSubkeyId;
|
private KeyIdentifier signingSubkeyId;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void generateKey() {
|
public void generateKey() {
|
||||||
secretKey = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.modernKeyRing(userId, originalPassphrase)
|
secretKey = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.modernKeyRing(userId, originalPassphrase);
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKey);
|
KeyRingInfo info = api.inspect(secretKey);
|
||||||
primaryKeyId = info.getKeyIdentifier().getKeyId();
|
primaryKeyId = info.getKeyIdentifier();
|
||||||
encryptionSubkeyId = info.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0).getKeyIdentifier();
|
encryptionSubkeyId = info.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0).getKeyIdentifier();
|
||||||
signingSubkeyId = info.getSigningSubkeys().get(0).getKeyIdentifier();
|
signingSubkeyId = info.getSigningSubkeys().get(0).getKeyIdentifier();
|
||||||
}
|
}
|
||||||
|
@ -63,9 +63,9 @@ public class ModifyKeys {
|
||||||
@Test
|
@Test
|
||||||
public void extractPublicKey() {
|
public void extractPublicKey() {
|
||||||
// the certificate consists of only the public keys
|
// 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());
|
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.
|
* This example demonstrates how to export a secret key or certificate to an ASCII armored string.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void toAsciiArmoredString() {
|
public void toAsciiArmoredString() throws IOException {
|
||||||
PGPPublicKeyRing certificate = PGPainless.extractCertificate(secretKey);
|
OpenPGPCertificate certificate = secretKey.toCertificate();
|
||||||
|
|
||||||
String asciiArmoredSecretKey = PGPainless.asciiArmor(secretKey);
|
String asciiArmoredSecretKey = secretKey.toAsciiArmoredString();
|
||||||
String asciiArmoredCertificate = PGPainless.asciiArmor(certificate);
|
String asciiArmoredCertificate = certificate.toAsciiArmoredString();
|
||||||
|
|
||||||
assertTrue(asciiArmoredSecretKey.startsWith("-----BEGIN PGP PRIVATE KEY BLOCK-----"));
|
assertTrue(asciiArmoredSecretKey.startsWith("-----BEGIN PGP PRIVATE KEY BLOCK-----"));
|
||||||
assertTrue(asciiArmoredCertificate.startsWith("-----BEGIN PGP PUBLIC KEY BLOCK-----"));
|
assertTrue(asciiArmoredCertificate.startsWith("-----BEGIN PGP PUBLIC KEY BLOCK-----"));
|
||||||
|
@ -88,7 +88,8 @@ public class ModifyKeys {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void changePassphrase() throws PGPException {
|
public void changePassphrase() throws PGPException {
|
||||||
secretKey = PGPainless.modifyKeyRing(secretKey)
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
secretKey = api.modify(secretKey)
|
||||||
.changePassphraseFromOldPassphrase(Passphrase.fromPassword(originalPassphrase))
|
.changePassphraseFromOldPassphrase(Passphrase.fromPassword(originalPassphrase))
|
||||||
.withSecureDefaultSettings()
|
.withSecureDefaultSettings()
|
||||||
.toNewPassphrase(Passphrase.fromPassword("n3wP4ssW0rD"))
|
.toNewPassphrase(Passphrase.fromPassword("n3wP4ssW0rD"))
|
||||||
|
@ -96,9 +97,9 @@ public class ModifyKeys {
|
||||||
|
|
||||||
// Old passphrase no longer works
|
// Old passphrase no longer works
|
||||||
assertThrows(WrongPassphraseException.class, () ->
|
assertThrows(WrongPassphraseException.class, () ->
|
||||||
UnlockSecretKey.unlockSecretKey(secretKey.getSecretKey(), Passphrase.fromPassword(originalPassphrase)));
|
UnlockSecretKey.unlockSecretKey(secretKey.getPGPSecretKeyRing().getSecretKey(), Passphrase.fromPassword(originalPassphrase)));
|
||||||
// But the new one does
|
// 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
|
@Test
|
||||||
public void changeSingleSubkeyPassphrase() throws PGPException {
|
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
|
// Here we change the passphrase of the encryption subkey
|
||||||
.changeSubKeyPassphraseFromOldPassphrase(encryptionSubkeyId.getKeyId(), Passphrase.fromPassword(originalPassphrase))
|
.changeSubKeyPassphraseFromOldPassphrase(encryptionSubkeyId, Passphrase.fromPassword(originalPassphrase))
|
||||||
.withSecureDefaultSettings()
|
.withSecureDefaultSettings()
|
||||||
.toNewPassphrase(Passphrase.fromPassword("cryptP4ssphr4s3"))
|
.toNewPassphrase(Passphrase.fromPassword("cryptP4ssphr4s3"))
|
||||||
.done();
|
.done();
|
||||||
|
@ -117,12 +119,12 @@ public class ModifyKeys {
|
||||||
// encryption key can now only be unlocked using the new passphrase
|
// encryption key can now only be unlocked using the new passphrase
|
||||||
assertThrows(WrongPassphraseException.class, () ->
|
assertThrows(WrongPassphraseException.class, () ->
|
||||||
UnlockSecretKey.unlockSecretKey(
|
UnlockSecretKey.unlockSecretKey(
|
||||||
secretKey.getSecretKey(encryptionSubkeyId), Passphrase.fromPassword(originalPassphrase)));
|
secretKey.getSecretKey(encryptionSubkeyId).getPGPSecretKey(), Passphrase.fromPassword(originalPassphrase)));
|
||||||
UnlockSecretKey.unlockSecretKey(
|
UnlockSecretKey.unlockSecretKey(
|
||||||
secretKey.getSecretKey(encryptionSubkeyId), Passphrase.fromPassword("cryptP4ssphr4s3"));
|
secretKey.getSecretKey(encryptionSubkeyId).getPGPSecretKey(), Passphrase.fromPassword("cryptP4ssphr4s3"));
|
||||||
// primary key remains unchanged
|
// primary key remains unchanged
|
||||||
UnlockSecretKey.unlockSecretKey(
|
UnlockSecretKey.unlockSecretKey(
|
||||||
secretKey.getSecretKey(primaryKeyId), Passphrase.fromPassword(originalPassphrase));
|
secretKey.getSecretKey(primaryKeyId).getPGPSecretKey(), Passphrase.fromPassword(originalPassphrase));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,13 +132,14 @@ public class ModifyKeys {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void addUserId() throws PGPException {
|
public void addUserId() throws PGPException {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
SecretKeyRingProtector protector =
|
SecretKeyRingProtector protector =
|
||||||
SecretKeyRingProtector.unlockEachKeyWith(Passphrase.fromPassword(originalPassphrase), secretKey);
|
SecretKeyRingProtector.unlockEachKeyWith(Passphrase.fromPassword(originalPassphrase), secretKey);
|
||||||
secretKey = PGPainless.modifyKeyRing(secretKey)
|
secretKey = api.modify(secretKey)
|
||||||
.addUserId("additional@user.id", protector)
|
.addUserId("additional@user.id", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKey);
|
KeyRingInfo info = api.inspect(secretKey);
|
||||||
assertTrue(info.isUserIdValid("additional@user.id"));
|
assertTrue(info.isUserIdValid("additional@user.id"));
|
||||||
assertFalse(info.isUserIdValid("another@user.id"));
|
assertFalse(info.isUserIdValid("another@user.id"));
|
||||||
}
|
}
|
||||||
|
@ -156,11 +159,12 @@ public class ModifyKeys {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void addSubkey() {
|
public void addSubkey() {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
// Protector for unlocking the existing secret key
|
// Protector for unlocking the existing secret key
|
||||||
SecretKeyRingProtector protector =
|
SecretKeyRingProtector protector =
|
||||||
SecretKeyRingProtector.unlockEachKeyWith(Passphrase.fromPassword(originalPassphrase), secretKey);
|
SecretKeyRingProtector.unlockEachKeyWith(Passphrase.fromPassword(originalPassphrase), secretKey);
|
||||||
Passphrase subkeyPassphrase = Passphrase.fromPassword("subk3yP4ssphr4s3");
|
Passphrase subkeyPassphrase = Passphrase.fromPassword("subk3yP4ssphr4s3");
|
||||||
secretKey = PGPainless.modifyKeyRing(secretKey)
|
secretKey = api.modify(secretKey)
|
||||||
.addSubKey(
|
.addSubKey(
|
||||||
KeySpec.getBuilder(KeyType.ECDH(EllipticCurve._BRAINPOOLP512R1), KeyFlag.ENCRYPT_COMMS)
|
KeySpec.getBuilder(KeyType.ECDH(EllipticCurve._BRAINPOOLP512R1), KeyFlag.ENCRYPT_COMMS)
|
||||||
.build(),
|
.build(),
|
||||||
|
@ -168,7 +172,7 @@ public class ModifyKeys {
|
||||||
protector)
|
protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKey);
|
KeyRingInfo info = api.inspect(secretKey);
|
||||||
assertEquals(4, info.getSecretKeys().size());
|
assertEquals(4, info.getSecretKeys().size());
|
||||||
assertEquals(4, info.getPublicKeys().size());
|
assertEquals(4, info.getPublicKeys().size());
|
||||||
List<OpenPGPCertificate.OpenPGPComponentKey> encryptionSubkeys = info.getEncryptionSubkeys(EncryptionPurpose.COMMUNICATIONS);
|
List<OpenPGPCertificate.OpenPGPComponentKey> encryptionSubkeys = info.getEncryptionSubkeys(EncryptionPurpose.COMMUNICATIONS);
|
||||||
|
@ -176,7 +180,7 @@ public class ModifyKeys {
|
||||||
OpenPGPCertificate.OpenPGPComponentKey addedKey = encryptionSubkeys.stream()
|
OpenPGPCertificate.OpenPGPComponentKey addedKey = encryptionSubkeys.stream()
|
||||||
.filter(it -> !it.getKeyIdentifier().matches(encryptionSubkeyId)).findFirst()
|
.filter(it -> !it.getKeyIdentifier().matches(encryptionSubkeyId)).findFirst()
|
||||||
.get();
|
.get();
|
||||||
UnlockSecretKey.unlockSecretKey(secretKey.getSecretKey(addedKey.getKeyIdentifier()), subkeyPassphrase);
|
UnlockSecretKey.unlockSecretKey(secretKey.getSecretKey(addedKey.getKeyIdentifier()).getPGPSecretKey(), subkeyPassphrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -185,15 +189,16 @@ public class ModifyKeys {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void setKeyExpirationDate() {
|
public void setKeyExpirationDate() {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
Date expirationDate = DateUtil.parseUTCDate("2030-06-24 12:44:56 UTC");
|
Date expirationDate = DateUtil.parseUTCDate("2030-06-24 12:44:56 UTC");
|
||||||
|
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector
|
SecretKeyRingProtector protector = SecretKeyRingProtector
|
||||||
.unlockEachKeyWith(Passphrase.fromPassword(originalPassphrase), secretKey);
|
.unlockEachKeyWith(Passphrase.fromPassword(originalPassphrase), secretKey);
|
||||||
secretKey = PGPainless.modifyKeyRing(secretKey)
|
secretKey = api.modify(secretKey)
|
||||||
.setExpirationDate(expirationDate, protector)
|
.setExpirationDate(expirationDate, protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKey);
|
KeyRingInfo info = api.inspect(secretKey);
|
||||||
assertEquals(DateUtil.formatUTCDate(expirationDate),
|
assertEquals(DateUtil.formatUTCDate(expirationDate),
|
||||||
DateUtil.formatUTCDate(info.getPrimaryKeyExpirationDate()));
|
DateUtil.formatUTCDate(info.getPrimaryKeyExpirationDate()));
|
||||||
assertEquals(DateUtil.formatUTCDate(expirationDate),
|
assertEquals(DateUtil.formatUTCDate(expirationDate),
|
||||||
|
@ -207,19 +212,20 @@ public class ModifyKeys {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void revokeUserId() throws PGPException {
|
public void revokeUserId() throws PGPException {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockEachKeyWith(
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockEachKeyWith(
|
||||||
Passphrase.fromPassword(originalPassphrase), secretKey);
|
Passphrase.fromPassword(originalPassphrase), secretKey);
|
||||||
secretKey = PGPainless.modifyKeyRing(secretKey)
|
secretKey = api.modify(secretKey)
|
||||||
.addUserId("alcie@pgpainless.org", protector)
|
.addUserId("alcie@pgpainless.org", protector)
|
||||||
.done();
|
.done();
|
||||||
// Initially the user-id is valid
|
// 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
|
// Revoke the second user-id
|
||||||
secretKey = PGPainless.modifyKeyRing(secretKey)
|
secretKey = api.modify(secretKey)
|
||||||
.revokeUserId("alcie@pgpainless.org", protector)
|
.revokeUserId("alcie@pgpainless.org", protector)
|
||||||
.done();
|
.done();
|
||||||
// Now the user-id is no longer valid
|
// Now the user-id is no longer valid
|
||||||
assertFalse(PGPainless.inspectKeyRing(secretKey).isUserIdValid("alcie@pgpainless.org"));
|
assertFalse(api.inspect(secretKey).isUserIdValid("alcie@pgpainless.org"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,11 @@ import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||||
import org.bouncycastle.openpgp.PGPUtil;
|
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.KeyFingerPrintCalculator;
|
||||||
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
|
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
|
||||||
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
|
|
||||||
public class TestKeys {
|
public class TestKeys {
|
||||||
|
@ -265,6 +268,10 @@ public class TestKeys {
|
||||||
"=1d67\n" +
|
"=1d67\n" +
|
||||||
"-----END PGP PRIVATE KEY BLOCK-----";
|
"-----END PGP PRIVATE KEY BLOCK-----";
|
||||||
|
|
||||||
|
public static OpenPGPKey getJulietKey() throws PGPException, IOException {
|
||||||
|
return PGPainless.getInstance().toKey(getJulietSecretKeyRing());
|
||||||
|
}
|
||||||
|
|
||||||
public static PGPSecretKeyRing getJulietSecretKeyRing() throws IOException, PGPException {
|
public static PGPSecretKeyRing getJulietSecretKeyRing() throws IOException, PGPException {
|
||||||
if (julietSecretKeyRing == null) {
|
if (julietSecretKeyRing == null) {
|
||||||
julietSecretKeyRing = new PGPSecretKeyRing(
|
julietSecretKeyRing = new PGPSecretKeyRing(
|
||||||
|
@ -281,6 +288,10 @@ public class TestKeys {
|
||||||
return julietSecretKeyRingCollection;
|
return julietSecretKeyRingCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OpenPGPCertificate getJulietCertificate() throws IOException {
|
||||||
|
return PGPainless.getInstance().toCertificate(getJulietPublicKeyRing());
|
||||||
|
}
|
||||||
|
|
||||||
public static PGPPublicKeyRing getJulietPublicKeyRing() throws IOException {
|
public static PGPPublicKeyRing getJulietPublicKeyRing() throws IOException {
|
||||||
if (julietPublicKeyRing == null) {
|
if (julietPublicKeyRing == null) {
|
||||||
julietPublicKeyRing = new PGPPublicKeyRing(
|
julietPublicKeyRing = new PGPPublicKeyRing(
|
||||||
|
@ -297,6 +308,10 @@ public class TestKeys {
|
||||||
return julietPublicKeyRingCollection;
|
return julietPublicKeyRingCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OpenPGPKey getRomeoKey() throws PGPException, IOException {
|
||||||
|
return PGPainless.getInstance().toKey(getRomeoSecretKeyRing());
|
||||||
|
}
|
||||||
|
|
||||||
public static PGPSecretKeyRing getRomeoSecretKeyRing() throws IOException, PGPException {
|
public static PGPSecretKeyRing getRomeoSecretKeyRing() throws IOException, PGPException {
|
||||||
if (romeoSecretKeyRing == null) {
|
if (romeoSecretKeyRing == null) {
|
||||||
romeoSecretKeyRing = new PGPSecretKeyRing(
|
romeoSecretKeyRing = new PGPSecretKeyRing(
|
||||||
|
@ -313,6 +328,10 @@ public class TestKeys {
|
||||||
return romeoSecretKeyRingCollection;
|
return romeoSecretKeyRingCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OpenPGPCertificate getRomeoCertificate() throws IOException {
|
||||||
|
return PGPainless.getInstance().toCertificate(getRomeoPublicKeyRing());
|
||||||
|
}
|
||||||
|
|
||||||
public static PGPPublicKeyRing getRomeoPublicKeyRing() throws IOException {
|
public static PGPPublicKeyRing getRomeoPublicKeyRing() throws IOException {
|
||||||
if (romeoPublicKeyRing == null) {
|
if (romeoPublicKeyRing == null) {
|
||||||
romeoPublicKeyRing = new PGPPublicKeyRing(
|
romeoPublicKeyRing = new PGPPublicKeyRing(
|
||||||
|
@ -329,6 +348,10 @@ public class TestKeys {
|
||||||
return romeoPublicKeyRingCollection;
|
return romeoPublicKeyRingCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OpenPGPKey getEmilKey() throws PGPException, IOException {
|
||||||
|
return PGPainless.getInstance().toKey(getEmilSecretKeyRing());
|
||||||
|
}
|
||||||
|
|
||||||
public static PGPSecretKeyRing getEmilSecretKeyRing() throws IOException, PGPException {
|
public static PGPSecretKeyRing getEmilSecretKeyRing() throws IOException, PGPException {
|
||||||
if (emilSecretKeyRing == null) {
|
if (emilSecretKeyRing == null) {
|
||||||
emilSecretKeyRing = new PGPSecretKeyRing(
|
emilSecretKeyRing = new PGPSecretKeyRing(
|
||||||
|
@ -345,6 +368,10 @@ public class TestKeys {
|
||||||
return emilSecretKeyRingCollection;
|
return emilSecretKeyRingCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OpenPGPCertificate getEmilCertificate() throws IOException {
|
||||||
|
return PGPainless.getInstance().toCertificate(getEmilPublicKeyRing());
|
||||||
|
}
|
||||||
|
|
||||||
public static PGPPublicKeyRing getEmilPublicKeyRing() throws IOException {
|
public static PGPPublicKeyRing getEmilPublicKeyRing() throws IOException {
|
||||||
if (emilPublicKeyRing == null) {
|
if (emilPublicKeyRing == null) {
|
||||||
emilPublicKeyRing = new PGPPublicKeyRing(
|
emilPublicKeyRing = new PGPPublicKeyRing(
|
||||||
|
@ -361,6 +388,10 @@ public class TestKeys {
|
||||||
return emilPublicKeyRingCollection;
|
return emilPublicKeyRingCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OpenPGPKey getCryptieKey() throws PGPException, IOException {
|
||||||
|
return PGPainless.getInstance().toKey(getCryptieSecretKeyRing());
|
||||||
|
}
|
||||||
|
|
||||||
public static PGPSecretKeyRing getCryptieSecretKeyRing() throws IOException, PGPException {
|
public static PGPSecretKeyRing getCryptieSecretKeyRing() throws IOException, PGPException {
|
||||||
if (cryptieSecretKeyRing == null) {
|
if (cryptieSecretKeyRing == null) {
|
||||||
cryptieSecretKeyRing = new PGPSecretKeyRing(
|
cryptieSecretKeyRing = new PGPSecretKeyRing(
|
||||||
|
@ -377,6 +408,10 @@ public class TestKeys {
|
||||||
return cryptieSecretKeyRingCollection;
|
return cryptieSecretKeyRingCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OpenPGPCertificate getCryptieCertificate() throws IOException {
|
||||||
|
return PGPainless.getInstance().toCertificate(getCryptiePublicKeyRing());
|
||||||
|
}
|
||||||
|
|
||||||
public static PGPPublicKeyRing getCryptiePublicKeyRing() throws IOException {
|
public static PGPPublicKeyRing getCryptiePublicKeyRing() throws IOException {
|
||||||
if (cryptiePublicKeyRing == null) {
|
if (cryptiePublicKeyRing == null) {
|
||||||
cryptiePublicKeyRing = new PGPPublicKeyRing(
|
cryptiePublicKeyRing = new PGPPublicKeyRing(
|
||||||
|
|
|
@ -18,10 +18,10 @@ import java.util.List;
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.sig.IssuerFingerprint;
|
import org.bouncycastle.bcpg.sig.IssuerFingerprint;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.algorithm.HashAlgorithm;
|
import org.pgpainless.algorithm.HashAlgorithm;
|
||||||
|
@ -39,10 +39,10 @@ public class KeyGenerationSubpacketsTest {
|
||||||
@Test
|
@Test
|
||||||
public void verifyDefaultSubpacketsForUserIdSignatures()
|
public void verifyDefaultSubpacketsForUserIdSignatures()
|
||||||
throws PGPException {
|
throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice");
|
||||||
Date plus1Sec = new Date(secretKeys.getPublicKey().getCreationTime().getTime() + 1000);
|
Date plus1Sec = new Date(secretKeys.getPrimarySecretKey().getCreationTime().getTime() + 1000);
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
PGPSignature userIdSig = info.getLatestUserIdCertification("Alice");
|
PGPSignature userIdSig = info.getLatestUserIdCertification("Alice");
|
||||||
assertNotNull(userIdSig);
|
assertNotNull(userIdSig);
|
||||||
int keyFlags = userIdSig.getHashedSubPackets().getKeyFlags();
|
int keyFlags = userIdSig.getHashedSubPackets().getKeyFlags();
|
||||||
|
@ -54,7 +54,7 @@ public class KeyGenerationSubpacketsTest {
|
||||||
|
|
||||||
assertEquals("Alice", info.getPrimaryUserId());
|
assertEquals("Alice", info.getPrimaryUserId());
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, plus1Sec)
|
secretKeys = api.modify(secretKeys, plus1Sec)
|
||||||
.addUserId("Bob",
|
.addUserId("Bob",
|
||||||
new SelfSignatureSubpackets.Callback() {
|
new SelfSignatureSubpackets.Callback() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,7 +66,7 @@ public class KeyGenerationSubpacketsTest {
|
||||||
.addUserId("Alice", SecretKeyRingProtector.unprotectedKeys())
|
.addUserId("Alice", SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, plus1Sec);
|
info = api.inspect(secretKeys, plus1Sec);
|
||||||
|
|
||||||
userIdSig = info.getLatestUserIdCertification("Alice");
|
userIdSig = info.getLatestUserIdCertification("Alice");
|
||||||
assertNotNull(userIdSig);
|
assertNotNull(userIdSig);
|
||||||
|
@ -89,7 +89,7 @@ public class KeyGenerationSubpacketsTest {
|
||||||
|
|
||||||
Date now = plus1Sec;
|
Date now = plus1Sec;
|
||||||
Date t1 = new Date(now.getTime() + 1000 * 60 * 60);
|
Date t1 = new Date(now.getTime() + 1000 * 60 * 60);
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, t1)
|
secretKeys = api.modify(secretKeys, t1)
|
||||||
.addUserId("Alice", new SelfSignatureSubpackets.Callback() {
|
.addUserId("Alice", new SelfSignatureSubpackets.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
||||||
|
@ -98,7 +98,7 @@ public class KeyGenerationSubpacketsTest {
|
||||||
}
|
}
|
||||||
}, SecretKeyRingProtector.unprotectedKeys())
|
}, SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, t1);
|
info = api.inspect(secretKeys, t1);
|
||||||
assertEquals("Alice", info.getPrimaryUserId());
|
assertEquals("Alice", info.getPrimaryUserId());
|
||||||
assertEquals(Collections.singleton(HashAlgorithm.SHA1), info.getPreferredHashAlgorithms("Alice"));
|
assertEquals(Collections.singleton(HashAlgorithm.SHA1), info.getPreferredHashAlgorithms("Alice"));
|
||||||
}
|
}
|
||||||
|
@ -106,29 +106,29 @@ public class KeyGenerationSubpacketsTest {
|
||||||
@Test
|
@Test
|
||||||
public void verifyDefaultSubpacketsForSubkeyBindingSignatures()
|
public void verifyDefaultSubpacketsForSubkeyBindingSignatures()
|
||||||
throws PGPException {
|
throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice");
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
List<OpenPGPCertificate.OpenPGPComponentKey> keysBefore = info.getPublicKeys();
|
List<OpenPGPCertificate.OpenPGPComponentKey> keysBefore = info.getPublicKeys();
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.addSubKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.SIGN_DATA).build(),
|
.addSubKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.SIGN_DATA).build(),
|
||||||
Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys())
|
Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys);
|
info = api.inspect(secretKeys);
|
||||||
List<OpenPGPCertificate.OpenPGPComponentKey> keysAfter = new ArrayList<>(info.getPublicKeys());
|
List<OpenPGPCertificate.OpenPGPComponentKey> keysAfter = new ArrayList<>(info.getPublicKeys());
|
||||||
keysAfter.removeAll(keysBefore);
|
keysAfter.removeAll(keysBefore);
|
||||||
assertEquals(1, keysAfter.size());
|
assertEquals(1, keysAfter.size());
|
||||||
OpenPGPCertificate.OpenPGPComponentKey newSigningKey = keysAfter.get(0);
|
OpenPGPCertificate.OpenPGPComponentKey newSigningKey = keysAfter.get(0);
|
||||||
|
|
||||||
PGPSignature bindingSig = info.getCurrentSubkeyBindingSignature(newSigningKey.getKeyIdentifier().getKeyId());
|
PGPSignature bindingSig = info.getCurrentSubkeyBindingSignature(newSigningKey.getKeyIdentifier());
|
||||||
assertNotNull(bindingSig);
|
assertNotNull(bindingSig);
|
||||||
assureSignatureHasDefaultSubpackets(bindingSig, secretKeys, KeyFlag.SIGN_DATA);
|
assureSignatureHasDefaultSubpackets(bindingSig, secretKeys, KeyFlag.SIGN_DATA);
|
||||||
assertNotNull(bindingSig.getHashedSubPackets().getEmbeddedSignatures().get(0));
|
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(),
|
.addSubKey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS).build(),
|
||||||
Passphrase.emptyPassphrase(),
|
Passphrase.emptyPassphrase(),
|
||||||
new SelfSignatureSubpackets.Callback() {
|
new SelfSignatureSubpackets.Callback() {
|
||||||
|
@ -139,24 +139,24 @@ public class KeyGenerationSubpacketsTest {
|
||||||
}, SecretKeyRingProtector.unprotectedKeys())
|
}, SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys);
|
info = api.inspect(secretKeys);
|
||||||
keysAfter = new ArrayList<>(info.getPublicKeys());
|
keysAfter = new ArrayList<>(info.getPublicKeys());
|
||||||
keysAfter.removeAll(keysBefore);
|
keysAfter.removeAll(keysBefore);
|
||||||
keysAfter.remove(newSigningKey);
|
keysAfter.remove(newSigningKey);
|
||||||
assertEquals(1, keysAfter.size());
|
assertEquals(1, keysAfter.size());
|
||||||
OpenPGPCertificate.OpenPGPComponentKey newEncryptionKey = keysAfter.get(0);
|
OpenPGPCertificate.OpenPGPComponentKey newEncryptionKey = keysAfter.get(0);
|
||||||
bindingSig = info.getCurrentSubkeyBindingSignature(newEncryptionKey.getKeyIdentifier().getKeyId());
|
bindingSig = info.getCurrentSubkeyBindingSignature(newEncryptionKey.getKeyIdentifier());
|
||||||
assertNotNull(bindingSig);
|
assertNotNull(bindingSig);
|
||||||
assertNull(bindingSig.getHashedSubPackets().getIssuerFingerprint());
|
assertNull(bindingSig.getHashedSubPackets().getIssuerFingerprint());
|
||||||
assertEquals(KeyFlag.toBitmask(KeyFlag.ENCRYPT_COMMS), bindingSig.getHashedSubPackets().getKeyFlags());
|
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();
|
PGPSignatureSubpacketVector hashedSubpackets = signature.getHashedSubPackets();
|
||||||
assertNotNull(hashedSubpackets.getIssuerFingerprint());
|
assertNotNull(hashedSubpackets.getIssuerFingerprint());
|
||||||
assertEquals(secretKeys.getPublicKey().getKeyID(), hashedSubpackets.getIssuerKeyID());
|
assertEquals(secretKeys.getKeyIdentifier().getKeyId(), hashedSubpackets.getIssuerKeyID());
|
||||||
assertArrayEquals(
|
assertArrayEquals(
|
||||||
secretKeys.getPublicKey().getFingerprint(),
|
secretKeys.getFingerprint(),
|
||||||
hashedSubpackets.getIssuerFingerprint().getFingerprint());
|
hashedSubpackets.getIssuerFingerprint().getFingerprint());
|
||||||
assertEquals(hashedSubpackets.getKeyFlags(), KeyFlag.toBitmask(keyFlags));
|
assertEquals(hashedSubpackets.getKeyFlags(), KeyFlag.toBitmask(keyFlags));
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.KeyIdentifier;
|
import org.bouncycastle.bcpg.KeyIdentifier;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.JUtils;
|
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.generation.type.eddsa_legacy.EdDSALegacyCurve;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.protection.UnprotectedKeysProtector;
|
import org.pgpainless.key.protection.UnprotectedKeysProtector;
|
||||||
import org.pgpainless.key.util.KeyRingUtils;
|
|
||||||
import org.pgpainless.key.util.RevocationAttributes;
|
import org.pgpainless.key.util.RevocationAttributes;
|
||||||
import org.pgpainless.key.util.UserId;
|
import org.pgpainless.key.util.UserId;
|
||||||
import org.pgpainless.util.DateUtil;
|
import org.pgpainless.util.DateUtil;
|
||||||
|
@ -62,11 +59,12 @@ public class KeyRingInfoTest {
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void testWithEmilsKeys() throws IOException, PGPException {
|
public void testWithEmilsKeys() throws IOException, PGPException {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
|
OpenPGPKey secretKeys = TestKeys.getEmilKey();
|
||||||
PGPPublicKeyRing publicKeys = TestKeys.getEmilPublicKeyRing();
|
OpenPGPCertificate publicKeys = TestKeys.getEmilCertificate();
|
||||||
KeyRingInfo sInfo = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo sInfo = api.inspect(secretKeys);
|
||||||
KeyRingInfo pInfo = PGPainless.inspectKeyRing(publicKeys);
|
KeyRingInfo pInfo = api.inspect(publicKeys);
|
||||||
|
|
||||||
assertEquals(TestKeys.EMIL_KEY_ID, sInfo.getKeyIdentifier().getKeyId());
|
assertEquals(TestKeys.EMIL_KEY_ID, sInfo.getKeyIdentifier().getKeyId());
|
||||||
assertEquals(TestKeys.EMIL_KEY_ID, pInfo.getKeyIdentifier().getKeyId());
|
assertEquals(TestKeys.EMIL_KEY_ID, pInfo.getKeyIdentifier().getKeyId());
|
||||||
|
@ -108,13 +106,13 @@ public class KeyRingInfoTest {
|
||||||
assertNull(sInfo.getRevocationDate());
|
assertNull(sInfo.getRevocationDate());
|
||||||
assertNull(pInfo.getRevocationDate());
|
assertNull(pInfo.getRevocationDate());
|
||||||
Date revocationDate = DateUtil.now();
|
Date revocationDate = DateUtil.now();
|
||||||
PGPSecretKeyRing revoked = PGPainless.modifyKeyRing(secretKeys).revoke(
|
OpenPGPKey revoked = api.modify(secretKeys).revoke(
|
||||||
new UnprotectedKeysProtector(),
|
new UnprotectedKeysProtector(),
|
||||||
RevocationAttributes.createKeyRevocation()
|
RevocationAttributes.createKeyRevocation()
|
||||||
.withReason(RevocationAttributes.Reason.KEY_RETIRED)
|
.withReason(RevocationAttributes.Reason.KEY_RETIRED)
|
||||||
.withoutDescription()
|
.withoutDescription()
|
||||||
).done();
|
).done();
|
||||||
KeyRingInfo rInfo = PGPainless.inspectKeyRing(revoked);
|
KeyRingInfo rInfo = api.inspect(revoked);
|
||||||
assertNotNull(rInfo.getRevocationDate());
|
assertNotNull(rInfo.getRevocationDate());
|
||||||
assertEquals(revocationDate.getTime(), rInfo.getRevocationDate().getTime(), 5);
|
assertEquals(revocationDate.getTime(), rInfo.getRevocationDate().getTime(), 5);
|
||||||
assertEquals(revocationDate.getTime(), rInfo.getLastModified().getTime(), 5);
|
assertEquals(revocationDate.getTime(), rInfo.getLastModified().getTime(), 5);
|
||||||
|
@ -125,32 +123,34 @@ public class KeyRingInfoTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsFullyDecrypted() throws IOException, PGPException {
|
public void testIsFullyDecrypted() throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
|
PGPainless api = PGPainless.getInstance();
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
OpenPGPKey secretKeys = TestKeys.getEmilKey();
|
||||||
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
|
|
||||||
assertTrue(info.isFullyDecrypted());
|
assertTrue(info.isFullyDecrypted());
|
||||||
|
|
||||||
secretKeys = encryptSecretKeys(secretKeys);
|
secretKeys = encryptSecretKeys(secretKeys, api);
|
||||||
info = PGPainless.inspectKeyRing(secretKeys);
|
info = api.inspect(secretKeys);
|
||||||
|
|
||||||
assertFalse(info.isFullyDecrypted());
|
assertFalse(info.isFullyDecrypted());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsFullyEncrypted() throws IOException, PGPException {
|
public void testIsFullyEncrypted() throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
|
PGPainless api = PGPainless.getInstance();
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
OpenPGPKey secretKeys = TestKeys.getEmilKey();
|
||||||
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
|
|
||||||
assertFalse(info.isFullyEncrypted());
|
assertFalse(info.isFullyEncrypted());
|
||||||
|
|
||||||
secretKeys = encryptSecretKeys(secretKeys);
|
secretKeys = encryptSecretKeys(secretKeys, api);
|
||||||
info = PGPainless.inspectKeyRing(secretKeys);
|
info = api.inspect(secretKeys);
|
||||||
|
|
||||||
assertTrue(info.isFullyEncrypted());
|
assertTrue(info.isFullyEncrypted());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PGPSecretKeyRing encryptSecretKeys(PGPSecretKeyRing secretKeys) throws PGPException {
|
private static OpenPGPKey encryptSecretKeys(OpenPGPKey secretKeys, PGPainless api) throws PGPException {
|
||||||
return PGPainless.modifyKeyRing(secretKeys)
|
return api.modify(secretKeys)
|
||||||
.changePassphraseFromOldPassphrase(Passphrase.emptyPassphrase())
|
.changePassphraseFromOldPassphrase(Passphrase.emptyPassphrase())
|
||||||
.withSecureDefaultSettings()
|
.withSecureDefaultSettings()
|
||||||
.toNewPassphrase(Passphrase.fromPassword("sw0rdf1sh"))
|
.toNewPassphrase(Passphrase.fromPassword("sw0rdf1sh"))
|
||||||
|
@ -160,27 +160,29 @@ public class KeyRingInfoTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSecretKey() throws IOException, PGPException {
|
public void testGetSecretKey() throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
PGPainless api = PGPainless.getInstance();
|
||||||
PGPPublicKeyRing publicKeys = KeyRingUtils.publicKeyRingFrom(secretKeys);
|
OpenPGPKey secretKeys = TestKeys.getCryptieKey();
|
||||||
|
OpenPGPCertificate publicKeys = secretKeys.toCertificate();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
OpenPGPKey.OpenPGPSecretKey primarySecretKey = info.getSecretKey();
|
OpenPGPKey.OpenPGPSecretKey primarySecretKey = info.getSecretKey();
|
||||||
assertNotNull(primarySecretKey);
|
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());
|
assertNull(info.getSecretKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetPublicKey() throws IOException, PGPException {
|
public void testGetPublicKey() throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey secretKeys = TestKeys.getCryptieKey();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
assertEquals(KeyRingUtils.requirePrimaryPublicKeyFrom(secretKeys), info.getPrimaryKey().getPGPPublicKey());
|
assertEquals(secretKeys.getPrimaryKey().getPGPPublicKey(), info.getPrimaryKey().getPGPPublicKey());
|
||||||
|
|
||||||
assertEquals(KeyRingUtils.requirePrimarySecretKeyFrom(secretKeys),
|
assertEquals(secretKeys.getPrimarySecretKey().getPGPSecretKey(),
|
||||||
KeyRingUtils.requireSecretKeyFrom(secretKeys, secretKeys.getPublicKey().getKeyID()));
|
secretKeys.getPGPSecretKeyRing().getSecretKey(secretKeys.getKeyIdentifier()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
|
@ -224,8 +226,8 @@ public class KeyRingInfoTest {
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void testGetKeysWithFlagsAndExpiry() {
|
public void testGetKeysWithFlagsAndExpiry() {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.buildKeyRing()
|
OpenPGPKey secretKeys = PGPainless.buildKeyRing()
|
||||||
.setPrimaryKey(KeySpec.getBuilder(
|
.setPrimaryKey(KeySpec.getBuilder(
|
||||||
KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.CERTIFY_OTHER))
|
KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.CERTIFY_OTHER))
|
||||||
.addSubkey(KeySpec.getBuilder(
|
.addSubkey(KeySpec.getBuilder(
|
||||||
|
@ -234,10 +236,9 @@ public class KeyRingInfoTest {
|
||||||
.addSubkey(KeySpec.getBuilder(
|
.addSubkey(KeySpec.getBuilder(
|
||||||
KeyType.ECDSA(EllipticCurve._BRAINPOOLP384R1), KeyFlag.SIGN_DATA))
|
KeyType.ECDSA(EllipticCurve._BRAINPOOLP384R1), KeyFlag.SIGN_DATA))
|
||||||
.addUserId(UserId.builder().withName("Alice").withEmail("alice@pgpainless.org").build())
|
.addUserId(UserId.builder().withName("Alice").withEmail("alice@pgpainless.org").build())
|
||||||
.build()
|
.build();
|
||||||
.getPGPSecretKeyRing();
|
|
||||||
|
|
||||||
Iterator<PGPSecretKey> keys = secretKeys.iterator();
|
Iterator<PGPSecretKey> keys = secretKeys.getPGPSecretKeyRing().iterator();
|
||||||
Date now = DateUtil.now();
|
Date now = DateUtil.now();
|
||||||
|
|
||||||
Calendar calendar = Calendar.getInstance();
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
@ -255,11 +256,11 @@ public class KeyRingInfoTest {
|
||||||
PGPSecretKey signingKey = keys.next();
|
PGPSecretKey signingKey = keys.next();
|
||||||
|
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.setExpirationDate(primaryKeyExpiration, protector)
|
.setExpirationDate(primaryKeyExpiration, protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo info = new KeyRingInfo(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
|
|
||||||
List<OpenPGPCertificate.OpenPGPComponentKey> encryptionKeys = info.getKeysWithKeyFlag(KeyFlag.ENCRYPT_STORAGE);
|
List<OpenPGPCertificate.OpenPGPComponentKey> encryptionKeys = info.getKeysWithKeyFlag(KeyFlag.ENCRYPT_STORAGE);
|
||||||
assertEquals(1, encryptionKeys.size());
|
assertEquals(1, encryptionKeys.size());
|
||||||
|
@ -354,9 +355,10 @@ public class KeyRingInfoTest {
|
||||||
"crH02GDG8CotAnEHkLTz9GPO80q8mowzBV0EtHsXb4TeAFw5T5Qd0a5I+wk=\n" +
|
"crH02GDG8CotAnEHkLTz9GPO80q8mowzBV0EtHsXb4TeAFw5T5Qd0a5I+wk=\n" +
|
||||||
"=Vcb3\n" +
|
"=Vcb3\n" +
|
||||||
"-----END PGP ARMORED FILE-----\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
|
// Subkey is hard revoked
|
||||||
assertFalse(info.isKeyValidlyBound(new KeyIdentifier(5364407983539305061L)));
|
assertFalse(info.isKeyValidlyBound(new KeyIdentifier(5364407983539305061L)));
|
||||||
}
|
}
|
||||||
|
@ -434,14 +436,15 @@ public class KeyRingInfoTest {
|
||||||
"=7Feh\n" +
|
"=7Feh\n" +
|
||||||
"-----END PGP ARMORED FILE-----\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);
|
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));
|
assertFalse(inspectDuringRevokedPeriod.isKeyValidlyBound(subkeyId));
|
||||||
assertNotNull(inspectDuringRevokedPeriod.getSubkeyRevocationSignature(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));
|
assertTrue(inspectAfterRebinding.isKeyValidlyBound(subkeyId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,9 +521,10 @@ public class KeyRingInfoTest {
|
||||||
"=MhJL\n" +
|
"=MhJL\n" +
|
||||||
"-----END PGP ARMORED FILE-----\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
|
// Primary key is hard revoked
|
||||||
assertFalse(info.isKeyValidlyBound(keys.getKeyIdentifier()));
|
assertFalse(info.isKeyValidlyBound(keys.getKeyIdentifier()));
|
||||||
assertFalse(info.isFullyEncrypted());
|
assertFalse(info.isFullyEncrypted());
|
||||||
|
@ -528,49 +532,48 @@ public class KeyRingInfoTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSecretKeyTest() {
|
public void getSecretKeyTest() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice");
|
||||||
OpenPGPKey key = new OpenPGPKey(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
|
||||||
|
|
||||||
OpenPgpV4Fingerprint primaryKeyFingerprint = new OpenPgpV4Fingerprint(secretKeys);
|
OpenPgpV4Fingerprint primaryKeyFingerprint = new OpenPgpV4Fingerprint(secretKeys);
|
||||||
OpenPGPKey.OpenPGPSecretKey primaryKey = info.getSecretKey(primaryKeyFingerprint);
|
OpenPGPKey.OpenPGPSecretKey primaryKey = info.getSecretKey(primaryKeyFingerprint);
|
||||||
assertNotNull(primaryKey);
|
assertNotNull(primaryKey);
|
||||||
assertEquals(key.getPrimarySecretKey().getKeyIdentifier(), primaryKey.getKeyIdentifier());
|
assertEquals(secretKeys.getPrimarySecretKey().getKeyIdentifier(), primaryKey.getKeyIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetLatestKeyCreationDate() throws PGPException, IOException {
|
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");
|
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());
|
JUtils.assertDateEquals(latestCreationDate, info.getLatestKeyCreationDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetExpirationDateForUse_SPLIT() throws PGPException, IOException {
|
public void testGetExpirationDateForUse_SPLIT() throws PGPException, IOException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
|
OpenPGPKey secretKeys = TestKeys.getEmilKey();
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = PGPainless.getInstance().inspect(secretKeys);
|
||||||
assertThrows(IllegalArgumentException.class, () -> info.getExpirationDateForUse(KeyFlag.SPLIT));
|
assertThrows(IllegalArgumentException.class, () -> info.getExpirationDateForUse(KeyFlag.SPLIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetExpirationDateForUse_SHARED() throws PGPException, IOException {
|
public void testGetExpirationDateForUse_SHARED() throws PGPException, IOException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
|
OpenPGPKey secretKeys = TestKeys.getEmilKey();
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = PGPainless.getInstance().inspect(secretKeys);
|
||||||
assertThrows(IllegalArgumentException.class, () -> info.getExpirationDateForUse(KeyFlag.SHARED));
|
assertThrows(IllegalArgumentException.class, () -> info.getExpirationDateForUse(KeyFlag.SHARED));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetExpirationDateForUse_NoSuchKey() {
|
public void testGetExpirationDateForUse_NoSuchKey() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.buildKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey secretKeys = PGPainless.buildKeyRing()
|
||||||
.addUserId("Alice")
|
.addUserId("Alice")
|
||||||
.setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.CERTIFY_OTHER))
|
.setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.CERTIFY_OTHER))
|
||||||
.build()
|
.build();
|
||||||
.getPGPSecretKeyRing();
|
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
|
|
||||||
assertThrows(NoSuchElementException.class, () -> info.getExpirationDateForUse(KeyFlag.ENCRYPT_COMMS));
|
assertThrows(NoSuchElementException.class, () -> info.getExpirationDateForUse(KeyFlag.ENCRYPT_COMMS));
|
||||||
}
|
}
|
||||||
|
@ -600,8 +603,8 @@ public class KeyRingInfoTest {
|
||||||
"/+XL+qMMgLHaQ25aA11GVAkC\n" +
|
"/+XL+qMMgLHaQ25aA11GVAkC\n" +
|
||||||
"=7gbt\n" +
|
"=7gbt\n" +
|
||||||
"-----END PGP PRIVATE KEY BLOCK-----";
|
"-----END PGP PRIVATE KEY BLOCK-----";
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
OpenPGPKey secretKeys = PGPainless.getInstance().readKey().parseKey(KEY);
|
OpenPGPKey secretKeys = api.readKey().parseKey(KEY);
|
||||||
final KeyIdentifier pkid = new KeyIdentifier(6643807985200014832L);
|
final KeyIdentifier pkid = new KeyIdentifier(6643807985200014832L);
|
||||||
final KeyIdentifier skid1 = new KeyIdentifier(-2328413746552029063L);
|
final KeyIdentifier skid1 = new KeyIdentifier(-2328413746552029063L);
|
||||||
final KeyIdentifier skid2 = new KeyIdentifier(-3276877650571760552L);
|
final KeyIdentifier skid2 = new KeyIdentifier(-3276877650571760552L);
|
||||||
|
@ -611,7 +614,7 @@ public class KeyRingInfoTest {
|
||||||
Arrays.asList(CompressionAlgorithm.ZLIB, CompressionAlgorithm.BZIP2, CompressionAlgorithm.ZIP, CompressionAlgorithm.UNCOMPRESSED));
|
Arrays.asList(CompressionAlgorithm.ZLIB, CompressionAlgorithm.BZIP2, CompressionAlgorithm.ZIP, CompressionAlgorithm.UNCOMPRESSED));
|
||||||
Set<SymmetricKeyAlgorithm> preferredSymmetricAlgorithms = new LinkedHashSet<>(
|
Set<SymmetricKeyAlgorithm> preferredSymmetricAlgorithms = new LinkedHashSet<>(
|
||||||
Arrays.asList(SymmetricKeyAlgorithm.AES_256, SymmetricKeyAlgorithm.AES_192, SymmetricKeyAlgorithm.AES_128));
|
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
|
// Bob is an invalid userId
|
||||||
assertThrows(NoSuchElementException.class, () -> info.getPreferredSymmetricKeyAlgorithms("Bob"));
|
assertThrows(NoSuchElementException.class, () -> info.getPreferredSymmetricKeyAlgorithms("Bob"));
|
||||||
|
@ -694,10 +697,10 @@ public class KeyRingInfoTest {
|
||||||
"C9h35EjDuD+1COXUOoW2B8LX6m2yf8cY72K70QgtGemj7UWhXL5u/wARAQAB\n" +
|
"C9h35EjDuD+1COXUOoW2B8LX6m2yf8cY72K70QgtGemj7UWhXL5u/wARAQAB\n" +
|
||||||
"=A3B8\n" +
|
"=A3B8\n" +
|
||||||
"-----END PGP PUBLIC KEY BLOCK-----\n";
|
"-----END PGP PUBLIC KEY BLOCK-----\n";
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
OpenPGPCertificate certificate = PGPainless.getInstance().readKey().parseCertificate(KEY);
|
OpenPGPCertificate certificate = api.readKey().parseCertificate(KEY);
|
||||||
OpenPgpV4Fingerprint unboundKey = new OpenPgpV4Fingerprint("D622C916384E0F6D364907E55D918BBD521CCD10");
|
OpenPgpV4Fingerprint unboundKey = new OpenPgpV4Fingerprint("D622C916384E0F6D364907E55D918BBD521CCD10");
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(certificate);
|
KeyRingInfo info = api.inspect(certificate);
|
||||||
|
|
||||||
assertFalse(info.isKeyValidlyBound(unboundKey.getKeyIdentifier()));
|
assertFalse(info.isKeyValidlyBound(unboundKey.getKeyIdentifier()));
|
||||||
|
|
||||||
|
@ -773,9 +776,9 @@ public class KeyRingInfoTest {
|
||||||
"qDzPRwEAhdVBeryRUcwjgwHX0xmMFK7vLkdonn8BR2++nXBO2g8=\n" +
|
"qDzPRwEAhdVBeryRUcwjgwHX0xmMFK7vLkdonn8BR2++nXBO2g8=\n" +
|
||||||
"=ZRAy\n" +
|
"=ZRAy\n" +
|
||||||
"-----END PGP PRIVATE KEY BLOCK-----\n";
|
"-----END PGP PRIVATE KEY BLOCK-----\n";
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
OpenPGPKey secretKeys = PGPainless.getInstance().readKey().parseKey(KEY);
|
OpenPGPKey secretKeys = api.readKey().parseKey(KEY);
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
|
|
||||||
List<String> emails = info.getEmailAddresses();
|
List<String> emails = info.getEmailAddresses();
|
||||||
assertEquals(emails, Arrays.asList("alice@email.tld", "alice@pgpainless.org", "alice@openpgp.org", "alice@rfc4880.spec"));
|
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" +
|
"J5wP\n" +
|
||||||
"=nFoO\n" +
|
"=nFoO\n" +
|
||||||
"-----END PGP PUBLIC KEY BLOCK-----";
|
"-----END PGP PUBLIC KEY BLOCK-----";
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
OpenPGPCertificate cert = PGPainless.getInstance().readKey().parseCertificate(CERT);
|
OpenPGPCertificate cert = api.readKey().parseCertificate(CERT);
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(cert);
|
KeyRingInfo info = api.inspect(cert);
|
||||||
assertTrue(info.isUsableForEncryption());
|
assertTrue(info.isUsableForEncryption());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -833,9 +836,9 @@ public class KeyRingInfoTest {
|
||||||
"2XO/hpB2T8VXFfFKwj7U9LGkX+ciLg==\n" +
|
"2XO/hpB2T8VXFfFKwj7U9LGkX+ciLg==\n" +
|
||||||
"=etPP\n" +
|
"=etPP\n" +
|
||||||
"-----END PGP PUBLIC KEY BLOCK-----";
|
"-----END PGP PUBLIC KEY BLOCK-----";
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
OpenPGPCertificate publicKeys = PGPainless.getInstance().readKey().parseCertificate(CERT);
|
OpenPGPCertificate publicKeys = api.readKey().parseCertificate(CERT);
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(publicKeys);
|
KeyRingInfo info = api.inspect(publicKeys);
|
||||||
|
|
||||||
assertTrue(info.isUsableForEncryption(EncryptionPurpose.COMMUNICATIONS));
|
assertTrue(info.isUsableForEncryption(EncryptionPurpose.COMMUNICATIONS));
|
||||||
assertTrue(info.isUsableForEncryption(EncryptionPurpose.ANY));
|
assertTrue(info.isUsableForEncryption(EncryptionPurpose.ANY));
|
||||||
|
@ -870,8 +873,9 @@ public class KeyRingInfoTest {
|
||||||
"AQCjeV+3VT+u1movwIYv4XkzB6gB+B2C+DK9nvG5sXZhBg==\n" +
|
"AQCjeV+3VT+u1movwIYv4XkzB6gB+B2C+DK9nvG5sXZhBg==\n" +
|
||||||
"=uqmO\n" +
|
"=uqmO\n" +
|
||||||
"-----END PGP PUBLIC KEY BLOCK-----";
|
"-----END PGP PUBLIC KEY BLOCK-----";
|
||||||
OpenPGPCertificate publicKeys = PGPainless.getInstance().readKey().parseCertificate(CERT);
|
PGPainless api = PGPainless.getInstance();
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(publicKeys);
|
OpenPGPCertificate publicKeys = api.readKey().parseCertificate(CERT);
|
||||||
|
KeyRingInfo info = api.inspect(publicKeys);
|
||||||
|
|
||||||
assertFalse(info.isUsableForEncryption());
|
assertFalse(info.isUsableForEncryption());
|
||||||
assertFalse(info.isUsableForEncryption(EncryptionPurpose.ANY));
|
assertFalse(info.isUsableForEncryption(EncryptionPurpose.ANY));
|
||||||
|
|
|
@ -7,7 +7,7 @@ package org.pgpainless.key.info;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
|
@ -16,13 +16,13 @@ public class PrimaryUserIdTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetPrimaryUserId() throws PGPException {
|
public void testGetPrimaryUserId() throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("alice@wonderland.lit")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().simpleEcKeyRing("alice@wonderland.lit");
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.addUserId("mad_alice@wonderland.lit", SecretKeyRingProtector.unprotectedKeys())
|
.addUserId("mad_alice@wonderland.lit", SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
assertEquals("alice@wonderland.lit", info.getPrimaryUserId());
|
assertEquals("alice@wonderland.lit", info.getPrimaryUserId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,12 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import org.bouncycastle.bcpg.KeyIdentifier;
|
||||||
import org.bouncycastle.bcpg.SignatureSubpacketTags;
|
import org.bouncycastle.bcpg.SignatureSubpacketTags;
|
||||||
import org.bouncycastle.bcpg.sig.RevocationReason;
|
import org.bouncycastle.bcpg.sig.RevocationReason;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.algorithm.KeyFlag;
|
import org.pgpainless.algorithm.KeyFlag;
|
||||||
|
@ -37,7 +38,8 @@ public class UserIdRevocationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRevocationWithoutRevocationAttributes() throws PGPException {
|
public void testRevocationWithoutRevocationAttributes() throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.buildKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey secretKeys = PGPainless.buildKeyRing()
|
||||||
.setPrimaryKey(KeySpec.getBuilder(
|
.setPrimaryKey(KeySpec.getBuilder(
|
||||||
KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519),
|
KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519),
|
||||||
KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER))
|
KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER))
|
||||||
|
@ -45,28 +47,27 @@ public class UserIdRevocationTest {
|
||||||
KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS))
|
KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS))
|
||||||
.addUserId("primary@key.id")
|
.addUserId("primary@key.id")
|
||||||
.addUserId("secondary@key.id")
|
.addUserId("secondary@key.id")
|
||||||
.build()
|
.build();
|
||||||
.getPGPSecretKeyRing();
|
|
||||||
|
|
||||||
// make a copy with revoked subkey
|
// make a copy with revoked subkey
|
||||||
PGPSecretKeyRing revoked = PGPainless.modifyKeyRing(secretKeys)
|
OpenPGPKey revoked = api.modify(secretKeys)
|
||||||
.revokeUserId("secondary@key.id", new UnprotectedKeysProtector())
|
.revokeUserId("secondary@key.id", new UnprotectedKeysProtector())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(revoked);
|
KeyRingInfo info = api.inspect(revoked);
|
||||||
List<String> userIds = info.getUserIds();
|
List<String> userIds = info.getUserIds();
|
||||||
assertEquals(Arrays.asList("primary@key.id", "secondary@key.id"), userIds);
|
assertEquals(Arrays.asList("primary@key.id", "secondary@key.id"), userIds);
|
||||||
assertTrue(info.isUserIdValid("primary@key.id"));
|
assertTrue(info.isUserIdValid("primary@key.id"));
|
||||||
assertFalse(info.isUserIdValid("sedondary@key.id"));
|
assertFalse(info.isUserIdValid("sedondary@key.id"));
|
||||||
assertFalse(info.isUserIdValid("tertiary@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
|
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())
|
.revokeUserId("secondary@key.id", new UnprotectedKeysProtector())
|
||||||
.done();
|
.done();
|
||||||
info = PGPainless.inspectKeyRing(revoked);
|
info = api.inspect(revoked);
|
||||||
userIds = info.getUserIds();
|
userIds = info.getUserIds();
|
||||||
assertEquals(Arrays.asList("primary@key.id", "secondary@key.id"), userIds);
|
assertEquals(Arrays.asList("primary@key.id", "secondary@key.id"), userIds);
|
||||||
assertTrue(info.isUserIdValid("primary@key.id"));
|
assertTrue(info.isUserIdValid("primary@key.id"));
|
||||||
|
@ -76,23 +77,23 @@ public class UserIdRevocationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRevocationWithRevocationReason() {
|
public void testRevocationWithRevocationReason() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.buildKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey secretKeys = PGPainless.buildKeyRing()
|
||||||
.setPrimaryKey(KeySpec.getBuilder(
|
.setPrimaryKey(KeySpec.getBuilder(
|
||||||
KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519),
|
KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519),
|
||||||
KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER))
|
KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER))
|
||||||
.addSubkey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS))
|
.addSubkey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS))
|
||||||
.addUserId("primary@key.id")
|
.addUserId("primary@key.id")
|
||||||
.addUserId("secondary@key.id")
|
.addUserId("secondary@key.id")
|
||||||
.build()
|
.build();
|
||||||
.getPGPSecretKeyRing();
|
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.revokeUserId("secondary@key.id", new UnprotectedKeysProtector(),
|
.revokeUserId("secondary@key.id", new UnprotectedKeysProtector(),
|
||||||
RevocationAttributes.createCertificateRevocation()
|
RevocationAttributes.createCertificateRevocation()
|
||||||
.withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID)
|
.withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID)
|
||||||
.withDescription("I lost my mail password"))
|
.withDescription("I lost my mail password"))
|
||||||
.done();
|
.done();
|
||||||
KeyRingInfo info = new KeyRingInfo(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
|
|
||||||
PGPSignature signature = info.getUserIdRevocation("secondary@key.id");
|
PGPSignature signature = info.getUserIdRevocation("secondary@key.id");
|
||||||
assertNotNull(signature);
|
assertNotNull(signature);
|
||||||
|
@ -104,31 +105,31 @@ public class UserIdRevocationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unknownKeyThrowsIllegalArgumentException() throws IOException, PGPException {
|
public void unknownKeyThrowsIllegalArgumentException() throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
OpenPGPKey secretKeys = TestKeys.getCryptieKey();
|
||||||
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector
|
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)
|
||||||
.revokeSubKey(1L, protector));
|
.revokeSubKey(new KeyIdentifier(1L), protector));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unknownUserIdThrowsNoSuchElementException() throws IOException, PGPException {
|
public void unknownUserIdThrowsNoSuchElementException() throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
OpenPGPKey secretKeys = TestKeys.getCryptieKey();
|
||||||
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector
|
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));
|
.revokeUserId("invalid@user.id", protector));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidRevocationReasonThrowsIllegalArgumentException() throws IOException, PGPException {
|
public void invalidRevocationReasonThrowsIllegalArgumentException() throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
OpenPGPKey secretKeys = TestKeys.getCryptieKey();
|
||||||
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector
|
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,
|
.revokeUserId("cryptie@encrypted.key", protector,
|
||||||
RevocationAttributes.createKeyRevocation().withReason(RevocationAttributes.Reason.KEY_RETIRED)
|
RevocationAttributes.createKeyRevocation().withReason(RevocationAttributes.Reason.KEY_RETIRED)
|
||||||
.withDescription("This is not a valid certification revocation reason.")));
|
.withDescription("This is not a valid certification revocation reason.")));
|
||||||
|
|
|
@ -16,8 +16,7 @@ import java.util.List;
|
||||||
import org.bouncycastle.bcpg.KeyIdentifier;
|
import org.bouncycastle.bcpg.KeyIdentifier;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.junit.jupiter.api.TestTemplate;
|
import org.junit.jupiter.api.TestTemplate;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
|
@ -39,14 +38,15 @@ public class AddSubKeyTest {
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void testAddSubKey()
|
public void testAddSubKey()
|
||||||
throws IOException, PGPException {
|
throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey secretKeys = TestKeys.getCryptieKey();
|
||||||
|
|
||||||
List<KeyIdentifier> keyIdentifiersBefore = new ArrayList<>();
|
List<KeyIdentifier> keyIdentifiersBefore = new ArrayList<>();
|
||||||
for (Iterator<PGPPublicKey> it = secretKeys.getPublicKeys(); it.hasNext(); ) {
|
for (Iterator<PGPPublicKey> it = secretKeys.getPGPSecretKeyRing().getPublicKeys(); it.hasNext(); ) {
|
||||||
keyIdentifiersBefore.add(it.next().getKeyIdentifier());
|
keyIdentifiersBefore.add(it.next().getKeyIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.addSubKey(
|
.addSubKey(
|
||||||
KeySpec.getBuilder(ECDSA.fromCurve(EllipticCurve._P256), KeyFlag.SIGN_DATA).build(),
|
KeySpec.getBuilder(ECDSA.fromCurve(EllipticCurve._P256), KeyFlag.SIGN_DATA).build(),
|
||||||
Passphrase.fromPassword("subKeyPassphrase"),
|
Passphrase.fromPassword("subKeyPassphrase"),
|
||||||
|
@ -54,7 +54,7 @@ public class AddSubKeyTest {
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
List<KeyIdentifier> keyIdentifiersAfter = new ArrayList<>();
|
List<KeyIdentifier> keyIdentifiersAfter = new ArrayList<>();
|
||||||
for (Iterator<PGPPublicKey> it = secretKeys.getPublicKeys(); it.hasNext(); ) {
|
for (Iterator<PGPPublicKey> it = secretKeys.getPGPSecretKeyRing().getPublicKeys(); it.hasNext(); ) {
|
||||||
keyIdentifiersAfter.add(it.next().getKeyIdentifier());
|
keyIdentifiersAfter.add(it.next().getKeyIdentifier());
|
||||||
}
|
}
|
||||||
assertNotEquals(keyIdentifiersAfter, keyIdentifiersBefore);
|
assertNotEquals(keyIdentifiersAfter, keyIdentifiersBefore);
|
||||||
|
@ -62,12 +62,12 @@ public class AddSubKeyTest {
|
||||||
keyIdentifiersAfter.removeAll(keyIdentifiersBefore);
|
keyIdentifiersAfter.removeAll(keyIdentifiersBefore);
|
||||||
KeyIdentifier subKeyIdentifier = keyIdentifiersAfter.get(0);
|
KeyIdentifier subKeyIdentifier = keyIdentifiersAfter.get(0);
|
||||||
|
|
||||||
PGPSecretKey subKey = secretKeys.getSecretKey(subKeyIdentifier);
|
OpenPGPKey.OpenPGPSecretKey subKey = secretKeys.getSecretKey(subKeyIdentifier);
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockEachKeyWith(
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockEachKeyWith(
|
||||||
Passphrase.fromPassword("subKeyPassphrase"), secretKeys);
|
Passphrase.fromPassword("subKeyPassphrase"), secretKeys);
|
||||||
UnlockSecretKey.unlockSecretKey(subKey, protector);
|
UnlockSecretKey.unlockSecretKey(subKey, protector);
|
||||||
|
|
||||||
KeyRingInfo info = new KeyRingInfo(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
assertEquals(Collections.singletonList(KeyFlag.SIGN_DATA), info.getKeyFlagsOf(subKeyIdentifier));
|
assertEquals(Collections.singletonList(KeyFlag.SIGN_DATA), info.getKeyFlagsOf(subKeyIdentifier));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@ import java.util.List;
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.sig.NotationData;
|
import org.bouncycastle.bcpg.sig.NotationData;
|
||||||
import org.bouncycastle.openpgp.PGPKeyPair;
|
import org.bouncycastle.openpgp.PGPKeyPair;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.JUtils;
|
import org.junit.JUtils;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
|
@ -38,11 +38,11 @@ public class AddSubkeyWithModifiedBindingSignatureSubpacketsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindEncryptionSubkeyAndModifyBindingSignatureHashedSubpackets() {
|
public void bindEncryptionSubkeyAndModifyBindingSignatureHashedSubpackets() {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.modernKeyRing("Alice <alice@pgpainless.org>")
|
.modernKeyRing("Alice <alice@pgpainless.org>");
|
||||||
.getPGPSecretKeyRing();
|
KeyRingInfo before = api.inspect(secretKeys);
|
||||||
KeyRingInfo before = PGPainless.inspectKeyRing(secretKeys);
|
|
||||||
List<OpenPGPCertificate.OpenPGPComponentKey> signingKeysBefore = before.getSigningSubkeys();
|
List<OpenPGPCertificate.OpenPGPComponentKey> signingKeysBefore = before.getSigningSubkeys();
|
||||||
|
|
||||||
PGPKeyPair secretSubkey = KeyRingBuilder.generateKeyPair(
|
PGPKeyPair secretSubkey = KeyRingBuilder.generateKeyPair(
|
||||||
|
@ -50,7 +50,7 @@ public class AddSubkeyWithModifiedBindingSignatureSubpacketsTest {
|
||||||
OpenPGPKeyVersion.v4);
|
OpenPGPKeyVersion.v4);
|
||||||
|
|
||||||
long secondsUntilExpiration = 1000;
|
long secondsUntilExpiration = 1000;
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.addSubKey(secretSubkey, new SelfSignatureSubpackets.Callback() {
|
.addSubKey(secretSubkey, new SelfSignatureSubpackets.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
||||||
|
@ -60,7 +60,7 @@ public class AddSubkeyWithModifiedBindingSignatureSubpacketsTest {
|
||||||
}, SecretKeyRingProtector.unprotectedKeys(), protector, KeyFlag.SIGN_DATA)
|
}, SecretKeyRingProtector.unprotectedKeys(), protector, KeyFlag.SIGN_DATA)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo after = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo after = api.inspect(secretKeys);
|
||||||
List<OpenPGPCertificate.OpenPGPComponentKey> signingKeysAfter = after.getSigningSubkeys();
|
List<OpenPGPCertificate.OpenPGPComponentKey> signingKeysAfter = after.getSigningSubkeys();
|
||||||
signingKeysAfter.removeAll(signingKeysBefore);
|
signingKeysAfter.removeAll(signingKeysBefore);
|
||||||
assertFalse(signingKeysAfter.isEmpty());
|
assertFalse(signingKeysAfter.isEmpty());
|
||||||
|
|
|
@ -37,31 +37,31 @@ public class AddUserIdTest {
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void addUserIdToExistingKeyRing()
|
public void addUserIdToExistingKeyRing()
|
||||||
throws PGPException {
|
throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.simpleEcKeyRing("alice@wonderland.lit", "rabb1th0le")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.simpleEcKeyRing("alice@wonderland.lit", "rabb1th0le");
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
Iterator<String> userIds = info.getValidUserIds().iterator();
|
Iterator<String> userIds = info.getValidUserIds().iterator();
|
||||||
assertEquals("alice@wonderland.lit", userIds.next());
|
assertEquals("alice@wonderland.lit", userIds.next());
|
||||||
assertFalse(userIds.hasNext());
|
assertFalse(userIds.hasNext());
|
||||||
|
|
||||||
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector.forKey(secretKeys, Passphrase.fromPassword("rabb1th0le"));
|
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector.forKey(secretKeys, Passphrase.fromPassword("rabb1th0le"));
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.addUserId("cheshirecat@wonderland.lit", protector)
|
.addUserId("cheshirecat@wonderland.lit", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys);
|
info = api.inspect(secretKeys);
|
||||||
userIds = info.getValidUserIds().iterator();
|
userIds = info.getValidUserIds().iterator();
|
||||||
assertEquals("alice@wonderland.lit", userIds.next());
|
assertEquals("alice@wonderland.lit", userIds.next());
|
||||||
assertEquals("cheshirecat@wonderland.lit", userIds.next());
|
assertEquals("cheshirecat@wonderland.lit", userIds.next());
|
||||||
assertFalse(userIds.hasNext());
|
assertFalse(userIds.hasNext());
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.revokeUserId("cheshirecat@wonderland.lit", protector)
|
.revokeUserId("cheshirecat@wonderland.lit", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys);
|
info = api.inspect(secretKeys);
|
||||||
userIds = info.getValidUserIds().iterator();
|
userIds = info.getValidUserIds().iterator();
|
||||||
assertEquals("alice@wonderland.lit", userIds.next());
|
assertEquals("alice@wonderland.lit", userIds.next());
|
||||||
assertFalse(userIds.hasNext());
|
assertFalse(userIds.hasNext());
|
||||||
|
@ -96,20 +96,21 @@ public class AddUserIdTest {
|
||||||
"=bk4o\r\n" +
|
"=bk4o\r\n" +
|
||||||
"-----END PGP PRIVATE KEY BLOCK-----\r\n";
|
"-----END PGP PRIVATE KEY BLOCK-----\r\n";
|
||||||
|
|
||||||
OpenPGPKey key = PGPainless.getInstance().readKey().parseKey(ARMORED_PRIVATE_KEY);
|
PGPainless api = PGPainless.getInstance();
|
||||||
PGPSecretKeyRing secretKeys = key.getPGPSecretKeyRing();
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
OpenPGPKey key = api.readKey().parseKey(ARMORED_PRIVATE_KEY);
|
||||||
|
KeyRingInfo info = api.inspect(key);
|
||||||
Iterator<String> userIds = info.getValidUserIds().iterator();
|
Iterator<String> userIds = info.getValidUserIds().iterator();
|
||||||
assertEquals("<user@example.com>", userIds.next());
|
assertEquals("<user@example.com>", userIds.next());
|
||||||
assertFalse(userIds.hasNext());
|
assertFalse(userIds.hasNext());
|
||||||
|
|
||||||
SecretKeyRingProtector protector = new UnprotectedKeysProtector();
|
SecretKeyRingProtector protector = new UnprotectedKeysProtector();
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
key = api.modify(key)
|
||||||
.revokeUserId("<user@example.com>", protector)
|
.revokeUserId("<user@example.com>", protector)
|
||||||
.addUserId("cheshirecat@wonderland.lit", protector)
|
.addUserId("cheshirecat@wonderland.lit", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys);
|
info = api.inspect(key);
|
||||||
userIds = info.getValidUserIds().iterator();
|
userIds = info.getValidUserIds().iterator();
|
||||||
assertEquals("cheshirecat@wonderland.lit", userIds.next());
|
assertEquals("cheshirecat@wonderland.lit", userIds.next());
|
||||||
assertFalse(userIds.hasNext());
|
assertFalse(userIds.hasNext());
|
||||||
|
@ -118,17 +119,17 @@ public class AddUserIdTest {
|
||||||
@Test
|
@Test
|
||||||
public void addNewPrimaryUserIdTest() {
|
public void addNewPrimaryUserIdTest() {
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.modernKeyRing("Alice")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.modernKeyRing("Alice");
|
||||||
UserId bob = UserId.builder().withName("Bob").noEmail().noComment().build();
|
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())
|
.addPrimaryUserId(bob, SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
assertEquals("Bob", PGPainless.inspectKeyRing(secretKeys, DateExtensionsKt.plusSeconds(now, 2)).getPrimaryUserId());
|
assertEquals("Bob", api.inspect(secretKeys, DateExtensionsKt.plusSeconds(now, 2)).getPrimaryUserId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ package org.pgpainless.key.modification;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.JUtils;
|
import org.junit.JUtils;
|
||||||
import org.junit.jupiter.api.TestTemplate;
|
import org.junit.jupiter.api.TestTemplate;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
@ -138,7 +138,8 @@ public class ChangeExpirationOnKeyWithDifferentSignatureTypesTest {
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void setExpirationDate_keyHasSigClass10()
|
public void setExpirationDate_keyHasSigClass10()
|
||||||
throws IOException {
|
throws IOException {
|
||||||
PGPSecretKeyRing keys = PGPainless.readKeyRing().secretKeyRing(keyWithGenericCertification);
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey keys = api.readKey().parseKey(keyWithGenericCertification);
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
executeTestForKeys(keys, protector);
|
executeTestForKeys(keys, protector);
|
||||||
}
|
}
|
||||||
|
@ -147,20 +148,23 @@ public class ChangeExpirationOnKeyWithDifferentSignatureTypesTest {
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void setExpirationDate_keyHasSigClass12()
|
public void setExpirationDate_keyHasSigClass12()
|
||||||
throws IOException {
|
throws IOException {
|
||||||
PGPSecretKeyRing keys = PGPainless.readKeyRing().secretKeyRing(keyWithCasualCertification);
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey keys = api.readKey().parseKey(keyWithCasualCertification);
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
executeTestForKeys(keys, protector);
|
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);
|
Date expirationDate = new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 14);
|
||||||
// round date for test stability
|
// round date for test stability
|
||||||
expirationDate = DateUtil.toSecondsPrecision(expirationDate);
|
expirationDate = DateUtil.toSecondsPrecision(expirationDate);
|
||||||
|
|
||||||
PGPSecretKeyRing modded = PGPainless.modifyKeyRing(keys)
|
OpenPGPKey modded = api.modify(keys)
|
||||||
.setExpirationDate(expirationDate, protector)
|
.setExpirationDate(expirationDate, protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
JUtils.assertDateEquals(expirationDate, PGPainless.inspectKeyRing(modded).getPrimaryKeyExpirationDate());
|
JUtils.assertDateEquals(expirationDate, api.inspect(modded).getPrimaryKeyExpirationDate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.JUtils;
|
import org.junit.JUtils;
|
||||||
import org.junit.jupiter.api.TestTemplate;
|
import org.junit.jupiter.api.TestTemplate;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
@ -35,27 +35,28 @@ public class ChangeExpirationTest {
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void setExpirationDateAndThenUnsetIt_OnPrimaryKey()
|
public void setExpirationDateAndThenUnsetIt_OnPrimaryKey()
|
||||||
throws PGPException, IOException {
|
throws PGPException, IOException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
|
PGPainless api = PGPainless.getInstance();
|
||||||
KeyRingInfo sInfo = PGPainless.inspectKeyRing(secretKeys);
|
OpenPGPKey secretKeys = TestKeys.getEmilKey();
|
||||||
|
KeyRingInfo sInfo = api.inspect(secretKeys);
|
||||||
|
|
||||||
assertNull(sInfo.getPrimaryKeyExpirationDate());
|
assertNull(sInfo.getPrimaryKeyExpirationDate());
|
||||||
assertNull(sInfo.getSubkeyExpirationDate(subKeyFingerprint));
|
assertNull(sInfo.getSubkeyExpirationDate(subKeyFingerprint));
|
||||||
|
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
Date date = DateUtil.parseUTCDate("2020-11-27 16:10:32 UTC");
|
Date date = DateUtil.parseUTCDate("2020-11-27 16:10:32 UTC");
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.setExpirationDate(date, new UnprotectedKeysProtector()).done();
|
.setExpirationDate(date, new UnprotectedKeysProtector()).done();
|
||||||
sInfo = PGPainless.inspectKeyRing(secretKeys);
|
sInfo = api.inspect(secretKeys);
|
||||||
assertNotNull(sInfo.getPrimaryKeyExpirationDate());
|
assertNotNull(sInfo.getPrimaryKeyExpirationDate());
|
||||||
assertEquals(date.getTime(), sInfo.getPrimaryKeyExpirationDate().getTime());
|
assertEquals(date.getTime(), sInfo.getPrimaryKeyExpirationDate().getTime());
|
||||||
// subkey unchanged
|
// subkey unchanged
|
||||||
assertNull(sInfo.getSubkeyExpirationDate(subKeyFingerprint));
|
assertNull(sInfo.getSubkeyExpirationDate(subKeyFingerprint));
|
||||||
|
|
||||||
Date t1 = new Date(now.getTime() + 1000 * 60 * 60);
|
Date t1 = new Date(now.getTime() + 1000 * 60 * 60);
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, t1)
|
secretKeys = api.modify(secretKeys, t1)
|
||||||
.setExpirationDate(null, new UnprotectedKeysProtector()).done();
|
.setExpirationDate(null, new UnprotectedKeysProtector()).done();
|
||||||
|
|
||||||
sInfo = PGPainless.inspectKeyRing(secretKeys, t1);
|
sInfo = api.inspect(secretKeys, t1);
|
||||||
assertNull(sInfo.getPrimaryKeyExpirationDate());
|
assertNull(sInfo.getPrimaryKeyExpirationDate());
|
||||||
assertNull(sInfo.getSubkeyExpirationDate(subKeyFingerprint));
|
assertNull(sInfo.getSubkeyExpirationDate(subKeyFingerprint));
|
||||||
}
|
}
|
||||||
|
@ -64,9 +65,9 @@ public class ChangeExpirationTest {
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void setExpirationDateAndThenUnsetIt_OnSubkey()
|
public void setExpirationDateAndThenUnsetIt_OnSubkey()
|
||||||
throws PGPException, IOException {
|
throws PGPException, IOException {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
|
OpenPGPKey secretKeys = TestKeys.getEmilKey();
|
||||||
KeyRingInfo sInfo = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo sInfo = api.inspect(secretKeys);
|
||||||
|
|
||||||
assertNull(sInfo.getPrimaryKeyExpirationDate());
|
assertNull(sInfo.getPrimaryKeyExpirationDate());
|
||||||
|
|
||||||
|
@ -76,42 +77,43 @@ public class ChangeExpirationTest {
|
||||||
calendar.add(Calendar.DATE, 5);
|
calendar.add(Calendar.DATE, 5);
|
||||||
Date expiration = calendar.getTime(); // in 5 days
|
Date expiration = calendar.getTime(); // in 5 days
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.setExpirationDate(expiration, new UnprotectedKeysProtector()).done();
|
.setExpirationDate(expiration, new UnprotectedKeysProtector()).done();
|
||||||
sInfo = PGPainless.inspectKeyRing(secretKeys);
|
sInfo = api.inspect(secretKeys);
|
||||||
assertNotNull(sInfo.getPrimaryKeyExpirationDate());
|
assertNotNull(sInfo.getPrimaryKeyExpirationDate());
|
||||||
JUtils.assertDateEquals(expiration, sInfo.getPrimaryKeyExpirationDate());
|
JUtils.assertDateEquals(expiration, sInfo.getPrimaryKeyExpirationDate());
|
||||||
|
|
||||||
Date t1 = new Date(now.getTime() + 1000 * 60 * 60);
|
Date t1 = new Date(now.getTime() + 1000 * 60 * 60);
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, t1)
|
secretKeys = api.modify(secretKeys, t1)
|
||||||
.setExpirationDate(null, new UnprotectedKeysProtector()).done();
|
.setExpirationDate(null, new UnprotectedKeysProtector()).done();
|
||||||
|
|
||||||
sInfo = PGPainless.inspectKeyRing(secretKeys, t1);
|
sInfo = api.inspect(secretKeys, t1);
|
||||||
assertNull(sInfo.getPrimaryKeyExpirationDate());
|
assertNull(sInfo.getPrimaryKeyExpirationDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void testExtremeExpirationDates() throws PGPException, IOException {
|
public void testExtremeExpirationDates() throws PGPException, IOException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey secretKeys = TestKeys.getEmilKey();
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
|
|
||||||
// seconds from 2021 to 2199 will overflow 32bit integers
|
// seconds from 2021 to 2199 will overflow 32bit integers
|
||||||
Date farAwayExpiration = DateUtil.parseUTCDate("2199-01-01 00:00:00 UTC");
|
Date farAwayExpiration = DateUtil.parseUTCDate("2199-01-01 00:00:00 UTC");
|
||||||
|
|
||||||
final PGPSecretKeyRing finalKeys = secretKeys;
|
final OpenPGPKey finalKeys = secretKeys;
|
||||||
assertThrows(IllegalArgumentException.class, () ->
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
PGPainless.modifyKeyRing(finalKeys)
|
api.modify(finalKeys)
|
||||||
.setExpirationDate(farAwayExpiration, protector)
|
.setExpirationDate(farAwayExpiration, protector)
|
||||||
.done());
|
.done());
|
||||||
|
|
||||||
Date notSoFarAwayExpiration = DateUtil.parseUTCDate("2100-01-01 00:00:00 UTC");
|
Date notSoFarAwayExpiration = DateUtil.parseUTCDate("2100-01-01 00:00:00 UTC");
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.setExpirationDate(notSoFarAwayExpiration, protector)
|
.setExpirationDate(notSoFarAwayExpiration, protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
Date actualExpiration = PGPainless.inspectKeyRing(secretKeys)
|
Date actualExpiration = api.inspect(secretKeys)
|
||||||
.getPrimaryKeyExpirationDate();
|
.getPrimaryKeyExpirationDate();
|
||||||
JUtils.assertDateEquals(notSoFarAwayExpiration, actualExpiration);
|
JUtils.assertDateEquals(notSoFarAwayExpiration, actualExpiration);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
package org.pgpainless.key.modification;
|
package org.pgpainless.key.modification;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.key.info.KeyRingInfo;
|
import org.pgpainless.key.info.KeyRingInfo;
|
||||||
|
@ -26,13 +26,14 @@ public class ChangePrimaryUserIdAndExpirationDatesTest {
|
||||||
@Test
|
@Test
|
||||||
public void generateA_primaryB_revokeA_cantSecondaryA()
|
public void generateA_primaryB_revokeA_cantSecondaryA()
|
||||||
throws PGPException {
|
throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.modernKeyRing("A")
|
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
|
.modernKeyRing("A");
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
|
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys, now);
|
KeyRingInfo info = api.inspect(secretKeys, now);
|
||||||
assertFalse(info.isHardRevoked("A"));
|
assertFalse(info.isHardRevoked("A"));
|
||||||
assertFalse(info.isHardRevoked("B"));
|
assertFalse(info.isHardRevoked("B"));
|
||||||
assertIsPrimaryUserId("A", info);
|
assertIsPrimaryUserId("A", info);
|
||||||
|
@ -41,10 +42,10 @@ public class ChangePrimaryUserIdAndExpirationDatesTest {
|
||||||
|
|
||||||
// One hour later
|
// One hour later
|
||||||
Date oneHourLater = new Date(now.getTime() + millisInHour);
|
Date oneHourLater = new Date(now.getTime() + millisInHour);
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, oneHourLater)
|
secretKeys = api.modify(secretKeys, oneHourLater)
|
||||||
.addPrimaryUserId("B", protector)
|
.addPrimaryUserId("B", protector)
|
||||||
.done();
|
.done();
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, oneHourLater);
|
info = api.inspect(secretKeys, oneHourLater);
|
||||||
|
|
||||||
assertIsPrimaryUserId("B", info);
|
assertIsPrimaryUserId("B", info);
|
||||||
assertIsNotPrimaryUserId("A", info);
|
assertIsNotPrimaryUserId("A", info);
|
||||||
|
@ -52,10 +53,10 @@ public class ChangePrimaryUserIdAndExpirationDatesTest {
|
||||||
// Two hours later
|
// Two hours later
|
||||||
Date twoHoursLater = new Date(now.getTime() + 2 * millisInHour);
|
Date twoHoursLater = new Date(now.getTime() + 2 * millisInHour);
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, twoHoursLater)
|
secretKeys = api.modify(secretKeys, twoHoursLater)
|
||||||
.revokeUserId("A", protector) // hard revoke A
|
.revokeUserId("A", protector) // hard revoke A
|
||||||
.done();
|
.done();
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, twoHoursLater);
|
info = api.inspect(secretKeys, twoHoursLater);
|
||||||
|
|
||||||
assertTrue(info.isHardRevoked("A"));
|
assertTrue(info.isHardRevoked("A"));
|
||||||
assertFalse(info.isHardRevoked("B"));
|
assertFalse(info.isHardRevoked("B"));
|
||||||
|
@ -65,71 +66,71 @@ public class ChangePrimaryUserIdAndExpirationDatesTest {
|
||||||
// Three hours later
|
// Three hours later
|
||||||
Date threeHoursLater = new Date(now.getTime() + 3 * millisInHour);
|
Date threeHoursLater = new Date(now.getTime() + 3 * millisInHour);
|
||||||
|
|
||||||
PGPSecretKeyRing finalSecretKeys = secretKeys;
|
OpenPGPKey finalSecretKeys = secretKeys;
|
||||||
assertThrows(IllegalArgumentException.class, () ->
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
PGPainless.modifyKeyRing(finalSecretKeys, threeHoursLater).addUserId("A", protector));
|
api.modify(finalSecretKeys, threeHoursLater).addUserId("A", protector));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void generateA_primaryExpire_isExpired() {
|
public void generateA_primaryExpire_isExpired() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.modernKeyRing("A")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.modernKeyRing("A");
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
assertIsPrimaryUserId("A", info);
|
assertIsPrimaryUserId("A", info);
|
||||||
|
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
Date later = new Date(now.getTime() + millisInHour);
|
Date later = new Date(now.getTime() + millisInHour);
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, now)
|
secretKeys = api.modify(secretKeys, now)
|
||||||
.setExpirationDate(later, protector) // expire the whole key
|
.setExpirationDate(later, protector) // expire the whole key
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
Date evenLater = new Date(now.getTime() + 2 * millisInHour);
|
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
|
assertFalse(info.isUserIdValid("A")); // is expired by now
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void generateA_primaryB_primaryExpire_bIsStillPrimary() {
|
public void generateA_primaryB_primaryExpire_bIsStillPrimary() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.modernKeyRing("A")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.modernKeyRing("A");
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
|
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
// Generate key with primary user-id A
|
// Generate key with primary user-id A
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
assertIsPrimaryUserId("A", info);
|
assertIsPrimaryUserId("A", info);
|
||||||
|
|
||||||
// later set primary user-id to B
|
// later set primary user-id to B
|
||||||
Date t1 = new Date(now.getTime() + millisInHour);
|
Date t1 = new Date(now.getTime() + millisInHour);
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, t1)
|
secretKeys = api.modify(secretKeys, t1)
|
||||||
.addPrimaryUserId("B", protector)
|
.addPrimaryUserId("B", protector)
|
||||||
.done();
|
.done();
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, t1);
|
info = api.inspect(secretKeys, t1);
|
||||||
assertIsPrimaryUserId("B", info);
|
assertIsPrimaryUserId("B", info);
|
||||||
assertIsNotPrimaryUserId("A", info);
|
assertIsNotPrimaryUserId("A", info);
|
||||||
|
|
||||||
// Even later expire the whole key
|
// Even later expire the whole key
|
||||||
Date t2 = new Date(now.getTime() + 2 * millisInHour);
|
Date t2 = new Date(now.getTime() + 2 * millisInHour);
|
||||||
Date expiration = new Date(now.getTime() + 10 * 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
|
.setExpirationDate(expiration, protector) // expire the whole key in 1 hour
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
Date t3 = new Date(now.getTime() + 3 * millisInHour);
|
Date t3 = new Date(now.getTime() + 3 * millisInHour);
|
||||||
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, t3);
|
info = api.inspect(secretKeys, t3);
|
||||||
assertIsValid("A", info);
|
assertIsValid("A", info);
|
||||||
assertIsValid("B", info);
|
assertIsValid("B", info);
|
||||||
assertIsPrimaryUserId("B", info);
|
assertIsPrimaryUserId("B", info);
|
||||||
assertIsNotPrimaryUserId("A", info);
|
assertIsNotPrimaryUserId("A", info);
|
||||||
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, expiration);
|
info = api.inspect(secretKeys, expiration);
|
||||||
assertIsPrimaryUserId("B", info); // B is still primary, even though
|
assertIsPrimaryUserId("B", info); // B is still primary, even though
|
||||||
assertFalse(info.isUserIdValid("A")); // key is expired by now
|
assertFalse(info.isUserIdValid("A")); // key is expired by now
|
||||||
assertFalse(info.isUserIdValid("B"));
|
assertFalse(info.isUserIdValid("B"));
|
||||||
|
@ -137,23 +138,23 @@ public class ChangePrimaryUserIdAndExpirationDatesTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void generateA_expire_certify() {
|
public void generateA_expire_certify() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("A")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().modernKeyRing("A");
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
|
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
Date t1 = new Date(now.getTime() + millisInHour);
|
Date t1 = new Date(now.getTime() + millisInHour);
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, now)
|
secretKeys = api.modify(secretKeys, now)
|
||||||
.setExpirationDate(t1, protector)
|
.setExpirationDate(t1, protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
Date t2 = new Date(now.getTime() + 2 * millisInHour);
|
Date t2 = new Date(now.getTime() + 2 * millisInHour);
|
||||||
Date t4 = new Date(now.getTime() + 4 * millisInHour);
|
Date t4 = new Date(now.getTime() + 4 * millisInHour);
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, t2)
|
secretKeys = api.modify(secretKeys, t2)
|
||||||
.setExpirationDate(t4, protector)
|
.setExpirationDate(t4, protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
assertIsValid("A", info);
|
assertIsValid("A", info);
|
||||||
assertIsPrimaryUserId("A", info);
|
assertIsPrimaryUserId("A", info);
|
||||||
}
|
}
|
||||||
|
@ -161,28 +162,28 @@ public class ChangePrimaryUserIdAndExpirationDatesTest {
|
||||||
@Test
|
@Test
|
||||||
public void generateA_expire_primaryB_expire_isPrimaryB()
|
public void generateA_expire_primaryB_expire_isPrimaryB()
|
||||||
throws PGPException {
|
throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("A")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().modernKeyRing("A");
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
|
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
Date t1 = new Date(now.getTime() + millisInHour);
|
Date t1 = new Date(now.getTime() + millisInHour);
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, t1)
|
secretKeys = api.modify(secretKeys, t1)
|
||||||
.setExpirationDate(t1, protector)
|
.setExpirationDate(t1, protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
Date t2 = new Date(now.getTime() + 2 * millisInHour);
|
Date t2 = new Date(now.getTime() + 2 * millisInHour);
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys, t2);
|
KeyRingInfo info = api.inspect(secretKeys, t2);
|
||||||
|
|
||||||
assertIsPrimaryUserId("A", info);
|
assertIsPrimaryUserId("A", info);
|
||||||
assertIsNotValid("A", info); // A is expired
|
assertIsNotValid("A", info); // A is expired
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, t2)
|
secretKeys = api.modify(secretKeys, t2)
|
||||||
.addPrimaryUserId("B", protector)
|
.addPrimaryUserId("B", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
Date t3 = new Date(now.getTime() + 3 * millisInHour);
|
Date t3 = new Date(now.getTime() + 3 * millisInHour);
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, t3);
|
info = api.inspect(secretKeys, t3);
|
||||||
|
|
||||||
assertIsPrimaryUserId("B", info);
|
assertIsPrimaryUserId("B", info);
|
||||||
assertIsNotValid("B", info); // A and B are still expired
|
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 t4 = new Date(now.getTime() + 4 * millisInHour);
|
||||||
Date t5 = new Date(now.getTime() + 5 * millisInHour);
|
Date t5 = new Date(now.getTime() + 5 * millisInHour);
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, t3)
|
secretKeys = api.modify(secretKeys, t3)
|
||||||
.setExpirationDate(t5, protector)
|
.setExpirationDate(t5, protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, t4);
|
info = api.inspect(secretKeys, t4);
|
||||||
assertIsValid("B", info);
|
assertIsValid("B", info);
|
||||||
assertIsValid("A", info); // A got re-validated when changing exp date
|
assertIsValid("A", info); // A got re-validated when changing exp date
|
||||||
assertIsPrimaryUserId("B", info);
|
assertIsPrimaryUserId("B", info);
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, t4)
|
secretKeys = api.modify(secretKeys, t4)
|
||||||
.addUserId("A", protector) // re-certify A as non-primary user-id
|
.addUserId("A", protector) // re-certify A as non-primary user-id
|
||||||
.done();
|
.done();
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, t4);
|
info = api.inspect(secretKeys, t4);
|
||||||
|
|
||||||
assertIsValid("B", info);
|
assertIsValid("B", info);
|
||||||
assertIsValid("A", info);
|
assertIsValid("A", info);
|
||||||
|
|
|
@ -15,8 +15,8 @@ import java.util.Iterator;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPImplementation;
|
import org.bouncycastle.openpgp.api.OpenPGPImplementation;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
|
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||||
import org.bouncycastle.util.io.Streams;
|
import org.bouncycastle.util.io.Streams;
|
||||||
import org.junit.jupiter.api.TestTemplate;
|
import org.junit.jupiter.api.TestTemplate;
|
||||||
|
@ -35,8 +35,8 @@ import org.pgpainless.util.Passphrase;
|
||||||
|
|
||||||
public class ChangeSecretKeyRingPassphraseTest {
|
public class ChangeSecretKeyRingPassphraseTest {
|
||||||
|
|
||||||
private final PGPSecretKeyRing keyRing = PGPainless.generateKeyRing().simpleEcKeyRing("password@encryp.ted", "weakPassphrase")
|
private final OpenPGPKey keyRing = PGPainless.getInstance()
|
||||||
.getPGPSecretKeyRing();
|
.generateKey().simpleEcKeyRing("password@encryp.ted", "weakPassphrase");
|
||||||
|
|
||||||
public ChangeSecretKeyRingPassphraseTest() {
|
public ChangeSecretKeyRingPassphraseTest() {
|
||||||
}
|
}
|
||||||
|
@ -44,66 +44,64 @@ public class ChangeSecretKeyRingPassphraseTest {
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void changePassphraseOfWholeKeyRingTest() throws PGPException {
|
public void changePassphraseOfWholeKeyRingTest() throws PGPException {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.modifyKeyRing(keyRing)
|
OpenPGPKey secretKeys = api.modify(keyRing)
|
||||||
.changePassphraseFromOldPassphrase(Passphrase.fromPassword("weakPassphrase"))
|
.changePassphraseFromOldPassphrase(Passphrase.fromPassword("weakPassphrase"))
|
||||||
.withSecureDefaultSettings()
|
.withSecureDefaultSettings()
|
||||||
.toNewPassphrase(Passphrase.fromPassword("1337p455phr453"))
|
.toNewPassphrase(Passphrase.fromPassword("1337p455phr453"))
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
PGPSecretKeyRing changedPassphraseKeyRing = secretKeys;
|
|
||||||
|
|
||||||
assertEquals(KeyRingProtectionSettings.secureDefaultSettings().getEncryptionAlgorithm().getAlgorithmId(),
|
assertEquals(KeyRingProtectionSettings.secureDefaultSettings().getEncryptionAlgorithm().getAlgorithmId(),
|
||||||
changedPassphraseKeyRing.getSecretKey().getKeyEncryptionAlgorithm());
|
secretKeys.getPGPSecretKeyRing().getSecretKey().getKeyEncryptionAlgorithm());
|
||||||
|
|
||||||
assertThrows(PGPException.class, () ->
|
assertThrows(PGPException.class, () ->
|
||||||
signDummyMessageWithKeysAndPassphrase(changedPassphraseKeyRing, Passphrase.emptyPassphrase()),
|
signDummyMessageWithKeysAndPassphrase(api, secretKeys, Passphrase.emptyPassphrase()),
|
||||||
"Unlocking secret key ring with empty passphrase MUST fail.");
|
"Unlocking secret key ring with empty passphrase MUST fail.");
|
||||||
|
|
||||||
assertThrows(PGPException.class, () ->
|
assertThrows(PGPException.class, () ->
|
||||||
signDummyMessageWithKeysAndPassphrase(changedPassphraseKeyRing, Passphrase.fromPassword("weakPassphrase")),
|
signDummyMessageWithKeysAndPassphrase(api, secretKeys, Passphrase.fromPassword("weakPassphrase")),
|
||||||
"Unlocking secret key ring with old passphrase MUST fail.");
|
"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.");
|
"Unlocking the secret key ring with the new passphrase MUST succeed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void changePassphraseOfWholeKeyRingToEmptyPassphrase() throws PGPException, IOException {
|
public void changePassphraseOfWholeKeyRingToEmptyPassphrase() throws PGPException, IOException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.modifyKeyRing(keyRing)
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
|
||||||
|
OpenPGPKey changedPassphraseKeyRing = api.modify(keyRing)
|
||||||
.changePassphraseFromOldPassphrase(Passphrase.fromPassword("weakPassphrase"))
|
.changePassphraseFromOldPassphrase(Passphrase.fromPassword("weakPassphrase"))
|
||||||
.withSecureDefaultSettings()
|
.withSecureDefaultSettings()
|
||||||
.toNoPassphrase()
|
.toNoPassphrase()
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
PGPSecretKeyRing changedPassphraseKeyRing = secretKeys;
|
|
||||||
|
|
||||||
assertEquals(SymmetricKeyAlgorithm.NULL.getAlgorithmId(),
|
assertEquals(SymmetricKeyAlgorithm.NULL.getAlgorithmId(),
|
||||||
changedPassphraseKeyRing.getSecretKey().getKeyEncryptionAlgorithm());
|
changedPassphraseKeyRing.getPGPSecretKeyRing().getSecretKey().getKeyEncryptionAlgorithm());
|
||||||
|
|
||||||
signDummyMessageWithKeysAndPassphrase(changedPassphraseKeyRing, Passphrase.emptyPassphrase());
|
signDummyMessageWithKeysAndPassphrase(api, changedPassphraseKeyRing, Passphrase.emptyPassphrase());
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void changePassphraseOfSingleSubkeyToNewPassphrase() throws PGPException {
|
public void changePassphraseOfSingleSubkeyToNewPassphrase() throws PGPException {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
Iterator<PGPSecretKey> keys = keyRing.getSecretKeys();
|
Iterator<PGPSecretKey> keys = keyRing.getPGPSecretKeyRing().getSecretKeys();
|
||||||
PGPSecretKey primaryKey = keys.next();
|
PGPSecretKey primaryKey = keys.next();
|
||||||
PGPSecretKey subKey = keys.next();
|
PGPSecretKey subKey = keys.next();
|
||||||
|
|
||||||
extractPrivateKey(primaryKey, Passphrase.fromPassword("weakPassphrase"));
|
extractPrivateKey(primaryKey, Passphrase.fromPassword("weakPassphrase"));
|
||||||
extractPrivateKey(subKey, Passphrase.fromPassword("weakPassphrase"));
|
extractPrivateKey(subKey, Passphrase.fromPassword("weakPassphrase"));
|
||||||
|
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.modifyKeyRing(keyRing)
|
OpenPGPKey secretKeys = api.modify(keyRing)
|
||||||
.changeSubKeyPassphraseFromOldPassphrase(subKey.getPublicKey().getKeyIdentifier(),
|
.changeSubKeyPassphraseFromOldPassphrase(subKey.getPublicKey().getKeyIdentifier(),
|
||||||
Passphrase.fromPassword("weakPassphrase"))
|
Passphrase.fromPassword("weakPassphrase"))
|
||||||
.withSecureDefaultSettings()
|
.withSecureDefaultSettings()
|
||||||
.toNewPassphrase(Passphrase.fromPassword("subKeyPassphrase"))
|
.toNewPassphrase(Passphrase.fromPassword("subKeyPassphrase"))
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
keys = secretKeys.getSecretKeys();
|
keys = secretKeys.getPGPSecretKeyRing().getSecretKeys();
|
||||||
primaryKey = keys.next();
|
primaryKey = keys.next();
|
||||||
subKey = keys.next();
|
subKey = keys.next();
|
||||||
|
|
||||||
|
@ -124,18 +122,18 @@ public class ChangeSecretKeyRingPassphraseTest {
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void changePassphraseOfSingleSubkeyToEmptyPassphrase() throws PGPException {
|
public void changePassphraseOfSingleSubkeyToEmptyPassphrase() throws PGPException {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
Iterator<PGPSecretKey> keys = keyRing.getSecretKeys();
|
Iterator<PGPSecretKey> keys = keyRing.getPGPSecretKeyRing().getSecretKeys();
|
||||||
PGPSecretKey primaryKey = keys.next();
|
PGPSecretKey primaryKey = keys.next();
|
||||||
PGPSecretKey subKey = keys.next();
|
PGPSecretKey subKey = keys.next();
|
||||||
|
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.modifyKeyRing(keyRing)
|
OpenPGPKey secretKeys = api.modify(keyRing)
|
||||||
.changeSubKeyPassphraseFromOldPassphrase(subKey.getKeyIdentifier(), Passphrase.fromPassword("weakPassphrase"))
|
.changeSubKeyPassphraseFromOldPassphrase(subKey.getKeyIdentifier(), Passphrase.fromPassword("weakPassphrase"))
|
||||||
.withSecureDefaultSettings()
|
.withSecureDefaultSettings()
|
||||||
.toNoPassphrase()
|
.toNoPassphrase()
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
keys = secretKeys.getSecretKeys();
|
keys = secretKeys.getPGPSecretKeyRing().getSecretKeys();
|
||||||
primaryKey = keys.next();
|
primaryKey = keys.next();
|
||||||
subKey = keys.next();
|
subKey = keys.next();
|
||||||
|
|
||||||
|
@ -176,13 +174,13 @@ public class ChangeSecretKeyRingPassphraseTest {
|
||||||
UnlockSecretKey.unlockSecretKey(secretKey, decryptor);
|
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";
|
String dummyMessage = "dummy";
|
||||||
ByteArrayOutputStream dummy = new ByteArrayOutputStream();
|
ByteArrayOutputStream dummy = new ByteArrayOutputStream();
|
||||||
EncryptionStream stream = PGPainless.encryptAndOrSign().onOutputStream(dummy)
|
EncryptionStream stream = api.generateMessage().onOutputStream(dummy)
|
||||||
.withOptions(ProducerOptions.sign(SigningOptions.get()
|
.withOptions(ProducerOptions.sign(SigningOptions.get()
|
||||||
.addInlineSignature(PasswordBasedSecretKeyRingProtector.forKey(keyRing, passphrase),
|
.addInlineSignature(PasswordBasedSecretKeyRingProtector.forKey(key, passphrase),
|
||||||
keyRing, DocumentSignatureType.BINARY_DOCUMENT)));
|
key, DocumentSignatureType.BINARY_DOCUMENT)));
|
||||||
|
|
||||||
Streams.pipeAll(new ByteArrayInputStream(dummyMessage.getBytes()), stream);
|
Streams.pipeAll(new ByteArrayInputStream(dummyMessage.getBytes()), stream);
|
||||||
stream.close();
|
stream.close();
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
package org.pgpainless.key.modification;
|
package org.pgpainless.key.modification;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.JUtils;
|
import org.junit.JUtils;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
|
@ -25,26 +25,27 @@ public class ChangeSubkeyExpirationTimeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void changeExpirationTimeOfSubkey() {
|
public void changeExpirationTimeOfSubkey() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice");
|
||||||
Date now = secretKeys.getPublicKey().getCreationTime();
|
Date now = secretKeys.getPrimaryKey().getCreationTime();
|
||||||
Date inAnHour = new Date(now.getTime() + 1000 * 60 * 60);
|
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);
|
.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0);
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.setExpirationDateOfSubkey(
|
.setExpirationDateOfSubkey(
|
||||||
inAnHour,
|
inAnHour,
|
||||||
encryptionKey.getKeyIdentifier().getKeyId(),
|
encryptionKey.getKeyIdentifier(),
|
||||||
SecretKeyRingProtector.unprotectedKeys())
|
SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
JUtils.assertDateEquals(inAnHour, PGPainless.inspectKeyRing(secretKeys)
|
JUtils.assertDateEquals(inAnHour, api.inspect(secretKeys)
|
||||||
.getSubkeyExpirationDate(OpenPgpFingerprint.of(encryptionKey.getPGPPublicKey())));
|
.getSubkeyExpirationDate(OpenPgpFingerprint.of(encryptionKey.getPGPPublicKey())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void changeExpirationTimeOfExpiredSubkey() throws IOException {
|
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" +
|
"-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||||
"Version: PGPainless\n" +
|
"Version: PGPainless\n" +
|
||||||
"Comment: CA52 4D5D E3D8 9CD9 105B BA45 3761 076B C6B5 3000\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");
|
OpenPgpFingerprint encryptionSubkey = new OpenPgpV4Fingerprint("2E541354A23C9943375EC27A3EF133ED8720D636");
|
||||||
JUtils.assertDateEquals(
|
JUtils.assertDateEquals(
|
||||||
DateUtil.parseUTCDate("2023-12-07 16:29:46 UTC"),
|
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)
|
// re-validate the subkey by setting its expiry to null (no expiry)
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.setExpirationDateOfSubkey(null, encryptionSubkey.getKeyId(), SecretKeyRingProtector.unprotectedKeys())
|
.setExpirationDateOfSubkey(null, encryptionSubkey.getKeyIdentifier(), SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
assertNull(PGPainless.inspectKeyRing(secretKeys).getSubkeyExpirationDate(encryptionSubkey));
|
assertNull(api.inspect(secretKeys).getSubkeyExpirationDate(encryptionSubkey));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
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.bouncycastle.util.io.Streams;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
|
@ -73,9 +73,10 @@ public class FixUserIdDoesNotBreakEncryptionCapabilityTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void manualReplaceUserIdWithFixedVersionDoesNotHinderEncryptionCapability() throws IOException, PGPException {
|
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();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
PGPSecretKeyRing modified = PGPainless.modifyKeyRing(secretKeys)
|
OpenPGPKey modified = api.modify(secretKeys)
|
||||||
.addUserId(userIdAfter, new SelfSignatureSubpackets.Callback() {
|
.addUserId(userIdAfter, new SelfSignatureSubpackets.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
public void modifyHashedSubpackets(SelfSignatureSubpackets hashedSubpackets) {
|
||||||
|
@ -85,8 +86,8 @@ public class FixUserIdDoesNotBreakEncryptionCapabilityTest {
|
||||||
.removeUserId(userIdBefore, protector)
|
.removeUserId(userIdBefore, protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo before = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo before = api.inspect(secretKeys);
|
||||||
KeyRingInfo after = PGPainless.inspectKeyRing(modified);
|
KeyRingInfo after = api.inspect(modified);
|
||||||
|
|
||||||
assertEquals(userIdBefore, before.getPrimaryUserId());
|
assertEquals(userIdBefore, before.getPrimaryUserId());
|
||||||
assertEquals(userIdAfter, after.getPrimaryUserId());
|
assertEquals(userIdAfter, after.getPrimaryUserId());
|
||||||
|
@ -104,34 +105,38 @@ public class FixUserIdDoesNotBreakEncryptionCapabilityTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReplaceUserId_missingOldUserIdThrows() throws IOException {
|
public void testReplaceUserId_missingOldUserIdThrows() throws IOException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(SECRET_KEY);
|
PGPainless api = PGPainless.getInstance();
|
||||||
assertThrows(NoSuchElementException.class, () -> PGPainless.modifyKeyRing(secretKeys)
|
OpenPGPKey secretKeys = api.readKey().parseKey(SECRET_KEY);
|
||||||
|
assertThrows(NoSuchElementException.class, () -> api.modify(secretKeys)
|
||||||
.replaceUserId("missing", userIdAfter, SecretKeyRingProtector.unprotectedKeys()));
|
.replaceUserId("missing", userIdAfter, SecretKeyRingProtector.unprotectedKeys()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReplaceUserId_emptyOldUserIdThrows() throws IOException {
|
public void testReplaceUserId_emptyOldUserIdThrows() throws IOException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(SECRET_KEY);
|
PGPainless api = PGPainless.getInstance();
|
||||||
assertThrows(IllegalArgumentException.class, () -> PGPainless.modifyKeyRing(secretKeys)
|
OpenPGPKey secretKeys = api.readKey().parseKey(SECRET_KEY);
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> api.modify(secretKeys)
|
||||||
.replaceUserId(" ", userIdAfter, SecretKeyRingProtector.unprotectedKeys()));
|
.replaceUserId(" ", userIdAfter, SecretKeyRingProtector.unprotectedKeys()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReplaceUserId_emptyNewUserIdThrows() throws IOException {
|
public void testReplaceUserId_emptyNewUserIdThrows() throws IOException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(SECRET_KEY);
|
PGPainless api = PGPainless.getInstance();
|
||||||
assertThrows(IllegalArgumentException.class, () -> PGPainless.modifyKeyRing(secretKeys)
|
OpenPGPKey secretKeys = api.readKey().parseKey(SECRET_KEY);
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> api.modify(secretKeys)
|
||||||
.replaceUserId(userIdBefore, " ", SecretKeyRingProtector.unprotectedKeys()));
|
.replaceUserId(userIdBefore, " ", SecretKeyRingProtector.unprotectedKeys()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReplaceImplicitUserIdDoesNotBreakStuff() throws IOException, PGPException {
|
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())
|
.replaceUserId(userIdBefore, userIdAfter, SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(edited);
|
KeyRingInfo info = api.inspect(edited);
|
||||||
assertTrue(info.isUserIdValid(userIdAfter));
|
assertTrue(info.isUserIdValid(userIdAfter));
|
||||||
assertEquals(userIdAfter, info.getPrimaryUserId());
|
assertEquals(userIdAfter, info.getPrimaryUserId());
|
||||||
|
|
||||||
|
@ -139,10 +144,10 @@ public class FixUserIdDoesNotBreakEncryptionCapabilityTest {
|
||||||
assertNotNull(latestCertification);
|
assertNotNull(latestCertification);
|
||||||
assertTrue(latestCertification.getHashedSubPackets().isPrimaryUserID());
|
assertTrue(latestCertification.getHashedSubPackets().isPrimaryUserID());
|
||||||
|
|
||||||
PGPPublicKeyRing cert = PGPainless.extractCertificate(edited);
|
OpenPGPCertificate cert = edited.toCertificate();
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
|
EncryptionStream encryptionStream = api.generateMessage()
|
||||||
.onOutputStream(out)
|
.onOutputStream(out)
|
||||||
.withOptions(ProducerOptions.encrypt(EncryptionOptions.get()
|
.withOptions(ProducerOptions.encrypt(EncryptionOptions.get()
|
||||||
.addRecipient(cert)));
|
.addRecipient(cert)));
|
||||||
|
@ -151,7 +156,7 @@ public class FixUserIdDoesNotBreakEncryptionCapabilityTest {
|
||||||
encryptionStream.close();
|
encryptionStream.close();
|
||||||
|
|
||||||
EncryptionResult result = encryptionStream.getResult();
|
EncryptionResult result = encryptionStream.getResult();
|
||||||
assertTrue(result.isEncryptedFor(cert));
|
assertTrue(result.isEncryptedFor(cert.getPGPPublicKeyRing()));
|
||||||
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||||
ByteArrayOutputStream plain = new ByteArrayOutputStream();
|
ByteArrayOutputStream plain = new ByteArrayOutputStream();
|
||||||
|
|
|
@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
|
@ -166,17 +166,18 @@ public class GnuDummyS2KChangePassphraseTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChangePassphraseToNoPassphraseIgnoresGnuDummyS2KKeys() throws PGPException, IOException {
|
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)
|
.changePassphraseFromOldPassphrase(passphrase)
|
||||||
.withSecureDefaultSettings()
|
.withSecureDefaultSettings()
|
||||||
.toNoPassphrase()
|
.toNoPassphrase()
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
assertTrue(PGPainless.inspectKeyRing(secretKey).isFullyDecrypted());
|
assertTrue(api.inspect(secretKey).isFullyDecrypted());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.TestTemplate;
|
import org.junit.jupiter.api.TestTemplate;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
|
@ -26,11 +26,11 @@ public class OldSignatureSubpacketsArePreservedOnNewSigTest {
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void verifyOldSignatureSubpacketsArePreservedOnNewExpirationDateSig() {
|
public void verifyOldSignatureSubpacketsArePreservedOnNewExpirationDateSig() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.simpleEcKeyRing("Alice <alice@wonderland.lit>")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.simpleEcKeyRing("Alice <alice@wonderland.lit>");
|
||||||
|
|
||||||
PGPSignature oldSignature = PGPainless.inspectKeyRing(secretKeys).getLatestUserIdCertification("Alice <alice@wonderland.lit>");
|
PGPSignature oldSignature = api.inspect(secretKeys).getLatestUserIdCertification("Alice <alice@wonderland.lit>");
|
||||||
assertNotNull(oldSignature);
|
assertNotNull(oldSignature);
|
||||||
PGPSignatureSubpacketVector oldPackets = oldSignature.getHashedSubPackets();
|
PGPSignatureSubpacketVector oldPackets = oldSignature.getHashedSubPackets();
|
||||||
|
|
||||||
|
@ -40,10 +40,10 @@ public class OldSignatureSubpacketsArePreservedOnNewSigTest {
|
||||||
Date t1 = new Date(now.getTime() + millisInHour);
|
Date t1 = new Date(now.getTime() + millisInHour);
|
||||||
Date expiration = new Date(now.getTime() + 5 * 24 * millisInHour); // in 5 days
|
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())
|
.setExpirationDate(expiration, new UnprotectedKeysProtector())
|
||||||
.done();
|
.done();
|
||||||
PGPSignature newSignature = PGPainless.inspectKeyRing(secretKeys, t1).getLatestUserIdCertification("Alice <alice@wonderland.lit>");
|
PGPSignature newSignature = api.inspect(secretKeys, t1).getLatestUserIdCertification("Alice <alice@wonderland.lit>");
|
||||||
assertNotNull(newSignature);
|
assertNotNull(newSignature);
|
||||||
PGPSignatureSubpacketVector newPackets = newSignature.getHashedSubPackets();
|
PGPSignatureSubpacketVector newPackets = newSignature.getHashedSubPackets();
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.algorithm.EncryptionPurpose;
|
import org.pgpainless.algorithm.EncryptionPurpose;
|
||||||
|
@ -28,31 +28,31 @@ public class RefuseToAddWeakSubkeyTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEditorRefusesToAddWeakSubkey() {
|
public void testEditorRefusesToAddWeakSubkey() {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
// ensure default policy is set
|
// ensure default policy is set
|
||||||
Policy oldPolicy = PGPainless.getPolicy();
|
Policy oldPolicy = api.getAlgorithmPolicy();
|
||||||
Policy adjusted = oldPolicy.copy().withPublicKeyAlgorithmPolicy(
|
Policy adjusted = oldPolicy.copy().withPublicKeyAlgorithmPolicy(
|
||||||
Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()
|
Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()
|
||||||
).build();
|
).build();
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(adjusted);
|
api.setAlgorithmPolicy(adjusted);
|
||||||
|
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.modernKeyRing("Alice")
|
.modernKeyRing("Alice");
|
||||||
.getPGPSecretKeyRing();
|
SecretKeyRingEditorInterface editor = api.modify(secretKeys);
|
||||||
SecretKeyRingEditorInterface editor = PGPainless.modifyKeyRing(secretKeys);
|
|
||||||
KeySpec spec = KeySpec.getBuilder(KeyType.RSA(RsaLength._1024), KeyFlag.ENCRYPT_COMMS).build();
|
KeySpec spec = KeySpec.getBuilder(KeyType.RSA(RsaLength._1024), KeyFlag.ENCRYPT_COMMS).build();
|
||||||
|
|
||||||
assertThrows(IllegalArgumentException.class, () ->
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys()));
|
editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys()));
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy);
|
api.setAlgorithmPolicy(oldPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEditorAllowsToAddWeakSubkeyIfCompliesToPublicKeyAlgorithmPolicy() {
|
public void testEditorAllowsToAddWeakSubkeyIfCompliesToPublicKeyAlgorithmPolicy() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.modernKeyRing("Alice")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.modernKeyRing("Alice");
|
||||||
|
|
||||||
Policy oldPolicy = PGPainless.getPolicy();
|
Policy oldPolicy = api.getAlgorithmPolicy();
|
||||||
|
|
||||||
// set weak policy
|
// set weak policy
|
||||||
Map<PublicKeyAlgorithm, Integer> minimalBitStrengths = new EnumMap<>(PublicKeyAlgorithm.class);
|
Map<PublicKeyAlgorithm, Integer> minimalBitStrengths = new EnumMap<>(PublicKeyAlgorithm.class);
|
||||||
|
@ -75,11 +75,11 @@ public class RefuseToAddWeakSubkeyTest {
|
||||||
minimalBitStrengths.put(PublicKeyAlgorithm.DIFFIE_HELLMAN, 2000);
|
minimalBitStrengths.put(PublicKeyAlgorithm.DIFFIE_HELLMAN, 2000);
|
||||||
// §7.2.2
|
// §7.2.2
|
||||||
minimalBitStrengths.put(PublicKeyAlgorithm.ECDH, 250);
|
minimalBitStrengths.put(PublicKeyAlgorithm.ECDH, 250);
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy.copy()
|
api.setAlgorithmPolicy(oldPolicy.copy()
|
||||||
.withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(minimalBitStrengths))
|
.withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(minimalBitStrengths))
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
SecretKeyRingEditorInterface editor = PGPainless.modifyKeyRing(secretKeys);
|
SecretKeyRingEditorInterface editor = api.modify(secretKeys);
|
||||||
KeySpec spec = KeySpec.getBuilder(KeyType.RSA(RsaLength._1024), KeyFlag.ENCRYPT_COMMS)
|
KeySpec spec = KeySpec.getBuilder(KeyType.RSA(RsaLength._1024), KeyFlag.ENCRYPT_COMMS)
|
||||||
.setKeyCreationDate(editor.getReferenceTime()) // The key gets created after we instantiate the editor.
|
.setKeyCreationDate(editor.getReferenceTime()) // The key gets created after we instantiate the editor.
|
||||||
.build();
|
.build();
|
||||||
|
@ -87,9 +87,9 @@ public class RefuseToAddWeakSubkeyTest {
|
||||||
secretKeys = editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys())
|
secretKeys = editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
assertEquals(2, PGPainless.inspectKeyRing(secretKeys).getEncryptionSubkeys(EncryptionPurpose.ANY).size());
|
assertEquals(2, api.inspect(secretKeys).getEncryptionSubkeys(EncryptionPurpose.ANY).size());
|
||||||
|
|
||||||
// reset default policy
|
// reset default policy
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy);
|
api.setAlgorithmPolicy(oldPolicy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,10 @@ import java.io.IOException;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
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.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.key.TestKeys;
|
import org.pgpainless.key.TestKeys;
|
||||||
|
@ -30,9 +31,10 @@ public class RevocationCertificateTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createRevocationCertificateTest() throws PGPException, IOException {
|
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(),
|
.createRevocation(SecretKeyRingProtector.unprotectedKeys(),
|
||||||
RevocationAttributes.createKeyRevocation()
|
RevocationAttributes.createKeyRevocation()
|
||||||
.withReason(RevocationAttributes.Reason.KEY_RETIRED)
|
.withReason(RevocationAttributes.Reason.KEY_RETIRED)
|
||||||
|
@ -40,66 +42,68 @@ public class RevocationCertificateTest {
|
||||||
|
|
||||||
assertNotNull(revocation);
|
assertNotNull(revocation);
|
||||||
|
|
||||||
assertTrue(PGPainless.inspectKeyRing(secretKeys).isKeyValidlyBound(secretKeys.getPublicKey().getKeyID()));
|
assertTrue(api.inspect(secretKeys).isKeyValidlyBound(secretKeys.getKeyIdentifier()));
|
||||||
|
|
||||||
// merge key and revocation certificate
|
// merge key and revocation certificate
|
||||||
PGPSecretKeyRing revokedKey = KeyRingUtils.keysPlusSecretKey(
|
PGPSecretKeyRing revokedKey = KeyRingUtils.keysPlusSecretKey(
|
||||||
secretKeys,
|
secretKeys.getPGPSecretKeyRing(),
|
||||||
KeyRingUtils.secretKeyPlusSignature(secretKeys.getSecretKey(), revocation));
|
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
|
@Test
|
||||||
public void createMinimalRevocationCertificateTest() throws PGPException, IOException {
|
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(),
|
SecretKeyRingProtector.unprotectedKeys(),
|
||||||
RevocationAttributes.createKeyRevocation().withReason(RevocationAttributes.Reason.KEY_RETIRED).withoutDescription());
|
RevocationAttributes.createKeyRevocation().withReason(RevocationAttributes.Reason.KEY_RETIRED).withoutDescription());
|
||||||
|
|
||||||
assertEquals(1, minimalRevocationCert.size());
|
assertEquals(1, minimalRevocationCert.getPGPKeyRing().size());
|
||||||
PGPPublicKey key = minimalRevocationCert.getPublicKey();
|
PGPPublicKey key = minimalRevocationCert.getPrimaryKey().getPGPPublicKey();
|
||||||
assertEquals(secretKeys.getPublicKey().getKeyID(), key.getKeyID());
|
assertEquals(secretKeys.getKeyIdentifier(), key.getKeyIdentifier());
|
||||||
assertEquals(1, CollectionUtils.iteratorToList(key.getSignatures()).size());
|
assertEquals(1, CollectionUtils.iteratorToList(key.getSignatures()).size());
|
||||||
assertFalse(key.getUserIDs().hasNext());
|
assertFalse(key.getUserIDs().hasNext());
|
||||||
assertFalse(key.getUserAttributes().hasNext());
|
assertFalse(key.getUserAttributes().hasNext());
|
||||||
assertNull(key.getTrustData());
|
assertNull(key.getTrustData());
|
||||||
|
|
||||||
PGPPublicKeyRing originalCert = PGPainless.extractCertificate(secretKeys);
|
OpenPGPCertificate originalCert = secretKeys.toCertificate();
|
||||||
PGPPublicKeyRing mergedCert = PGPainless.mergeCertificate(originalCert, minimalRevocationCert);
|
OpenPGPCertificate mergedCert = api.mergeCertificate(originalCert, minimalRevocationCert);
|
||||||
|
|
||||||
assertTrue(PGPainless.inspectKeyRing(mergedCert).getRevocationState().isSoftRevocation());
|
assertTrue(api.inspect(mergedCert).getRevocationState().isSoftRevocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createMinimalRevocationCertificateForFreshKeyTest() {
|
public void createMinimalRevocationCertificateForFreshKeyTest() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@example.org>")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice <alice@example.org>");
|
||||||
|
|
||||||
PGPPublicKeyRing minimalRevocationCert = PGPainless.modifyKeyRing(secretKeys).createMinimalRevocationCertificate(
|
OpenPGPCertificate minimalRevocationCert = api.modify(secretKeys).createMinimalRevocationCertificate(
|
||||||
SecretKeyRingProtector.unprotectedKeys(),
|
SecretKeyRingProtector.unprotectedKeys(),
|
||||||
RevocationAttributes.createKeyRevocation().withReason(RevocationAttributes.Reason.KEY_RETIRED).withoutDescription());
|
RevocationAttributes.createKeyRevocation().withReason(RevocationAttributes.Reason.KEY_RETIRED).withoutDescription());
|
||||||
|
|
||||||
assertEquals(1, minimalRevocationCert.size());
|
assertEquals(1, minimalRevocationCert.getKeys().size());
|
||||||
PGPPublicKey key = minimalRevocationCert.getPublicKey();
|
PGPPublicKey key = minimalRevocationCert.getPGPPublicKeyRing().getPublicKey();
|
||||||
assertEquals(secretKeys.getPublicKey().getKeyID(), key.getKeyID());
|
assertEquals(secretKeys.getKeyIdentifier(), key.getKeyIdentifier());
|
||||||
assertEquals(1, CollectionUtils.iteratorToList(key.getSignatures()).size());
|
assertEquals(1, CollectionUtils.iteratorToList(key.getSignatures()).size());
|
||||||
assertFalse(key.getUserIDs().hasNext());
|
assertFalse(key.getUserIDs().hasNext());
|
||||||
assertFalse(key.getUserAttributes().hasNext());
|
assertFalse(key.getUserAttributes().hasNext());
|
||||||
assertNull(key.getTrustData());
|
assertNull(key.getTrustData());
|
||||||
|
|
||||||
PGPPublicKeyRing originalCert = PGPainless.extractCertificate(secretKeys);
|
OpenPGPCertificate originalCert = secretKeys.toCertificate();
|
||||||
PGPPublicKeyRing mergedCert = PGPainless.mergeCertificate(originalCert, minimalRevocationCert);
|
OpenPGPCertificate mergedCert = api.mergeCertificate(originalCert, minimalRevocationCert);
|
||||||
|
|
||||||
assertTrue(PGPainless.inspectKeyRing(mergedCert).getRevocationState().isSoftRevocation());
|
assertTrue(api.inspect(mergedCert).getRevocationState().isSoftRevocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createMinimalRevocationCertificate_wrongReason() throws PGPException, IOException {
|
public void createMinimalRevocationCertificate_wrongReason() throws PGPException, IOException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey secretKeys = TestKeys.getEmilKey();
|
||||||
assertThrows(IllegalArgumentException.class,
|
assertThrows(IllegalArgumentException.class,
|
||||||
() -> PGPainless.modifyKeyRing(secretKeys).createMinimalRevocationCertificate(
|
() -> api.modify(secretKeys).createMinimalRevocationCertificate(
|
||||||
SecretKeyRingProtector.unprotectedKeys(),
|
SecretKeyRingProtector.unprotectedKeys(),
|
||||||
RevocationAttributes.createCertificateRevocation()
|
RevocationAttributes.createCertificateRevocation()
|
||||||
.withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID)
|
.withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID)
|
||||||
|
|
|
@ -7,13 +7,14 @@ package org.pgpainless.key.modification;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.TestTemplate;
|
import org.junit.jupiter.api.TestTemplate;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.pgpainless.PGPainless;
|
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
|
* Test that makes sure that PGPainless can deal with keys that carry a key
|
||||||
* signature of type 0x10 (generic certification).
|
* signature of type 0x10 (generic certification).
|
||||||
*
|
* <p>
|
||||||
* Originally PGPainless would only handle keys with key signature type
|
* Originally PGPainless would only handle keys with key signature type
|
||||||
* 0x13 (positive certification) and would otherwise crash when negotiating
|
* 0x13 (positive certification) and would otherwise crash when negotiating
|
||||||
* algorithms, esp. when revoking a key.
|
* algorithms, esp. when revoking a key.
|
||||||
|
@ -70,23 +71,26 @@ public class RevokeKeyWithGenericCertificationSignatureTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeyPair revokeKey(String priv) throws IOException, PGPException {
|
private KeyPair revokeKey(String priv) throws IOException, PGPException {
|
||||||
byte[] armoredBytes = priv.getBytes(StandardCharsets.UTF_8);
|
PGPainless api = PGPainless.getInstance();
|
||||||
PGPSecretKeyRing r = PGPainless.readKeyRing()
|
OpenPGPKey key = api.readKey().parseKey(priv);
|
||||||
.secretKeyRing(armoredBytes);
|
OpenPGPKey onlyPrimaryKey = api.toKey(
|
||||||
PGPSecretKey secretKey = r.getSecretKey();
|
new PGPSecretKeyRing(
|
||||||
|
Collections.singletonList(key.getPrimarySecretKey().getPGPSecretKey())
|
||||||
|
)
|
||||||
|
);
|
||||||
// this is not ideal, but still valid usage
|
// this is not ideal, but still valid usage
|
||||||
PGPSecretKeyRing secretKeyRing =
|
OpenPGPKey revokedPrimaryKey =
|
||||||
PGPainless.modifyKeyRing(new PGPSecretKeyRing(Arrays.asList(secretKey)))
|
api.modify(onlyPrimaryKey)
|
||||||
.revoke(new UnprotectedKeysProtector()).done();
|
.revoke(new UnprotectedKeysProtector()).done();
|
||||||
|
|
||||||
PGPPublicKey pkr = secretKeyRing.getPublicKeys().next();
|
PGPPublicKey pkr = revokedPrimaryKey.getPGPSecretKeyRing().getPublicKeys().next();
|
||||||
ByteArrayOutputStream pubOutBytes = new ByteArrayOutputStream();
|
ByteArrayOutputStream pubOutBytes = new ByteArrayOutputStream();
|
||||||
try (ArmoredOutputStream pubOut = ArmoredOutputStreamFactory.get(pubOutBytes)) {
|
try (ArmoredOutputStream pubOut = ArmoredOutputStreamFactory.get(pubOutBytes)) {
|
||||||
pkr.encode(pubOut);
|
pkr.encode(pubOut);
|
||||||
}
|
}
|
||||||
pubOutBytes.close();
|
pubOutBytes.close();
|
||||||
|
|
||||||
PGPSecretKey skr = secretKeyRing.getSecretKeys().next();
|
PGPSecretKey skr = revokedPrimaryKey.getPGPSecretKeyRing().getSecretKeys().next();
|
||||||
ByteArrayOutputStream secOutBytes = new ByteArrayOutputStream();
|
ByteArrayOutputStream secOutBytes = new ByteArrayOutputStream();
|
||||||
try (ArmoredOutputStream privOut = ArmoredOutputStreamFactory.get(secOutBytes)) {
|
try (ArmoredOutputStream privOut = ArmoredOutputStreamFactory.get(secOutBytes)) {
|
||||||
skr.encode(privOut);
|
skr.encode(privOut);
|
||||||
|
|
|
@ -7,7 +7,7 @@ package org.pgpainless.key.modification;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.JUtils;
|
import org.junit.JUtils;
|
||||||
import org.junit.jupiter.api.TestTemplate;
|
import org.junit.jupiter.api.TestTemplate;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
@ -99,16 +99,17 @@ public class RevokeKeyWithoutPreferredAlgorithmsOnPrimaryKey {
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void testChangingExpirationTimeWithKeyWithoutPrefAlgos()
|
public void testChangingExpirationTimeWithKeyWithoutPrefAlgos()
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
Date expirationDate = DateUtil.now();
|
Date expirationDate = DateUtil.now();
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(KEY);
|
OpenPGPKey secretKeys = api.readKey().parseKey(KEY);
|
||||||
|
|
||||||
SecretKeyRingProtector protector = new UnprotectedKeysProtector();
|
SecretKeyRingProtector protector = new UnprotectedKeysProtector();
|
||||||
|
|
||||||
SecretKeyRingEditorInterface modify = PGPainless.modifyKeyRing(secretKeys)
|
SecretKeyRingEditorInterface modify = api.modify(secretKeys)
|
||||||
.setExpirationDate(expirationDate, protector);
|
.setExpirationDate(expirationDate, protector);
|
||||||
secretKeys = modify.done();
|
secretKeys = modify.done();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
|
|
||||||
JUtils.assertDateEquals(expirationDate, info.getPrimaryKeyExpirationDate());
|
JUtils.assertDateEquals(expirationDate, info.getPrimaryKeyExpirationDate());
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,9 @@ import org.bouncycastle.bcpg.sig.IssuerFingerprint;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
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.Test;
|
||||||
import org.junit.jupiter.api.TestTemplate;
|
import org.junit.jupiter.api.TestTemplate;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
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.PasswordBasedSecretKeyRingProtector;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.util.RevocationAttributes;
|
import org.pgpainless.key.util.RevocationAttributes;
|
||||||
import org.pgpainless.signature.SignatureUtils;
|
|
||||||
import org.pgpainless.signature.subpackets.RevocationSignatureSubpackets;
|
import org.pgpainless.signature.subpackets.RevocationSignatureSubpackets;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||||
import org.pgpainless.util.TestAllImplementations;
|
import org.pgpainless.util.TestAllImplementations;
|
||||||
|
@ -43,10 +43,11 @@ public class RevokeSubKeyTest {
|
||||||
|
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void revokeSukeyTest() throws IOException, PGPException {
|
public void revokeSubkeyTest() throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey secretKeys = TestKeys.getCryptieKey();
|
||||||
|
|
||||||
Iterator<PGPSecretKey> keysIterator = secretKeys.iterator();
|
Iterator<PGPSecretKey> keysIterator = secretKeys.getPGPSecretKeyRing().iterator();
|
||||||
PGPSecretKey primaryKey = keysIterator.next();
|
PGPSecretKey primaryKey = keysIterator.next();
|
||||||
PGPSecretKey subKey = keysIterator.next();
|
PGPSecretKey subKey = keysIterator.next();
|
||||||
|
|
||||||
|
@ -55,10 +56,10 @@ public class RevokeSubKeyTest {
|
||||||
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector
|
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector
|
||||||
.forKey(secretKeys, Passphrase.fromPassword("password123"));
|
.forKey(secretKeys, Passphrase.fromPassword("password123"));
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.revokeSubKey(new OpenPgpV4Fingerprint(subKey), protector)
|
.revokeSubKey(new OpenPgpV4Fingerprint(subKey), protector)
|
||||||
.done();
|
.done();
|
||||||
keysIterator = secretKeys.iterator();
|
keysIterator = secretKeys.getPGPSecretKeyRing().iterator();
|
||||||
primaryKey = keysIterator.next();
|
primaryKey = keysIterator.next();
|
||||||
subKey = keysIterator.next();
|
subKey = keysIterator.next();
|
||||||
|
|
||||||
|
@ -68,19 +69,20 @@ public class RevokeSubKeyTest {
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void detachedRevokeSubkeyTest() throws IOException, PGPException {
|
public void detachedRevokeSubkeyTest() throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey secretKeys = TestKeys.getCryptieKey();
|
||||||
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(secretKeys);
|
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(secretKeys);
|
||||||
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector.forKey(secretKeys, Passphrase.fromPassword("password123"));
|
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector.forKey(secretKeys, Passphrase.fromPassword("password123"));
|
||||||
|
|
||||||
PGPSignature revocationCertificate = PGPainless.modifyKeyRing(secretKeys)
|
OpenPGPSignature revocationCertificate = api.modify(secretKeys)
|
||||||
.createRevocation(fingerprint, protector, RevocationAttributes.createKeyRevocation()
|
.createRevocation(fingerprint, protector, RevocationAttributes.createKeyRevocation()
|
||||||
.withReason(RevocationAttributes.Reason.KEY_RETIRED)
|
.withReason(RevocationAttributes.Reason.KEY_RETIRED)
|
||||||
.withDescription("Key no longer used."));
|
.withDescription("Key no longer used."));
|
||||||
|
|
||||||
PGPPublicKey publicKey = secretKeys.getPublicKey();
|
PGPPublicKey publicKey = secretKeys.getPGPSecretKeyRing().getPublicKey();
|
||||||
assertFalse(publicKey.hasRevocation());
|
assertFalse(publicKey.hasRevocation());
|
||||||
|
|
||||||
publicKey = PGPPublicKey.addCertification(publicKey, revocationCertificate);
|
publicKey = PGPPublicKey.addCertification(publicKey, revocationCertificate.getSignature());
|
||||||
|
|
||||||
assertTrue(publicKey.hasRevocation());
|
assertTrue(publicKey.hasRevocation());
|
||||||
}
|
}
|
||||||
|
@ -88,19 +90,20 @@ public class RevokeSubKeyTest {
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void testRevocationSignatureTypeCorrect() throws IOException, PGPException {
|
public void testRevocationSignatureTypeCorrect() throws IOException, PGPException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
PGPainless api = PGPainless.getInstance();
|
||||||
Iterator<PGPPublicKey> keysIterator = secretKeys.getPublicKeys();
|
OpenPGPKey secretKeys = TestKeys.getCryptieKey();
|
||||||
|
Iterator<PGPPublicKey> keysIterator = secretKeys.getPGPKeyRing().getPublicKeys();
|
||||||
PGPPublicKey primaryKey = keysIterator.next();
|
PGPPublicKey primaryKey = keysIterator.next();
|
||||||
PGPPublicKey subKey = keysIterator.next();
|
PGPPublicKey subKey = keysIterator.next();
|
||||||
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector
|
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector
|
||||||
.forKey(secretKeys, Passphrase.fromPassword("password123"));
|
.forKey(secretKeys, Passphrase.fromPassword("password123"));
|
||||||
|
|
||||||
SecretKeyRingEditorInterface editor = PGPainless.modifyKeyRing(secretKeys);
|
SecretKeyRingEditorInterface editor = api.modify(secretKeys);
|
||||||
PGPSignature keyRevocation = editor.createRevocation(primaryKey.getKeyID(), protector, (RevocationAttributes) null);
|
OpenPGPSignature keyRevocation = editor.createRevocation(primaryKey.getKeyIdentifier(), protector, (RevocationAttributes) null);
|
||||||
PGPSignature subkeyRevocation = editor.createRevocation(subKey.getKeyID(), protector, (RevocationAttributes) null);
|
OpenPGPSignature subkeyRevocation = editor.createRevocation(subKey.getKeyIdentifier(), protector, (RevocationAttributes) null);
|
||||||
|
|
||||||
assertEquals(SignatureType.KEY_REVOCATION.getCode(), keyRevocation.getSignatureType());
|
assertEquals(SignatureType.KEY_REVOCATION.getCode(), keyRevocation.getSignature().getSignatureType());
|
||||||
assertEquals(SignatureType.SUBKEY_REVOCATION.getCode(), subkeyRevocation.getSignatureType());
|
assertEquals(SignatureType.SUBKEY_REVOCATION.getCode(), subkeyRevocation.getSignature().getSignatureType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -126,39 +129,39 @@ public class RevokeSubKeyTest {
|
||||||
@Test
|
@Test
|
||||||
public void inspectSubpacketsOnDefaultRevocationSignature()
|
public void inspectSubpacketsOnDefaultRevocationSignature()
|
||||||
throws PGPException {
|
throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice");
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
PGPPublicKey encryptionSubkey = PGPainless.inspectKeyRing(secretKeys)
|
PGPPublicKey encryptionSubkey = api.inspect(secretKeys)
|
||||||
.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0).getPGPPublicKey();
|
.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0).getPGPPublicKey();
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.revokeSubKey(encryptionSubkey.getKeyID(), protector)
|
.revokeSubKey(encryptionSubkey.getKeyIdentifier(), protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
encryptionSubkey = secretKeys.getPublicKey(encryptionSubkey.getKeyID());
|
encryptionSubkey = secretKeys.getPGPSecretKeyRing().getPublicKey(encryptionSubkey.getKeyIdentifier());
|
||||||
PGPSignature revocation = encryptionSubkey.getSignaturesOfType(SignatureType.SUBKEY_REVOCATION.getCode()).next();
|
PGPSignature revocation = encryptionSubkey.getSignaturesOfType(SignatureType.SUBKEY_REVOCATION.getCode()).next();
|
||||||
assertNotNull(revocation);
|
assertNotNull(revocation);
|
||||||
|
|
||||||
assertArrayEquals(
|
assertArrayEquals(
|
||||||
secretKeys.getPublicKey().getFingerprint(),
|
secretKeys.getPGPSecretKeyRing().getPublicKey().getFingerprint(),
|
||||||
revocation.getHashedSubPackets().getIssuerFingerprint().getFingerprint());
|
revocation.getHashedSubPackets().getIssuerFingerprint().getFingerprint());
|
||||||
assertEquals(secretKeys.getPublicKey().getKeyID(),
|
assertEquals(secretKeys.getPGPSecretKeyRing().getPublicKey().getKeyID(),
|
||||||
revocation.getHashedSubPackets().getIssuerKeyID());
|
revocation.getHashedSubPackets().getIssuerKeyID());
|
||||||
assertNull(SignatureSubpacketsUtil.getRevocationReason(revocation));
|
assertNull(SignatureSubpacketsUtil.getRevocationReason(revocation));
|
||||||
assertTrue(SignatureUtils.isHardRevocation(revocation));
|
assertTrue(revocation.isHardRevocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void inspectSubpacketsOnModifiedRevocationSignature() {
|
public void inspectSubpacketsOnModifiedRevocationSignature() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().modernKeyRing("Alice")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().modernKeyRing("Alice");
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
PGPPublicKey encryptionSubkey = PGPainless.inspectKeyRing(secretKeys)
|
PGPPublicKey encryptionSubkey = api.inspect(secretKeys)
|
||||||
.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0).getPGPPublicKey();
|
.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0).getPGPPublicKey();
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.revokeSubKey(encryptionSubkey.getKeyID(), protector, new RevocationSignatureSubpackets.Callback() {
|
.revokeSubKey(encryptionSubkey.getKeyIdentifier(), protector, new RevocationSignatureSubpackets.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void modifyHashedSubpackets(RevocationSignatureSubpackets hashedSubpackets) {
|
public void modifyHashedSubpackets(RevocationSignatureSubpackets hashedSubpackets) {
|
||||||
hashedSubpackets.setRevocationReason(
|
hashedSubpackets.setRevocationReason(
|
||||||
|
@ -171,14 +174,14 @@ public class RevokeSubKeyTest {
|
||||||
})
|
})
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
encryptionSubkey = secretKeys.getPublicKey(encryptionSubkey.getKeyID());
|
encryptionSubkey = secretKeys.getPGPSecretKeyRing().getPublicKey(encryptionSubkey.getKeyIdentifier());
|
||||||
PGPSignature revocation = encryptionSubkey.getSignaturesOfType(SignatureType.SUBKEY_REVOCATION.getCode()).next();
|
PGPSignature revocation = encryptionSubkey.getSignaturesOfType(SignatureType.SUBKEY_REVOCATION.getCode()).next();
|
||||||
assertNotNull(revocation);
|
assertNotNull(revocation);
|
||||||
|
|
||||||
assertNull(revocation.getHashedSubPackets().getIssuerFingerprint());
|
assertNull(revocation.getHashedSubPackets().getIssuerFingerprint());
|
||||||
assertEquals(secretKeys.getPublicKey().getKeyID(),
|
assertEquals(secretKeys.getKeyIdentifier().getKeyId(),
|
||||||
revocation.getHashedSubPackets().getIssuerKeyID());
|
revocation.getHashedSubPackets().getIssuerKeyID());
|
||||||
assertNotNull(SignatureSubpacketsUtil.getRevocationReason(revocation));
|
assertNotNull(SignatureSubpacketsUtil.getRevocationReason(revocation));
|
||||||
assertFalse(SignatureUtils.isHardRevocation(revocation));
|
assertFalse(revocation.isHardRevocation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,46 +13,45 @@ import java.util.Date;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.key.info.KeyRingInfo;
|
import org.pgpainless.key.info.KeyRingInfo;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.util.RevocationAttributes;
|
import org.pgpainless.key.util.RevocationAttributes;
|
||||||
import org.pgpainless.util.selection.userid.SelectUserId;
|
|
||||||
|
|
||||||
public class RevokeUserIdsTest {
|
public class RevokeUserIdsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void revokeWithSelectUserId() throws PGPException {
|
public void revokeWithSelectUserId() throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.modernKeyRing("Alice <alice@pgpainless.org>")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.modernKeyRing("Alice <alice@pgpainless.org>");
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.addUserId("Allice <alice@example.org>", protector)
|
.addUserId("Allice <alice@example.org>", protector)
|
||||||
.addUserId("Alice <alice@example.org>", protector)
|
.addUserId("Alice <alice@example.org>", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
assertTrue(info.isUserIdValid("Alice <alice@pgpainless.org>"));
|
assertTrue(info.isUserIdValid("Alice <alice@pgpainless.org>"));
|
||||||
assertTrue(info.isUserIdValid("Allice <alice@example.org>"));
|
assertTrue(info.isUserIdValid("Allice <alice@example.org>"));
|
||||||
assertTrue(info.isUserIdValid("Alice <alice@example.org>"));
|
assertTrue(info.isUserIdValid("Alice <alice@example.org>"));
|
||||||
|
|
||||||
Date n1 = new Date(info.getCreationDate().getTime() + 1000); // 1 sec later
|
Date n1 = new Date(info.getCreationDate().getTime() + 1000); // 1 sec later
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, n1)
|
secretKeys = api.modify(secretKeys, n1)
|
||||||
.revokeUserIds(
|
.revokeUserIds(
|
||||||
SelectUserId.containsEmailAddress("alice@example.org"),
|
|
||||||
protector,
|
protector,
|
||||||
RevocationAttributes.createCertificateRevocation()
|
RevocationAttributes.createCertificateRevocation()
|
||||||
.withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID)
|
.withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID)
|
||||||
.withoutDescription())
|
.withoutDescription(),
|
||||||
|
uid -> uid.contains("alice@example.org"))
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, n1);
|
info = api.inspect(secretKeys, n1);
|
||||||
assertTrue(info.isUserIdValid("Alice <alice@pgpainless.org>"));
|
assertTrue(info.isUserIdValid("Alice <alice@pgpainless.org>"));
|
||||||
assertFalse(info.isUserIdValid("Allice <alice@example.org>"));
|
assertFalse(info.isUserIdValid("Allice <alice@example.org>"));
|
||||||
assertFalse(info.isUserIdValid("Alice <alice@example.org>"));
|
assertFalse(info.isUserIdValid("Alice <alice@example.org>"));
|
||||||
|
@ -60,28 +59,28 @@ public class RevokeUserIdsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void removeUserId() throws PGPException {
|
public void removeUserId() throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.modernKeyRing("Alice <alice@pgpainless.org>")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.modernKeyRing("Alice <alice@pgpainless.org>");
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.addUserId("Allice <alice@example.org>", protector)
|
.addUserId("Allice <alice@example.org>", protector)
|
||||||
.addUserId("Alice <alice@example.org>", protector)
|
.addUserId("Alice <alice@example.org>", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(secretKeys);
|
||||||
assertTrue(info.isUserIdValid("Alice <alice@pgpainless.org>"));
|
assertTrue(info.isUserIdValid("Alice <alice@pgpainless.org>"));
|
||||||
assertTrue(info.isUserIdValid("Allice <alice@example.org>"));
|
assertTrue(info.isUserIdValid("Allice <alice@example.org>"));
|
||||||
assertTrue(info.isUserIdValid("Alice <alice@example.org>"));
|
assertTrue(info.isUserIdValid("Alice <alice@example.org>"));
|
||||||
|
|
||||||
Date n1 = new Date(info.getCreationDate().getTime() + 1000);
|
Date n1 = new Date(info.getCreationDate().getTime() + 1000);
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys, n1)
|
secretKeys = api.modify(secretKeys, n1)
|
||||||
.removeUserId("Allice <alice@example.org>", protector)
|
.removeUserId("Allice <alice@example.org>", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
info = PGPainless.inspectKeyRing(secretKeys, n1);
|
info = api.inspect(secretKeys, n1);
|
||||||
assertTrue(info.isUserIdValid("Alice <alice@pgpainless.org>"));
|
assertTrue(info.isUserIdValid("Alice <alice@pgpainless.org>"));
|
||||||
assertFalse(info.isUserIdValid("Allice <alice@example.org>"));
|
assertFalse(info.isUserIdValid("Allice <alice@example.org>"));
|
||||||
assertTrue(info.isUserIdValid("Alice <alice@example.org>"));
|
assertTrue(info.isUserIdValid("Alice <alice@example.org>"));
|
||||||
|
@ -95,14 +94,14 @@ public class RevokeUserIdsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void emptySelectionYieldsNoSuchElementException() {
|
public void emptySelectionYieldsNoSuchElementException() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.modernKeyRing("Alice <alice@pgpainless.org>")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.modernKeyRing("Alice <alice@pgpainless.org>");
|
||||||
|
|
||||||
assertThrows(NoSuchElementException.class, () ->
|
assertThrows(NoSuchElementException.class, () ->
|
||||||
PGPainless.modifyKeyRing(secretKeys).revokeUserIds(
|
api.modify(secretKeys).revokeUserIds(
|
||||||
SelectUserId.containsEmailAddress("alice@example.org"),
|
|
||||||
SecretKeyRingProtector.unprotectedKeys(),
|
SecretKeyRingProtector.unprotectedKeys(),
|
||||||
(RevocationAttributes) null));
|
(RevocationAttributes) null,
|
||||||
|
uid -> uid.contains("alice@example.org")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.bouncycastle.bcpg.SecretKeyPacket;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKey;
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.bouncycastle.util.io.Streams;
|
import org.bouncycastle.util.io.Streams;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
|
@ -67,27 +68,27 @@ public class S2KUsageFixTest {
|
||||||
@Test
|
@Test
|
||||||
public void verifyOutFixInChangePassphraseWorks()
|
public void verifyOutFixInChangePassphraseWorks()
|
||||||
throws PGPException {
|
throws PGPException {
|
||||||
PGPSecretKeyRing before = PGPainless.generateKeyRing().modernKeyRing("Alice", "before")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey before = api.generateKey().modernKeyRing("Alice", "before");
|
||||||
for (PGPSecretKey key : before) {
|
for (PGPSecretKey key : before.getPGPSecretKeyRing()) {
|
||||||
assertEquals(SecretKeyPacket.USAGE_SHA1, key.getS2KUsage());
|
assertEquals(SecretKeyPacket.USAGE_SHA1, key.getS2KUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPSecretKeyRing unprotected = PGPainless.modifyKeyRing(before)
|
OpenPGPKey unprotected = api.modify(before)
|
||||||
.changePassphraseFromOldPassphrase(Passphrase.fromPassword("before"))
|
.changePassphraseFromOldPassphrase(Passphrase.fromPassword("before"))
|
||||||
.withSecureDefaultSettings()
|
.withSecureDefaultSettings()
|
||||||
.toNoPassphrase()
|
.toNoPassphrase()
|
||||||
.done();
|
.done();
|
||||||
for (PGPSecretKey key : unprotected) {
|
for (PGPSecretKey key : unprotected.getPGPSecretKeyRing()) {
|
||||||
assertEquals(SecretKeyPacket.USAGE_NONE, key.getS2KUsage());
|
assertEquals(SecretKeyPacket.USAGE_NONE, key.getS2KUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPSecretKeyRing after = PGPainless.modifyKeyRing(unprotected)
|
OpenPGPKey after = api.modify(unprotected)
|
||||||
.changePassphraseFromOldPassphrase(Passphrase.emptyPassphrase())
|
.changePassphraseFromOldPassphrase(Passphrase.emptyPassphrase())
|
||||||
.withSecureDefaultSettings()
|
.withSecureDefaultSettings()
|
||||||
.toNewPassphrase(Passphrase.fromPassword("after"))
|
.toNewPassphrase(Passphrase.fromPassword("after"))
|
||||||
.done();
|
.done();
|
||||||
for (PGPSecretKey key : after) {
|
for (PGPSecretKey key : after.getPGPSecretKeyRing()) {
|
||||||
assertEquals(SecretKeyPacket.USAGE_SHA1, key.getS2KUsage());
|
assertEquals(SecretKeyPacket.USAGE_SHA1, key.getS2KUsage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,18 +96,19 @@ public class S2KUsageFixTest {
|
||||||
@Test
|
@Test
|
||||||
public void testFixS2KUsageFrom_USAGE_CHECKSUM_to_USAGE_SHA1()
|
public void testFixS2KUsageFrom_USAGE_CHECKSUM_to_USAGE_SHA1()
|
||||||
throws IOException, PGPException {
|
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"));
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword("after"));
|
||||||
|
|
||||||
PGPSecretKeyRing fixed = S2KUsageFix.replaceUsageChecksumWithUsageSha1(keys, protector);
|
PGPSecretKeyRing fixed = S2KUsageFix.replaceUsageChecksumWithUsageSha1(keys.getPGPSecretKeyRing(), protector);
|
||||||
for (PGPSecretKey key : fixed) {
|
for (PGPSecretKey key : fixed) {
|
||||||
assertEquals(SecretKeyPacket.USAGE_SHA1, key.getS2KUsage());
|
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 {
|
throws PGPException, IOException {
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(MESSAGE.getBytes(StandardCharsets.UTF_8));
|
ByteArrayInputStream in = new ByteArrayInputStream(MESSAGE.getBytes(StandardCharsets.UTF_8));
|
||||||
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
|
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.bouncycastle.openpgp.PGPSignatureGenerator;
|
||||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPImplementation;
|
import org.bouncycastle.openpgp.api.OpenPGPImplementation;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
import org.pgpainless.algorithm.CompressionAlgorithm;
|
||||||
|
@ -43,7 +44,6 @@ import org.pgpainless.algorithm.SignatureType;
|
||||||
import org.pgpainless.key.TestKeys;
|
import org.pgpainless.key.TestKeys;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||||
import org.pgpainless.policy.Policy;
|
|
||||||
import org.pgpainless.signature.consumer.SignaturePicker;
|
import org.pgpainless.signature.consumer.SignaturePicker;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||||
|
|
||||||
|
@ -51,17 +51,17 @@ public class SignatureSubpacketsUtilTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetKeyExpirationTimeAsDate() {
|
public void testGetKeyExpirationTimeAsDate() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.modernKeyRing("Expire")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.modernKeyRing("Expire");
|
||||||
Date expiration = Date.from(new Date().toInstant().plus(365, ChronoUnit.DAYS));
|
Date expiration = Date.from(new Date().toInstant().plus(365, ChronoUnit.DAYS));
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.setExpirationDate(expiration, SecretKeyRingProtector.unprotectedKeys())
|
.setExpirationDate(expiration, SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
PGPSignature expirationSig = SignaturePicker.pickCurrentUserIdCertificationSignature(
|
PGPSignature expirationSig = SignaturePicker.pickCurrentUserIdCertificationSignature(
|
||||||
secretKeys, "Expire", Policy.getInstance(), new Date());
|
secretKeys.getPGPSecretKeyRing(), "Expire", api.getAlgorithmPolicy(), new Date());
|
||||||
OpenPGPCertificate.OpenPGPComponentKey notTheRightKey = PGPainless.inspectKeyRing(secretKeys).getSigningSubkeys().get(0);
|
OpenPGPCertificate.OpenPGPComponentKey notTheRightKey = api.inspect(secretKeys).getSigningSubkeys().get(0);
|
||||||
|
|
||||||
assertThrows(IllegalArgumentException.class, () ->
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
SignatureSubpacketsUtil.getKeyExpirationTimeAsDate(expirationSig, notTheRightKey.getPGPPublicKey()));
|
SignatureSubpacketsUtil.getKeyExpirationTimeAsDate(expirationSig, notTheRightKey.getPGPPublicKey()));
|
||||||
|
@ -69,18 +69,19 @@ public class SignatureSubpacketsUtilTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetRevocable() throws PGPException, IOException {
|
public void testGetRevocable() throws PGPException, IOException {
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
|
OpenPGPKey secretKeys = TestKeys.getEmilKey();
|
||||||
PGPPrivateKey certKey = UnlockSecretKey.unlockSecretKey(secretKeys.getSecretKey(), SecretKeyRingProtector.unprotectedKeys());
|
PGPPrivateKey certKey = UnlockSecretKey.unlockSecretKey(secretKeys.getPrimarySecretKey().getPGPSecretKey(),
|
||||||
|
SecretKeyRingProtector.unprotectedKeys());
|
||||||
|
|
||||||
PGPSignatureGenerator generator = getSignatureGenerator(certKey, SignatureType.CASUAL_CERTIFICATION);
|
PGPSignatureGenerator generator = getSignatureGenerator(certKey, SignatureType.CASUAL_CERTIFICATION);
|
||||||
PGPSignature withoutRevocable = generator.generateCertification(secretKeys.getPublicKey());
|
PGPSignature withoutRevocable = generator.generateCertification(secretKeys.getPrimaryKey().getPGPPublicKey());
|
||||||
assertNull(SignatureSubpacketsUtil.getRevocable(withoutRevocable));
|
assertNull(SignatureSubpacketsUtil.getRevocable(withoutRevocable));
|
||||||
|
|
||||||
generator = getSignatureGenerator(certKey, SignatureType.CASUAL_CERTIFICATION);
|
generator = getSignatureGenerator(certKey, SignatureType.CASUAL_CERTIFICATION);
|
||||||
PGPSignatureSubpacketGenerator hashed = new PGPSignatureSubpacketGenerator();
|
PGPSignatureSubpacketGenerator hashed = new PGPSignatureSubpacketGenerator();
|
||||||
hashed.setRevocable(true, true);
|
hashed.setRevocable(true, true);
|
||||||
generator.setHashedSubpackets(hashed.generate());
|
generator.setHashedSubpackets(hashed.generate());
|
||||||
PGPSignature withRevocable = generator.generateCertification(secretKeys.getPublicKey());
|
PGPSignature withRevocable = generator.generateCertification(secretKeys.getPrimaryKey().getPGPPublicKey());
|
||||||
assertNotNull(SignatureSubpacketsUtil.getRevocable(withRevocable));
|
assertNotNull(SignatureSubpacketsUtil.getRevocable(withRevocable));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
|
@ -24,17 +24,17 @@ public class SelectUserIdTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSelectUserIds() throws PGPException {
|
public void testSelectUserIds() throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPainless api = PGPainless.getInstance();
|
||||||
.simpleEcKeyRing("<alice@wonderland.lit>")
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.getPGPSecretKeyRing();
|
.simpleEcKeyRing("<alice@wonderland.lit>");
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.addUserId(
|
.addUserId(
|
||||||
UserId.builder().withName("Alice Liddell").noComment()
|
UserId.builder().withName("Alice Liddell").noComment()
|
||||||
.withEmail("crazy@the-rabbit.hole").build(),
|
.withEmail("crazy@the-rabbit.hole").build(),
|
||||||
SecretKeyRingProtector.unprotectedKeys())
|
SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
List<String> userIds = PGPainless.inspectKeyRing(secretKeys).getValidUserIds();
|
List<String> userIds = api.inspect(secretKeys).getValidUserIds();
|
||||||
List<String> validEmail = userIds.stream().filter(SelectUserId.and(
|
List<String> validEmail = userIds.stream().filter(SelectUserId.and(
|
||||||
SelectUserId.validUserId(secretKeys),
|
SelectUserId.validUserId(secretKeys),
|
||||||
SelectUserId.containsEmailAddress("alice@wonderland.lit")
|
SelectUserId.containsEmailAddress("alice@wonderland.lit")
|
||||||
|
@ -54,14 +54,14 @@ public class SelectUserIdTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testContainsSubstring() throws PGPException {
|
public void testContainsSubstring() throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("wine drinker")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().simpleEcKeyRing("wine drinker");
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.addUserId("this is not a quine", SecretKeyRingProtector.unprotectedKeys())
|
.addUserId("this is not a quine", SecretKeyRingProtector.unprotectedKeys())
|
||||||
.addUserId("this is not a crime", SecretKeyRingProtector.unprotectedKeys())
|
.addUserId("this is not a crime", SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
List<String> userIds = PGPainless.inspectKeyRing(secretKeys).getValidUserIds();
|
List<String> userIds = api.inspect(secretKeys).getValidUserIds();
|
||||||
|
|
||||||
List<String> containSubstring = userIds.stream().filter(SelectUserId.containsSubstring("ine")).collect(Collectors.toList());
|
List<String> containSubstring = userIds.stream().filter(SelectUserId.containsSubstring("ine")).collect(Collectors.toList());
|
||||||
assertEquals(Arrays.asList("wine drinker", "this is not a quine"), containSubstring);
|
assertEquals(Arrays.asList("wine drinker", "this is not a quine"), containSubstring);
|
||||||
|
@ -69,9 +69,9 @@ public class SelectUserIdTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testContainsEmailAddress() {
|
public void testContainsEmailAddress() {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("Alice <alice@wonderland.lit>")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().simpleEcKeyRing("Alice <alice@wonderland.lit>");
|
||||||
List<String> userIds = PGPainless.inspectKeyRing(secretKeys).getValidUserIds();
|
List<String> userIds = api.inspect(secretKeys).getValidUserIds();
|
||||||
|
|
||||||
assertEquals("Alice <alice@wonderland.lit>", userIds.stream().filter(
|
assertEquals("Alice <alice@wonderland.lit>", userIds.stream().filter(
|
||||||
SelectUserId.containsEmailAddress("alice@wonderland.lit")).findFirst().get());
|
SelectUserId.containsEmailAddress("alice@wonderland.lit")).findFirst().get());
|
||||||
|
@ -83,15 +83,15 @@ public class SelectUserIdTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAndOrNot() throws PGPException {
|
public void testAndOrNot() throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("Alice <alice@wonderland.lit>")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().simpleEcKeyRing("Alice <alice@wonderland.lit>");
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.addUserId("Alice <another@email.address>", SecretKeyRingProtector.unprotectedKeys())
|
.addUserId("Alice <another@email.address>", SecretKeyRingProtector.unprotectedKeys())
|
||||||
.addUserId("<crazy@the-rabbit.hole>", SecretKeyRingProtector.unprotectedKeys())
|
.addUserId("<crazy@the-rabbit.hole>", SecretKeyRingProtector.unprotectedKeys())
|
||||||
.addUserId("Crazy Girl <alice@wonderland.lit>", SecretKeyRingProtector.unprotectedKeys())
|
.addUserId("Crazy Girl <alice@wonderland.lit>", SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
List<String> userIds = PGPainless.inspectKeyRing(secretKeys).getValidUserIds();
|
List<String> userIds = api.inspect(secretKeys).getValidUserIds();
|
||||||
|
|
||||||
List<String> or = userIds.stream().filter(SelectUserId.or(
|
List<String> or = userIds.stream().filter(SelectUserId.or(
|
||||||
SelectUserId.containsEmailAddress("alice@wonderland.lit"),
|
SelectUserId.containsEmailAddress("alice@wonderland.lit"),
|
||||||
|
@ -110,12 +110,12 @@ public class SelectUserIdTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFirstMatch() throws PGPException {
|
public void testFirstMatch() throws PGPException {
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("First UserID")
|
PGPainless api = PGPainless.getInstance();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPKey secretKeys = api.generateKey().simpleEcKeyRing("First UserID");
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.addUserId("Second UserID", SecretKeyRingProtector.unprotectedKeys())
|
.addUserId("Second UserID", SecretKeyRingProtector.unprotectedKeys())
|
||||||
.done();
|
.done();
|
||||||
List<String> userIds = PGPainless.inspectKeyRing(secretKeys).getValidUserIds();
|
List<String> userIds = api.inspect(secretKeys).getValidUserIds();
|
||||||
assertEquals("First UserID", userIds.stream().filter(SelectUserId.validUserId(secretKeys)).findFirst().get());
|
assertEquals("First UserID", userIds.stream().filter(SelectUserId.validUserId(secretKeys)).findFirst().get());
|
||||||
assertEquals("Second UserID", userIds.stream().filter(SelectUserId.containsSubstring("Second")).findFirst().get());
|
assertEquals("Second UserID", userIds.stream().filter(SelectUserId.containsSubstring("Second")).findFirst().get());
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,11 @@ import java.io.InputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.lang.RuntimeException
|
import java.lang.RuntimeException
|
||||||
import org.bouncycastle.openpgp.PGPException
|
import org.bouncycastle.openpgp.PGPException
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing
|
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection
|
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.bouncycastle.extensions.openPgpFingerprint
|
import org.pgpainless.bouncycastle.extensions.openPgpFingerprint
|
||||||
|
import org.pgpainless.bouncycastle.extensions.toOpenPGPCertificate
|
||||||
import org.pgpainless.exception.WrongPassphraseException
|
import org.pgpainless.exception.WrongPassphraseException
|
||||||
import org.pgpainless.key.util.KeyRingUtils
|
import org.pgpainless.key.util.KeyRingUtils
|
||||||
import org.pgpainless.key.util.RevocationAttributes
|
import org.pgpainless.key.util.RevocationAttributes
|
||||||
|
@ -38,7 +39,7 @@ class RevokeKeyImpl : RevokeKey {
|
||||||
|
|
||||||
secretKeyRings.forEach { protector.addSecretKey(it) }
|
secretKeyRings.forEach { protector.addSecretKey(it) }
|
||||||
|
|
||||||
val revocationCertificates = mutableListOf<PGPPublicKeyRing>()
|
val revocationCertificates = mutableListOf<OpenPGPCertificate>()
|
||||||
secretKeyRings.forEach { secretKeys ->
|
secretKeyRings.forEach { secretKeys ->
|
||||||
val editor = PGPainless.modifyKeyRing(secretKeys)
|
val editor = PGPainless.modifyKeyRing(secretKeys)
|
||||||
try {
|
try {
|
||||||
|
@ -53,7 +54,8 @@ class RevokeKeyImpl : RevokeKey {
|
||||||
val certificate = PGPainless.extractCertificate(secretKeys)
|
val certificate = PGPainless.extractCertificate(secretKeys)
|
||||||
val revocation = editor.createRevocation(protector, attributes)
|
val revocation = editor.createRevocation(protector, attributes)
|
||||||
revocationCertificates.add(
|
revocationCertificates.add(
|
||||||
KeyRingUtils.injectCertification(certificate, revocation))
|
KeyRingUtils.injectCertification(certificate, revocation.signature)
|
||||||
|
.toOpenPGPCertificate())
|
||||||
}
|
}
|
||||||
} catch (e: WrongPassphraseException) {
|
} catch (e: WrongPassphraseException) {
|
||||||
throw SOPGPException.KeyIsProtected(
|
throw SOPGPException.KeyIsProtected(
|
||||||
|
@ -67,7 +69,8 @@ class RevokeKeyImpl : RevokeKey {
|
||||||
|
|
||||||
return object : Ready() {
|
return object : Ready() {
|
||||||
override fun writeTo(outputStream: OutputStream) {
|
override fun writeTo(outputStream: OutputStream) {
|
||||||
val collection = PGPPublicKeyRingCollection(revocationCertificates)
|
val collection =
|
||||||
|
PGPPublicKeyRingCollection(revocationCertificates.map { it.pgpPublicKeyRing })
|
||||||
if (armor) {
|
if (armor) {
|
||||||
val armorOut = ArmoredOutputStreamFactory.get(outputStream)
|
val armorOut = ArmoredOutputStreamFactory.get(outputStream)
|
||||||
collection.encode(armorOut)
|
collection.encode(armorOut)
|
||||||
|
|
|
@ -7,7 +7,7 @@ package sop.testsuite.pgpainless.operation;
|
||||||
import org.bouncycastle.bcpg.KeyIdentifier;
|
import org.bouncycastle.bcpg.KeyIdentifier;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
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.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
|
@ -32,13 +32,13 @@ public class PGPainlessChangeKeyPasswordTest extends ChangeKeyPasswordTest {
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("provideInstances")
|
@MethodSource("provideInstances")
|
||||||
public void changePasswordOfKeyWithSeparateSubkeyPasswords(SOP sop) throws IOException, PGPException {
|
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))
|
.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.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.SIGN_DATA))
|
||||||
.addSubkey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE))
|
.addSubkey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE))
|
||||||
.build()
|
.build();
|
||||||
.getPGPSecretKeyRing();
|
Iterator<PGPPublicKey> keys = secretKeys.getPGPSecretKeyRing().getPublicKeys();
|
||||||
Iterator<PGPPublicKey> keys = secretKeys.getPublicKeys();
|
|
||||||
KeyIdentifier primaryKeyId = keys.next().getKeyIdentifier();
|
KeyIdentifier primaryKeyId = keys.next().getKeyIdentifier();
|
||||||
KeyIdentifier signingKeyId = keys.next().getKeyIdentifier();
|
KeyIdentifier signingKeyId = keys.next().getKeyIdentifier();
|
||||||
KeyIdentifier encryptKeyId = keys.next().getKeyIdentifier();
|
KeyIdentifier encryptKeyId = keys.next().getKeyIdentifier();
|
||||||
|
@ -47,7 +47,7 @@ public class PGPainlessChangeKeyPasswordTest extends ChangeKeyPasswordTest {
|
||||||
String p2 = "0r4ng3";
|
String p2 = "0r4ng3";
|
||||||
String p3 = "dr4g0n";
|
String p3 = "dr4g0n";
|
||||||
|
|
||||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
secretKeys = api.modify(secretKeys)
|
||||||
.changeSubKeyPassphraseFromOldPassphrase(primaryKeyId, Passphrase.emptyPassphrase())
|
.changeSubKeyPassphraseFromOldPassphrase(primaryKeyId, Passphrase.emptyPassphrase())
|
||||||
.withSecureDefaultSettings()
|
.withSecureDefaultSettings()
|
||||||
.toNewPassphrase(Passphrase.fromPassword(p1))
|
.toNewPassphrase(Passphrase.fromPassword(p1))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue