mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-09 18:29:39 +02:00
Improve KeyExceptions
This commit is contained in:
parent
92da00fc8c
commit
dcb78ddedf
4 changed files with 99 additions and 48 deletions
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
package org.pgpainless.exception;
|
package org.pgpainless.exception;
|
||||||
|
|
||||||
|
import org.bouncycastle.bcpg.KeyIdentifier;
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
||||||
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
||||||
import org.pgpainless.key.OpenPgpFingerprint;
|
import org.pgpainless.key.OpenPgpFingerprint;
|
||||||
import org.pgpainless.util.DateUtil;
|
import org.pgpainless.util.DateUtil;
|
||||||
|
@ -33,6 +35,10 @@ public abstract class KeyException extends RuntimeException {
|
||||||
|
|
||||||
public static class ExpiredKeyException extends KeyException {
|
public static class ExpiredKeyException extends KeyException {
|
||||||
|
|
||||||
|
public ExpiredKeyException(@Nonnull OpenPGPCertificate cert, @Nonnull Date expirationDate) {
|
||||||
|
this(OpenPgpFingerprint.of(cert), expirationDate);
|
||||||
|
}
|
||||||
|
|
||||||
public ExpiredKeyException(@Nonnull OpenPgpFingerprint fingerprint, @Nonnull Date expirationDate) {
|
public ExpiredKeyException(@Nonnull OpenPgpFingerprint fingerprint, @Nonnull Date expirationDate) {
|
||||||
super("Key " + fingerprint + " is expired. Expiration date: " + DateUtil.formatUTCDate(expirationDate), fingerprint);
|
super("Key " + fingerprint + " is expired. Expiration date: " + DateUtil.formatUTCDate(expirationDate), fingerprint);
|
||||||
}
|
}
|
||||||
|
@ -43,10 +49,29 @@ public abstract class KeyException extends RuntimeException {
|
||||||
public RevokedKeyException(@Nonnull OpenPgpFingerprint fingerprint) {
|
public RevokedKeyException(@Nonnull OpenPgpFingerprint fingerprint) {
|
||||||
super("Key " + fingerprint + " appears to be revoked.", fingerprint);
|
super("Key " + fingerprint + " appears to be revoked.", fingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RevokedKeyException(@Nonnull OpenPGPCertificate.OpenPGPComponentKey key) {
|
||||||
|
super("Subkey " + key.getKeyIdentifier() + " appears to be revoked.",
|
||||||
|
OpenPgpFingerprint.of(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public RevokedKeyException(@Nonnull OpenPGPCertificate cert) {
|
||||||
|
super("Key or certificate " + cert.getKeyIdentifier() + " appears to be revoked.",
|
||||||
|
OpenPgpFingerprint.of(cert));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class UnacceptableEncryptionKeyException extends KeyException {
|
public static class UnacceptableEncryptionKeyException extends KeyException {
|
||||||
|
|
||||||
|
public UnacceptableEncryptionKeyException(@Nonnull OpenPGPCertificate cert) {
|
||||||
|
this(OpenPgpFingerprint.of(cert));
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnacceptableEncryptionKeyException(@Nonnull OpenPGPCertificate.OpenPGPComponentKey subkey) {
|
||||||
|
super("Subkey " + subkey.getKeyIdentifier() + " is not an acceptable encryption key.",
|
||||||
|
OpenPgpFingerprint.of(subkey));
|
||||||
|
}
|
||||||
|
|
||||||
public UnacceptableEncryptionKeyException(@Nonnull OpenPgpFingerprint fingerprint) {
|
public UnacceptableEncryptionKeyException(@Nonnull OpenPgpFingerprint fingerprint) {
|
||||||
super("Key " + fingerprint + " has no acceptable encryption key.", fingerprint);
|
super("Key " + fingerprint + " has no acceptable encryption key.", fingerprint);
|
||||||
}
|
}
|
||||||
|
@ -58,6 +83,14 @@ public abstract class KeyException extends RuntimeException {
|
||||||
|
|
||||||
public static class UnacceptableSigningKeyException extends KeyException {
|
public static class UnacceptableSigningKeyException extends KeyException {
|
||||||
|
|
||||||
|
public UnacceptableSigningKeyException(OpenPGPCertificate certificate) {
|
||||||
|
this(OpenPgpFingerprint.of(certificate));
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnacceptableSigningKeyException(OpenPGPCertificate.OpenPGPComponentKey subkey) {
|
||||||
|
this(OpenPgpFingerprint.of(subkey));
|
||||||
|
}
|
||||||
|
|
||||||
public UnacceptableSigningKeyException(@Nonnull OpenPgpFingerprint fingerprint) {
|
public UnacceptableSigningKeyException(@Nonnull OpenPgpFingerprint fingerprint) {
|
||||||
super("Key " + fingerprint + " has no acceptable signing key.", fingerprint);
|
super("Key " + fingerprint + " has no acceptable signing key.", fingerprint);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +109,10 @@ public abstract class KeyException extends RuntimeException {
|
||||||
|
|
||||||
public static class UnacceptableSelfSignatureException extends KeyException {
|
public static class UnacceptableSelfSignatureException extends KeyException {
|
||||||
|
|
||||||
|
public UnacceptableSelfSignatureException(@Nonnull OpenPGPCertificate cert) {
|
||||||
|
this(OpenPgpFingerprint.of(cert));
|
||||||
|
}
|
||||||
|
|
||||||
public UnacceptableSelfSignatureException(@Nonnull OpenPgpFingerprint fingerprint) {
|
public UnacceptableSelfSignatureException(@Nonnull OpenPgpFingerprint fingerprint) {
|
||||||
super("Key " + fingerprint + " does not have a valid/acceptable signature to derive an expiration date from.", fingerprint);
|
super("Key " + fingerprint + " does not have a valid/acceptable signature to derive an expiration date from.", fingerprint);
|
||||||
}
|
}
|
||||||
|
@ -83,29 +120,50 @@ public abstract class KeyException extends RuntimeException {
|
||||||
|
|
||||||
public static class MissingSecretKeyException extends KeyException {
|
public static class MissingSecretKeyException extends KeyException {
|
||||||
|
|
||||||
private final long missingSecretKeyId;
|
private final KeyIdentifier missingSecretKeyIdentifier;
|
||||||
|
|
||||||
public MissingSecretKeyException(@Nonnull OpenPgpFingerprint fingerprint, long keyId) {
|
public MissingSecretKeyException(@Nonnull OpenPGPCertificate.OpenPGPComponentKey publicKey) {
|
||||||
super("Key " + fingerprint + " does not contain a secret key for public key " + Long.toHexString(keyId), fingerprint);
|
this(OpenPgpFingerprint.of(publicKey.getCertificate()), publicKey.getKeyIdentifier());
|
||||||
this.missingSecretKeyId = keyId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getMissingSecretKeyId() {
|
public MissingSecretKeyException(@Nonnull OpenPgpFingerprint fingerprint, KeyIdentifier keyIdentifier) {
|
||||||
return missingSecretKeyId;
|
super("Key " + fingerprint + " does not contain a secret key for public key " + keyIdentifier, fingerprint);
|
||||||
|
this.missingSecretKeyIdentifier = keyIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public MissingSecretKeyException(@Nonnull OpenPgpFingerprint fingerprint, long keyId) {
|
||||||
|
this(fingerprint, new KeyIdentifier(keyId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyIdentifier getMissingSecretKeyIdentifier() {
|
||||||
|
return missingSecretKeyIdentifier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PublicKeyAlgorithmPolicyException extends KeyException {
|
public static class PublicKeyAlgorithmPolicyException extends KeyException {
|
||||||
|
|
||||||
private final long violatingSubkeyId;
|
private final KeyIdentifier violatingSubkeyId;
|
||||||
|
|
||||||
public PublicKeyAlgorithmPolicyException(@Nonnull OpenPgpFingerprint fingerprint, long keyId, @Nonnull PublicKeyAlgorithm algorithm, int bitSize) {
|
public PublicKeyAlgorithmPolicyException(@Nonnull OpenPGPCertificate.OpenPGPComponentKey subkey,
|
||||||
super("Subkey " + Long.toHexString(keyId) + " of key " + fingerprint + " is violating the Public Key Algorithm Policy:\n" +
|
@Nonnull PublicKeyAlgorithm algorithm,
|
||||||
algorithm + " of size " + bitSize + " is not acceptable.", fingerprint);
|
int bitSize) {
|
||||||
this.violatingSubkeyId = keyId;
|
super("Subkey " + subkey.getKeyIdentifier() + " of key " + subkey.getCertificate().getKeyIdentifier() +
|
||||||
|
" is violating the Public Key Algorithm Policy:\n" +
|
||||||
|
algorithm + " of size " + bitSize + " is not acceptable.", OpenPgpFingerprint.of(subkey));
|
||||||
|
this.violatingSubkeyId = subkey.getKeyIdentifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getViolatingSubkeyId() {
|
public PublicKeyAlgorithmPolicyException(@Nonnull OpenPgpFingerprint fingerprint,
|
||||||
|
long keyId,
|
||||||
|
@Nonnull PublicKeyAlgorithm algorithm,
|
||||||
|
int bitSize) {
|
||||||
|
super("Subkey " + Long.toHexString(keyId) + " of key " + fingerprint + " is violating the Public Key Algorithm Policy:\n" +
|
||||||
|
algorithm + " of size " + bitSize + " is not acceptable.", fingerprint);
|
||||||
|
this.violatingSubkeyId = new KeyIdentifier(keyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyIdentifier getViolatingSubkeyId() {
|
||||||
return violatingSubkeyId;
|
return violatingSubkeyId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ import org.pgpainless.bouncycastle.extensions.toOpenPGPCertificate
|
||||||
import org.pgpainless.encryption_signing.EncryptionOptions.EncryptionKeySelector
|
import org.pgpainless.encryption_signing.EncryptionOptions.EncryptionKeySelector
|
||||||
import org.pgpainless.exception.KeyException.*
|
import org.pgpainless.exception.KeyException.*
|
||||||
import org.pgpainless.implementation.ImplementationFactory
|
import org.pgpainless.implementation.ImplementationFactory
|
||||||
import org.pgpainless.key.OpenPgpFingerprint
|
|
||||||
import org.pgpainless.key.SubkeyIdentifier
|
import org.pgpainless.key.SubkeyIdentifier
|
||||||
import org.pgpainless.key.info.KeyAccessor
|
import org.pgpainless.key.info.KeyAccessor
|
||||||
import org.pgpainless.key.info.KeyRingInfo
|
import org.pgpainless.key.info.KeyRingInfo
|
||||||
|
@ -197,7 +196,7 @@ class EncryptionOptions(private val purpose: EncryptionPurpose) {
|
||||||
encryptionKeySelector.selectEncryptionSubkeys(
|
encryptionKeySelector.selectEncryptionSubkeys(
|
||||||
info.getEncryptionSubkeys(userId, purpose))
|
info.getEncryptionSubkeys(userId, purpose))
|
||||||
if (subkeys.isEmpty()) {
|
if (subkeys.isEmpty()) {
|
||||||
throw UnacceptableEncryptionKeyException(OpenPgpFingerprint.of(cert))
|
throw UnacceptableEncryptionKeyException(cert)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (subkey in subkeys) {
|
for (subkey in subkeys) {
|
||||||
|
@ -295,13 +294,11 @@ class EncryptionOptions(private val purpose: EncryptionPurpose) {
|
||||||
try {
|
try {
|
||||||
info.primaryKeyExpirationDate
|
info.primaryKeyExpirationDate
|
||||||
} catch (e: NoSuchElementException) {
|
} catch (e: NoSuchElementException) {
|
||||||
throw UnacceptableSelfSignatureException(
|
throw UnacceptableSelfSignatureException(cert)
|
||||||
OpenPgpFingerprint.of(cert))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (primaryKeyExpiration != null && primaryKeyExpiration < evaluationDate) {
|
if (primaryKeyExpiration != null && primaryKeyExpiration < evaluationDate) {
|
||||||
throw ExpiredKeyException(
|
throw ExpiredKeyException(cert, primaryKeyExpiration)
|
||||||
OpenPgpFingerprint.of(cert), primaryKeyExpiration)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var encryptionSubkeys = selector.selectEncryptionSubkeys(info.getEncryptionSubkeys(purpose))
|
var encryptionSubkeys = selector.selectEncryptionSubkeys(info.getEncryptionSubkeys(purpose))
|
||||||
|
@ -318,7 +315,7 @@ class EncryptionOptions(private val purpose: EncryptionPurpose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encryptionSubkeys.isEmpty()) {
|
if (encryptionSubkeys.isEmpty()) {
|
||||||
throw UnacceptableEncryptionKeyException(OpenPgpFingerprint.of(cert))
|
throw UnacceptableEncryptionKeyException(cert)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (subkey in encryptionSubkeys) {
|
for (subkey in encryptionSubkeys) {
|
||||||
|
|
|
@ -157,14 +157,13 @@ class SigningOptions {
|
||||||
|
|
||||||
val signingPubKeys = keyRingInfo.signingSubkeys
|
val signingPubKeys = keyRingInfo.signingSubkeys
|
||||||
if (signingPubKeys.isEmpty()) {
|
if (signingPubKeys.isEmpty()) {
|
||||||
throw UnacceptableSigningKeyException(of(signingKey))
|
throw UnacceptableSigningKeyException(signingKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (signingPubKey in signingPubKeys) {
|
for (signingPubKey in signingPubKeys) {
|
||||||
val signingSecKey: OpenPGPSecretKey =
|
val signingSecKey: OpenPGPSecretKey =
|
||||||
signingKey.getSecretKey(signingPubKey)
|
signingKey.getSecretKey(signingPubKey)
|
||||||
?: throw MissingSecretKeyException(
|
?: throw MissingSecretKeyException(signingPubKey)
|
||||||
of(signingKey), signingPubKey.keyIdentifier.keyId)
|
|
||||||
val signingPrivKey: OpenPGPPrivateKey =
|
val signingPrivKey: OpenPGPPrivateKey =
|
||||||
unlockSecretKey(signingSecKey, signingKeyProtector)
|
unlockSecretKey(signingSecKey, signingKeyProtector)
|
||||||
val hashAlgorithms =
|
val hashAlgorithms =
|
||||||
|
@ -220,12 +219,11 @@ class SigningOptions {
|
||||||
val keyRingInfo = inspectKeyRing(openPGPKey, evaluationDate)
|
val keyRingInfo = inspectKeyRing(openPGPKey, evaluationDate)
|
||||||
val signingPubKeys = keyRingInfo.signingSubkeys
|
val signingPubKeys = keyRingInfo.signingSubkeys
|
||||||
if (signingPubKeys.isEmpty()) {
|
if (signingPubKeys.isEmpty()) {
|
||||||
throw UnacceptableSigningKeyException(of(openPGPKey))
|
throw UnacceptableSigningKeyException(openPGPKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!signingPubKeys.any { it.keyIdentifier.matches(signingKey.keyIdentifier) }) {
|
if (!signingPubKeys.any { it.keyIdentifier.matches(signingKey.keyIdentifier) }) {
|
||||||
throw MissingSecretKeyException(
|
throw MissingSecretKeyException(signingKey)
|
||||||
of(openPGPKey), signingKey.keyIdentifier.keyId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val signingPrivKey = unlockSecretKey(signingKey, signingKeyProtector)
|
val signingPrivKey = unlockSecretKey(signingKey, signingKeyProtector)
|
||||||
|
@ -258,13 +256,16 @@ class SigningOptions {
|
||||||
keyId: Long,
|
keyId: Long,
|
||||||
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
||||||
subpacketsCallback: Callback? = null
|
subpacketsCallback: Callback? = null
|
||||||
) =
|
): SigningOptions {
|
||||||
addInlineSignature(
|
val key = signingKey.toOpenPGPKey()
|
||||||
|
val subkeyIdentifier = KeyIdentifier(keyId)
|
||||||
|
return addInlineSignature(
|
||||||
signingKeyProtector,
|
signingKeyProtector,
|
||||||
signingKey.toOpenPGPKey().getSecretKey(KeyIdentifier(keyId))
|
key.getSecretKey(subkeyIdentifier)
|
||||||
?: throw MissingSecretKeyException(of(signingKey), keyId),
|
?: throw MissingSecretKeyException(of(signingKey), subkeyIdentifier),
|
||||||
signatureType,
|
signatureType,
|
||||||
subpacketsCallback)
|
subpacketsCallback)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add detached signatures with all key rings from the provided secret key ring collection.
|
* Add detached signatures with all key rings from the provided secret key ring collection.
|
||||||
|
@ -332,14 +333,13 @@ class SigningOptions {
|
||||||
|
|
||||||
val signingPubKeys = keyRingInfo.signingSubkeys
|
val signingPubKeys = keyRingInfo.signingSubkeys
|
||||||
if (signingPubKeys.isEmpty()) {
|
if (signingPubKeys.isEmpty()) {
|
||||||
throw UnacceptableSigningKeyException(of(signingKey))
|
throw UnacceptableSigningKeyException(signingKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (signingPubKey in signingPubKeys) {
|
for (signingPubKey in signingPubKeys) {
|
||||||
val signingSecKey: OpenPGPSecretKey =
|
val signingSecKey: OpenPGPSecretKey =
|
||||||
signingKey.getSecretKey(signingPubKey.keyIdentifier)
|
signingKey.getSecretKey(signingPubKey.keyIdentifier)
|
||||||
?: throw MissingSecretKeyException(
|
?: throw MissingSecretKeyException(signingPubKey)
|
||||||
of(signingKey), signingPubKey.keyIdentifier.keyId)
|
|
||||||
addDetachedSignature(
|
addDetachedSignature(
|
||||||
signingKeyProtector, signingSecKey, userId, signatureType, subpacketCallback)
|
signingKeyProtector, signingSecKey, userId, signatureType, subpacketCallback)
|
||||||
}
|
}
|
||||||
|
@ -421,14 +421,17 @@ class SigningOptions {
|
||||||
keyId: Long,
|
keyId: Long,
|
||||||
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
signatureType: DocumentSignatureType = DocumentSignatureType.BINARY_DOCUMENT,
|
||||||
subpacketsCallback: Callback? = null
|
subpacketsCallback: Callback? = null
|
||||||
) =
|
): SigningOptions {
|
||||||
addDetachedSignature(
|
val key = signingKey.toOpenPGPKey()
|
||||||
|
val signingKeyIdentifier = KeyIdentifier(keyId)
|
||||||
|
return addDetachedSignature(
|
||||||
signingKeyProtector,
|
signingKeyProtector,
|
||||||
signingKey.toOpenPGPKey().getSecretKey(KeyIdentifier(keyId))
|
key.getSecretKey(signingKeyIdentifier)
|
||||||
?: throw MissingSecretKeyException(of(signingKey), keyId),
|
?: throw MissingSecretKeyException(of(key), signingKeyIdentifier),
|
||||||
null,
|
null,
|
||||||
signatureType,
|
signatureType,
|
||||||
subpacketsCallback)
|
subpacketsCallback)
|
||||||
|
}
|
||||||
|
|
||||||
private fun addSigningMethod(
|
private fun addSigningMethod(
|
||||||
signingKey: OpenPGPPrivateKey,
|
signingKey: OpenPGPPrivateKey,
|
||||||
|
@ -443,10 +446,7 @@ class SigningOptions {
|
||||||
if (!getPolicy().publicKeyAlgorithmPolicy.isAcceptable(publicKeyAlgorithm, bitStrength)) {
|
if (!getPolicy().publicKeyAlgorithmPolicy.isAcceptable(publicKeyAlgorithm, bitStrength)) {
|
||||||
throw UnacceptableSigningKeyException(
|
throw UnacceptableSigningKeyException(
|
||||||
PublicKeyAlgorithmPolicyException(
|
PublicKeyAlgorithmPolicyException(
|
||||||
of(signingKey),
|
signingKey.secretKey, publicKeyAlgorithm, bitStrength))
|
||||||
signingSecretKey.keyID,
|
|
||||||
publicKeyAlgorithm,
|
|
||||||
bitStrength))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val generator: PGPSignatureGenerator =
|
val generator: PGPSignatureGenerator =
|
||||||
|
|
|
@ -132,17 +132,13 @@ abstract class OpenPgpFingerprint : CharSequence, Comparable<OpenPgpFingerprint>
|
||||||
*/
|
*/
|
||||||
@JvmStatic fun of(keys: PGPKeyRing): OpenPgpFingerprint = of(keys.publicKey)
|
@JvmStatic fun of(keys: PGPKeyRing): OpenPgpFingerprint = of(keys.publicKey)
|
||||||
|
|
||||||
/**
|
/** Return the [OpenPgpFingerprint] of the primary key of the given [OpenPGPCertificate]. */
|
||||||
* Return the [OpenPgpFingerprint] of the primary key of the given [OpenPGPCertificate].
|
|
||||||
*/
|
|
||||||
@JvmStatic fun of(cert: OpenPGPCertificate): OpenPgpFingerprint = of(cert.pgpPublicKeyRing)
|
@JvmStatic fun of(cert: OpenPGPCertificate): OpenPgpFingerprint = of(cert.pgpPublicKeyRing)
|
||||||
|
|
||||||
/**
|
/** Return the [OpenPgpFingerprint] of the given [OpenPGPComponentKey]. */
|
||||||
* Return the [OpenPgpFingerprint] of the given [OpenPGPComponentKey].
|
@JvmStatic fun of(key: OpenPGPComponentKey): OpenPgpFingerprint = of(key.pgpPublicKey)
|
||||||
*/
|
|
||||||
@JvmStatic fun of (key: OpenPGPComponentKey): OpenPgpFingerprint = of(key.pgpPublicKey)
|
|
||||||
|
|
||||||
@JvmStatic fun of (key: OpenPGPPrivateKey): OpenPgpFingerprint = of(key.secretKey)
|
@JvmStatic fun of(key: OpenPGPPrivateKey): OpenPgpFingerprint = of(key.secretKey)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to parse an [OpenPgpFingerprint] from the given fingerprint string. If the trimmed
|
* Try to parse an [OpenPgpFingerprint] from the given fingerprint string. If the trimmed
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue