diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.java b/pgpainless-core/src/main/java/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.java index 1510a865..3aab17c9 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.java +++ b/pgpainless-core/src/main/java/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.java @@ -315,7 +315,33 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface { @Override public SecretKeyRingEditorInterface revokeUserId(String userId, SecretKeyRingProtector secretKeyRingProtector, - RevocationAttributes revocationAttributes) + @Nullable RevocationAttributes revocationAttributes) + throws PGPException { + if (revocationAttributes != null) { + RevocationAttributes.Reason reason = revocationAttributes.getReason(); + if (reason != RevocationAttributes.Reason.NO_REASON + && reason != RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID) { + throw new IllegalArgumentException("Revocation reason must either be NO_REASON or USER_ID_NO_LONGER_VALID"); + } + } + + RevocationSignatureSubpackets.Callback callback = new RevocationSignatureSubpackets.Callback() { + @Override + public void modifyHashedSubpackets(RevocationSignatureSubpackets hashedSubpackets) { + if (revocationAttributes != null) { + hashedSubpackets.setRevocationReason(false, revocationAttributes); + } + } + }; + + return revokeUserId(userId, secretKeyRingProtector, callback); + } + + @Override + public SecretKeyRingEditorInterface revokeUserId( + String userId, + SecretKeyRingProtector secretKeyRingProtector, + @Nullable RevocationSignatureSubpackets.Callback subpacketCallback) throws PGPException { Iterator userIds = secretKeyRing.getPublicKey().getUserIDs(); boolean found = false; @@ -328,38 +354,23 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface { if (!found) { throw new NoSuchElementException("No user-id '" + userId + "' found on the key."); } - return doRevokeUserId(userId, secretKeyRingProtector, revocationAttributes); + return doRevokeUserId(userId, secretKeyRingProtector, subpacketCallback); } private SecretKeyRingEditorInterface doRevokeUserId(String userId, SecretKeyRingProtector protector, - RevocationAttributes revocationAttributes) + @Nullable RevocationSignatureSubpackets.Callback callback) throws PGPException { PGPSecretKey primarySecretKey = secretKeyRing.getSecretKey(); PGPPublicKey primaryPublicKey = primarySecretKey.getPublicKey(); - PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(primarySecretKey, protector); + RevocationSignatureBuilder signatureBuilder = new RevocationSignatureBuilder( + SignatureType.CERTIFICATION_REVOCATION, + primarySecretKey, + protector); - PGPSignatureSubpacketGenerator subpacketGenerator = new PGPSignatureSubpacketGenerator(); - subpacketGenerator.setSignatureCreationTime(false, new Date()); - subpacketGenerator.setRevocable(false, false); - subpacketGenerator.setIssuerFingerprint(false, primarySecretKey); - if (revocationAttributes != null) { - RevocationAttributes.Reason reason = revocationAttributes.getReason(); - if (reason != RevocationAttributes.Reason.NO_REASON - && reason != RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID) { - throw new IllegalArgumentException("Revocation reason must either be NO_REASON or USER_ID_NO_LONGER_VALID"); - } - subpacketGenerator.setRevocationReason( - false, - revocationAttributes.getReason().code(), - revocationAttributes.getDescription()); - } + signatureBuilder.applyCallback(callback); - PGPSignatureGenerator signatureGenerator = SignatureUtils.getSignatureGeneratorFor(primarySecretKey); - signatureGenerator.setHashedSubpackets(subpacketGenerator.generate()); - signatureGenerator.init(SignatureType.CERTIFICATION_REVOCATION.getCode(), privateKey); - - PGPSignature revocationSignature = signatureGenerator.generateCertification(userId, primaryPublicKey); + PGPSignature revocationSignature = signatureBuilder.build(userId); primaryPublicKey = PGPPublicKey.addCertification(primaryPublicKey, userId, revocationSignature); PGPPublicKeyRing publicKeyRing = KeyRingUtils.publicKeyRingFrom(secretKeyRing); diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.java b/pgpainless-core/src/main/java/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.java index 117d52be..41a395f9 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.java +++ b/pgpainless-core/src/main/java/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.java @@ -190,7 +190,7 @@ public interface SecretKeyRingEditorInterface { default SecretKeyRingEditorInterface revokeUserId(String userId, SecretKeyRingProtector secretKeyRingProtector) throws PGPException { - return revokeUserId(userId, secretKeyRingProtector, null); + return revokeUserId(userId, secretKeyRingProtector, (RevocationAttributes) null); } /** @@ -203,9 +203,14 @@ public interface SecretKeyRingEditorInterface { */ SecretKeyRingEditorInterface revokeUserId(String userId, SecretKeyRingProtector secretKeyRingProtector, - RevocationAttributes revocationAttributes) + @Nullable RevocationAttributes revocationAttributes) throws PGPException; + SecretKeyRingEditorInterface revokeUserId(String userId, + SecretKeyRingProtector secretKeyRingProtector, + @Nullable RevocationSignatureSubpackets.Callback subpacketCallback) + throws PGPException; + /** * Set the expiration date for the primary key of the key ring. * If the key is supposed to never expire, then an expiration date of null is expected. diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/builder/RevocationSignatureBuilder.java b/pgpainless-core/src/main/java/org/pgpainless/signature/builder/RevocationSignatureBuilder.java index d9f6ece3..3449a5dd 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/builder/RevocationSignatureBuilder.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/builder/RevocationSignatureBuilder.java @@ -20,6 +20,7 @@ public class RevocationSignatureBuilder extends AbstractSignatureBuilder