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

Complete migration of KeyRingInfo to KeyIdentifier, javadoc

This commit is contained in:
Paul Schaub 2025-02-26 14:59:39 +01:00
parent 664fe68224
commit bc6513b6c7
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311

View file

@ -6,7 +6,6 @@ package org.pgpainless.key.info
import java.util.* import java.util.*
import kotlin.NoSuchElementException import kotlin.NoSuchElementException
import openpgp.openPgpKeyId
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.OpenPGPCertificate
@ -232,6 +231,14 @@ class KeyRingInfo(
val isUsableForSigning: Boolean = val isUsableForSigning: Boolean =
isSigningCapable && signingSubkeys.any { isSecretKeyAvailable(it.keyIdentifier) } isSigningCapable && signingSubkeys.any { isSecretKeyAvailable(it.keyIdentifier) }
/**
* True, if the [OpenPGPCertificate] can be used to certify other
* [OpenPGPCertificates][OpenPGPCertificate].
*/
val isUsableForThirdPartyCertification: Boolean =
isKeyValidlyBound(keyIdentifier) &&
getKeyFlagsOf(keyIdentifier).contains(KeyFlag.CERTIFY_OTHER)
/** [HashAlgorithm] preferences of the primary user-ID or if absent, of the primary key. */ /** [HashAlgorithm] preferences of the primary user-ID or if absent, of the primary key. */
val preferredHashAlgorithms: Set<HashAlgorithm> val preferredHashAlgorithms: Set<HashAlgorithm>
get() = get() =
@ -252,6 +259,7 @@ class KeyRingInfo(
primaryUserId?.let { getPreferredCompressionAlgorithms(it) } primaryUserId?.let { getPreferredCompressionAlgorithms(it) }
?: getPreferredCompressionAlgorithms(keyIdentifier) ?: getPreferredCompressionAlgorithms(keyIdentifier)
/** [AEADCipherMode] preferences of the primary user-id, or if absent, the primary key. */
val preferredAEADCipherSuites: Set<AEADCipherMode> val preferredAEADCipherSuites: Set<AEADCipherMode>
get() = get() =
primaryUserId?.let { getPreferredAEADCipherSuites(it) } primaryUserId?.let { getPreferredAEADCipherSuites(it) }
@ -264,11 +272,24 @@ class KeyRingInfo(
* @return expiration date or null * @return expiration date or null
*/ */
fun getSubkeyExpirationDate(fingerprint: OpenPgpFingerprint): Date? { fun getSubkeyExpirationDate(fingerprint: OpenPgpFingerprint): Date? {
return getSubkeyExpirationDate(fingerprint.keyId) return getSubkeyExpirationDate(fingerprint.keyIdentifier)
} }
/**
* Return the expiration date of the [OpenPGPComponentKey] with the provided [keyIdentifier].
*
* @param keyIdentifier subkey KeyIdentifier
* @return expiration date
*/
fun getSubkeyExpirationDate(keyIdentifier: KeyIdentifier): Date? { fun getSubkeyExpirationDate(keyIdentifier: KeyIdentifier): Date? {
return getSubkeyExpirationDate(keyIdentifier.keyId) if (primaryKey.keyIdentifier.matches(keyIdentifier)) return primaryKeyExpirationDate
val subkey =
getPublicKey(keyIdentifier)
?: throw NoSuchElementException("No subkey with key-ID ${keyIdentifier} found.")
val bindingSig =
getCurrentSubkeyBindingSignature(keyIdentifier)
?: throw AssertionError("Subkey has no valid binding signature.")
return bindingSig.getKeyExpirationDate(subkey.creationTime)
} }
/** /**
@ -277,16 +298,9 @@ class KeyRingInfo(
* @param keyId subkey keyId * @param keyId subkey keyId
* @return expiration date * @return expiration date
*/ */
@Deprecated("Pass in a KeyIdentifer instead.")
fun getSubkeyExpirationDate(keyId: Long): Date? { fun getSubkeyExpirationDate(keyId: Long): Date? {
if (primaryKey.keyIdentifier.keyId == keyId) return primaryKeyExpirationDate return getSubkeyExpirationDate(KeyIdentifier(keyId))
val subkey =
getPublicKey(keyId)
?: throw NoSuchElementException(
"No subkey with key-ID ${keyId.openPgpKeyId()} found.")
val bindingSig =
getCurrentSubkeyBindingSignature(keyId)
?: throw AssertionError("Subkey has no valid binding signature.")
return bindingSig.getKeyExpirationDate(subkey.creationTime)
} }
/** /**
@ -465,32 +479,51 @@ class KeyRingInfo(
keys.getUserId(userId.toString())?.getRevocation(referenceDate)?.signature keys.getUserId(userId.toString())?.getRevocation(referenceDate)?.signature
/** /**
* Return the current binding signature for the subkey with the given key-ID. * Return the current binding signature for the subkey with the given [keyIdentifier].
* *
* @param keyIdentifier subkey identifier
* @return current subkey binding signature * @return current subkey binding signature
*/ */
fun getCurrentSubkeyBindingSignature(keyIdentifier: KeyIdentifier): PGPSignature? =
keys.getKey(keyIdentifier)?.getCertification(referenceDate)?.signature
/**
* Return the current binding signature for the subkey with the given key-ID.
*
* @param keyId key-ID
* @return current subkey binding signature
*/
@Deprecated("Pass in a KeyIdentifier instead.")
fun getCurrentSubkeyBindingSignature(keyId: Long): PGPSignature? = fun getCurrentSubkeyBindingSignature(keyId: Long): PGPSignature? =
keys.getKey(KeyIdentifier(keyId))?.getCertification(referenceDate)?.signature getCurrentSubkeyBindingSignature(KeyIdentifier(keyId))
/**
* Return the current revocation signature for the subkey with the given [keyIdentifier].
*
* @param keyIdentifier subkey identifier
* @return current subkey revocation signature
*/
fun getSubkeyRevocationSignature(keyIdentifier: KeyIdentifier): PGPSignature? =
keys.getKey(keyIdentifier)?.getRevocation(referenceDate)?.signature
/** /**
* Return the current revocation signature for the subkey with the given key-ID. * Return the current revocation signature for the subkey with the given key-ID.
* *
* @return current subkey revocation signature * @return current subkey revocation signature
*/ */
@Deprecated("Pass in a KeyIdentifier instead.")
fun getSubkeyRevocationSignature(keyId: Long): PGPSignature? = fun getSubkeyRevocationSignature(keyId: Long): PGPSignature? =
keys.getKey(KeyIdentifier(keyId))?.getRevocation(referenceDate)?.signature getSubkeyRevocationSignature(KeyIdentifier(keyId))
fun getKeyFlagsOf(keyIdentifier: KeyIdentifier): List<KeyFlag> =
getKeyFlagsOf(keyIdentifier.keyId)
/** /**
* Return a list of [KeyFlags][KeyFlag] that apply to the subkey with the provided key id. * Return a list of [KeyFlags][KeyFlag] that apply to the subkey with the provided
* [keyIdentifier].
* *
* @param keyId key-id * @param keyIdentifier keyIdentifier
* @return list of key flags * @return list of key flags
*/ */
fun getKeyFlagsOf(keyId: Long): List<KeyFlag> = fun getKeyFlagsOf(keyIdentifier: KeyIdentifier): List<KeyFlag> =
if (keyId == primaryKey.keyIdentifier.keyId) { if (primaryKey.keyIdentifier.matches(keyIdentifier)) {
latestDirectKeySelfSignature?.let { sig -> latestDirectKeySelfSignature?.let { sig ->
SignatureSubpacketsUtil.parseKeyFlags(sig)?.let { flags -> SignatureSubpacketsUtil.parseKeyFlags(sig)?.let { flags ->
return flags return flags
@ -505,7 +538,7 @@ class KeyRingInfo(
} }
listOf() listOf()
} else { } else {
getCurrentSubkeyBindingSignature(keyId)?.let { getCurrentSubkeyBindingSignature(keyIdentifier)?.let {
SignatureSubpacketsUtil.parseKeyFlags(it)?.let { flags -> SignatureSubpacketsUtil.parseKeyFlags(it)?.let { flags ->
return flags return flags
} }
@ -513,6 +546,15 @@ class KeyRingInfo(
listOf() listOf()
} }
/**
* Return a list of [KeyFlags][KeyFlag] that apply to the subkey with the provided key id.
*
* @param keyId key-id
* @return list of key flags
*/
@Deprecated("Pass in a KeyIdentifier instead.")
fun getKeyFlagsOf(keyId: Long): List<KeyFlag> = getKeyFlagsOf(KeyIdentifier(keyId))
/** /**
* Return a list of [KeyFlags][KeyFlag] that apply to the given user-id. * Return a list of [KeyFlags][KeyFlag] that apply to the given user-id.
* *
@ -530,13 +572,35 @@ class KeyRingInfo(
"While user-id '$userId' was reported as valid, there appears to be no certification for it.") "While user-id '$userId' was reported as valid, there appears to be no certification for it.")
} }
/**
* Return the [OpenPGPComponentKey] with the given [keyIdentifier] from this
* [OpenPGPCertificate] or [OpenPGPKey].
*
* @param keyIdentifier keyIdentifier
* @return public component key or null
*/
fun getPublicKey(keyIdentifier: KeyIdentifier): OpenPGPComponentKey? =
keys.getKey(keyIdentifier)
/** /**
* Return the public key with the given key id from the provided key ring. * Return the public key with the given key id from the provided key ring.
* *
* @param keyId key id * @param keyId key id
* @return public key or null * @return public key or null
*/ */
fun getPublicKey(keyId: Long): OpenPGPComponentKey? = keys.getKey(KeyIdentifier(keyId)) @Deprecated("Pass in a KeyIdentifier instead.")
fun getPublicKey(keyId: Long): OpenPGPComponentKey? = getPublicKey(KeyIdentifier(keyId))
/**
* Return the [OpenPGPSecretKey] component with the given [keyIdentifier].
*
* @param keyIdentifier keyIdentifier
* @return secret key or null
*/
fun getSecretKey(keyIdentifier: KeyIdentifier): OpenPGPSecretKey? =
if (keys.isSecretKey) {
(keys as OpenPGPKey).getSecretKey(keyIdentifier)
} else null
/** /**
* Return the secret key with the given key id. * Return the secret key with the given key id.
@ -544,20 +608,12 @@ class KeyRingInfo(
* @param keyId key id * @param keyId key id
* @return secret key or null * @return secret key or null
*/ */
@Deprecated("Pass in a KeyIdentifier instead.")
fun getSecretKey(keyId: Long): OpenPGPSecretKey? = getSecretKey(KeyIdentifier(keyId)) fun getSecretKey(keyId: Long): OpenPGPSecretKey? = getSecretKey(KeyIdentifier(keyId))
fun getSecretKey(keyIdentifier: KeyIdentifier): OpenPGPSecretKey? =
if (keys.isSecretKey) {
(keys as OpenPGPKey).getSecretKey(keyIdentifier)
} else null
fun isSecretKeyAvailable(keyId: Long): Boolean {
return isSecretKeyAvailable(KeyIdentifier(keyId))
}
/** /**
* Return true, if the secret-key with the given key-ID is available (i.e. not moved to a * Return true, if the secret-key with the given [keyIdentifier] is available (i.e. part of the
* smart-card). * certificate AND not moved to a smart-card).
* *
* @return availability of the secret key * @return availability of the secret key
*/ */
@ -569,6 +625,11 @@ class KeyRingInfo(
?: false // Missing secret key ?: false // Missing secret key
} }
@Deprecated("Pass in a KeyIdentifier instead.")
fun isSecretKeyAvailable(keyId: Long): Boolean {
return isSecretKeyAvailable(KeyIdentifier(keyId))
}
/** /**
* Return the public key with the given fingerprint. * Return the public key with the given fingerprint.
* *
@ -576,7 +637,7 @@ class KeyRingInfo(
* @return public key or null * @return public key or null
*/ */
fun getPublicKey(fingerprint: OpenPgpFingerprint): OpenPGPComponentKey? = fun getPublicKey(fingerprint: OpenPgpFingerprint): OpenPGPComponentKey? =
keys.getKey(KeyIdentifier(fingerprint.bytes)) keys.getKey(fingerprint.keyIdentifier)
/** /**
* Return the secret key with the given fingerprint. * Return the secret key with the given fingerprint.
@ -585,11 +646,7 @@ class KeyRingInfo(
* @return secret key or null * @return secret key or null
*/ */
fun getSecretKey(fingerprint: OpenPgpFingerprint): OpenPGPSecretKey? = fun getSecretKey(fingerprint: OpenPgpFingerprint): OpenPGPSecretKey? =
getSecretKey(KeyIdentifier(fingerprint.bytes)) getSecretKey(fingerprint.keyIdentifier)
fun getPublicKey(keyIdentifier: KeyIdentifier): OpenPGPComponentKey? {
return keys.getKey(keyIdentifier)
}
/** /**
* Return the public key matching the given [SubkeyIdentifier]. * Return the public key matching the given [SubkeyIdentifier].
@ -599,7 +656,7 @@ class KeyRingInfo(
* key of the key. * key of the key.
*/ */
fun getPublicKey(identifier: SubkeyIdentifier): OpenPGPComponentKey? { fun getPublicKey(identifier: SubkeyIdentifier): OpenPGPComponentKey? {
require(primaryKey.keyIdentifier.equals(identifier.keyIdentifier)) { require(primaryKey.keyIdentifier.matches(identifier.keyIdentifier)) {
"Mismatching primary key ID." "Mismatching primary key ID."
} }
return getPublicKey(identifier.componentKeyIdentifier) return getPublicKey(identifier.componentKeyIdentifier)
@ -612,11 +669,22 @@ class KeyRingInfo(
* @throws IllegalArgumentException if the identifier's primary key does not match the primary * @throws IllegalArgumentException if the identifier's primary key does not match the primary
* key of the key. * key of the key.
*/ */
fun getSecretKey(identifier: SubkeyIdentifier): OpenPGPComponentKey? = fun getSecretKey(identifier: SubkeyIdentifier): OpenPGPComponentKey? {
getSecretKey(identifier.componentKeyIdentifier) require(primaryKey.keyIdentifier.matches(identifier.keyIdentifier)) {
"Mismatching primary key ID."
}
return getSecretKey(identifier.componentKeyIdentifier)
}
/**
* Return true if the [OpenPGPComponentKey] with the given [keyIdentifier] is bound to the
* [OpenPGPCertificate] properly.
*
* @param keyIdentifier identifier of the component key
* @return true if key is bound validly
*/
fun isKeyValidlyBound(keyIdentifier: KeyIdentifier): Boolean { fun isKeyValidlyBound(keyIdentifier: KeyIdentifier): Boolean {
return isKeyValidlyBound(keyIdentifier.keyId) return keys.getKey(keyIdentifier)?.isBoundAt(referenceDate) ?: false
} }
/** /**
@ -625,9 +693,8 @@ class KeyRingInfo(
* @param keyId key id * @param keyId key id
* @return true if key is bound validly * @return true if key is bound validly
*/ */
fun isKeyValidlyBound(keyId: Long): Boolean { @Deprecated("Pass in a KeyIdentifier instead.")
return keys.getKey(KeyIdentifier(keyId))?.isBoundAt(referenceDate) ?: false fun isKeyValidlyBound(keyId: Long): Boolean = isKeyValidlyBound(KeyIdentifier(keyId))
}
/** /**
* Return the current primary user-id of the key ring. * Return the current primary user-id of the key ring.
@ -643,7 +710,12 @@ class KeyRingInfo(
return keys.primaryKey.getExplicitOrImplicitPrimaryUserId(referenceDate)?.userId return keys.primaryKey.getExplicitOrImplicitPrimaryUserId(referenceDate)?.userId
} }
/** Return true, if the primary user-ID, as well as the given user-ID are valid and bound. */ /**
* Return true, if the primary user-ID, as well as the given user-ID are valid and bound.
*
* @param userId user-id
* @return true if the primary user-ID and the given user-ID are valid.
*/
fun isUserIdValid(userId: CharSequence): Boolean { fun isUserIdValid(userId: CharSequence): Boolean {
var valid = isUserIdBound(userId) var valid = isUserIdBound(userId)
if (primaryUserId != null) valid = valid && isUserIdBound(primaryUserId) if (primaryUserId != null) valid = valid && isUserIdBound(primaryUserId)
@ -651,11 +723,21 @@ class KeyRingInfo(
return valid return valid
} }
/** Return true, if the given user-ID is validly bound. */ /**
* Return true, if the given user-ID is validly bound.
*
* @param userId user-id
* @return true if the user-id is validly bound to the [OpenPGPCertificate]
*/
fun isUserIdBound(userId: CharSequence): Boolean = fun isUserIdBound(userId: CharSequence): Boolean =
keys.getUserId(userId.toString())?.isBoundAt(referenceDate) ?: false keys.getUserId(userId.toString())?.isBoundAt(referenceDate) ?: false
/** [HashAlgorithm] preferences of the given user-ID. */ /**
* Return the [HashAlgorithm] preferences of the given [userId].
*
* @param userId user-id
* @return ordered set of preferred [HashAlgorithms][HashAlgorithm] (descending order)
*/
fun getPreferredHashAlgorithms(userId: CharSequence): Set<HashAlgorithm> { fun getPreferredHashAlgorithms(userId: CharSequence): Set<HashAlgorithm> {
return keys return keys
.getUserId(userId.toString()) .getUserId(userId.toString())
@ -664,6 +746,12 @@ class KeyRingInfo(
?: throw NoSuchElementException("No user-id '$userId' found on this key.") ?: throw NoSuchElementException("No user-id '$userId' found on this key.")
} }
/**
* Return the [HashAlgorithm] preferences of the component key with the given [KeyIdentifier].
*
* @param keyIdentifier identifier of a [OpenPGPComponentKey]
* @return ordered set of preferred [HashAlgorithms][HashAlgorithm] (descending order)
*/
fun getPreferredHashAlgorithms(keyIdentifier: KeyIdentifier): Set<HashAlgorithm> { fun getPreferredHashAlgorithms(keyIdentifier: KeyIdentifier): Set<HashAlgorithm> {
return keys return keys
.getKey(keyIdentifier) .getKey(keyIdentifier)
@ -679,7 +767,13 @@ class KeyRingInfo(
return getPreferredHashAlgorithms(KeyIdentifier(keyId)) return getPreferredHashAlgorithms(KeyIdentifier(keyId))
} }
/** [SymmetricKeyAlgorithm] preferences of the given user-ID. */ /**
* Return the [SymmetricKeyAlgorithm] preferences of the given [userId].
*
* @param userId user-id
* @return ordered set of preferred [SymmetricKeyAlgorithms][SymmetricKeyAlgorithm] (descending
* order)
*/
fun getPreferredSymmetricKeyAlgorithms(userId: CharSequence): Set<SymmetricKeyAlgorithm> { fun getPreferredSymmetricKeyAlgorithms(userId: CharSequence): Set<SymmetricKeyAlgorithm> {
return keys return keys
.getUserId(userId.toString()) .getUserId(userId.toString())
@ -688,6 +782,14 @@ class KeyRingInfo(
?: throw NoSuchElementException("No user-id '$userId' found on this key.") ?: throw NoSuchElementException("No user-id '$userId' found on this key.")
} }
/**
* Return the [SymmetricKeyAlgorithm] preferences of the [OpenPGPComponentKey] with the given
* [keyIdentifier].
*
* @param keyIdentifier identifier of the [OpenPGPComponentKey]
* @return ordered set of preferred [SymmetricKeyAlgorithms][SymmetricKeyAlgorithm] (descending
* order)
*/
fun getPreferredSymmetricKeyAlgorithms( fun getPreferredSymmetricKeyAlgorithms(
keyIdentifier: KeyIdentifier keyIdentifier: KeyIdentifier
): Set<SymmetricKeyAlgorithm> { ): Set<SymmetricKeyAlgorithm> {
@ -705,7 +807,13 @@ class KeyRingInfo(
return getPreferredSymmetricKeyAlgorithms(KeyIdentifier(keyId)) return getPreferredSymmetricKeyAlgorithms(KeyIdentifier(keyId))
} }
/** [CompressionAlgorithm] preferences of the given user-ID. */ /**
* Return the [CompressionAlgorithm] preferences of the given [userId].
*
* @param userId user-id
* @return ordered set of preferred [CompressionAlgorithms][CompressionAlgorithm] (descending
* order)
*/
fun getPreferredCompressionAlgorithms(userId: CharSequence): Set<CompressionAlgorithm> { fun getPreferredCompressionAlgorithms(userId: CharSequence): Set<CompressionAlgorithm> {
return keys return keys
.getUserId(userId.toString()) .getUserId(userId.toString())
@ -714,6 +822,14 @@ class KeyRingInfo(
?: throw NoSuchElementException("No user-id '$userId' found on this key.") ?: throw NoSuchElementException("No user-id '$userId' found on this key.")
} }
/**
* Return the [CompressionAlgorithm] preferences of the [OpenPGPComponentKey] with the given
* [keyIdentifier].
*
* @param keyIdentifier identifier of the [OpenPGPComponentKey]
* @return ordered set of preferred [CompressionAlgorithms][CompressionAlgorithm] (descending
* order)
*/
fun getPreferredCompressionAlgorithms(keyIdentifier: KeyIdentifier): Set<CompressionAlgorithm> { fun getPreferredCompressionAlgorithms(keyIdentifier: KeyIdentifier): Set<CompressionAlgorithm> {
return keys return keys
.getKey(keyIdentifier) .getKey(keyIdentifier)
@ -724,10 +840,18 @@ class KeyRingInfo(
} }
/** [CompressionAlgorithm] preferences of the given key. */ /** [CompressionAlgorithm] preferences of the given key. */
@Deprecated("Pass in a KeyIdentifier instead.")
fun getPreferredCompressionAlgorithms(keyId: Long): Set<CompressionAlgorithm> { fun getPreferredCompressionAlgorithms(keyId: Long): Set<CompressionAlgorithm> {
return getPreferredCompressionAlgorithms(KeyIdentifier(keyId)) return getPreferredCompressionAlgorithms(KeyIdentifier(keyId))
} }
/**
* Return the [AEADCipherMode] preferences of the given [userId].
*
* @param userId user-ID
* @return ordered set of [AEADCipherModes][AEADCipherMode] (descending order, including
* implicitly supported AEAD modes)
*/
fun getPreferredAEADCipherSuites(userId: CharSequence): Set<AEADCipherMode> { fun getPreferredAEADCipherSuites(userId: CharSequence): Set<AEADCipherMode> {
return keys return keys
.getUserId(userId.toString()) .getUserId(userId.toString())
@ -736,6 +860,14 @@ class KeyRingInfo(
?: throw NoSuchElementException("No user-id '$userId' found on this key.") ?: throw NoSuchElementException("No user-id '$userId' found on this key.")
} }
/**
* Return the [AEADCipherMode] preferences of the [OpenPGPComponentKey] with the given
* [keyIdentifier].
*
* @param keyIdentifier component key identifier
* @return ordered set of [AEADCipherModes][AEADCipherMode] (descending order, including
* implicitly supported AEAD modes)
*/
fun getPreferredAEADCipherSuites(keyIdentifier: KeyIdentifier): Set<AEADCipherMode> { fun getPreferredAEADCipherSuites(keyIdentifier: KeyIdentifier): Set<AEADCipherMode> {
return keys return keys
.getKey(keyIdentifier) .getKey(keyIdentifier)
@ -750,10 +882,6 @@ class KeyRingInfo(
return getPreferredAEADCipherSuites(KeyIdentifier(keyId)) return getPreferredAEADCipherSuites(KeyIdentifier(keyId))
} }
val isUsableForThirdPartyCertification: Boolean =
isKeyValidlyBound(keyIdentifier) &&
getKeyFlagsOf(keyIdentifier).contains(KeyFlag.CERTIFY_OTHER)
companion object { companion object {
/** Evaluate the key for the given signature. */ /** Evaluate the key for the given signature. */