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 9c88e6c5..66336c6f 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 @@ -190,6 +190,28 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface { return this; } + @Override + public SecretKeyRingEditorInterface removeUserId( + SelectUserId userIdSelector, + SecretKeyRingProtector protector) + throws PGPException { + RevocationAttributes revocationAttributes = RevocationAttributes.createCertificateRevocation() + .withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID) + .withoutDescription(); + return revokeUserIds(userIdSelector, + protector, + revocationAttributes); + } + + @Override + public SecretKeyRingEditorInterface removeUserId( + CharSequence userId, + SecretKeyRingProtector protector) throws PGPException { + return removeUserId( + SelectUserId.exactMatch(userId.toString()), + protector); + } + // TODO: Move to utility class? private String sanitizeUserId(@Nonnull CharSequence userId) { // TODO: Further research how to sanitize user IDs. 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 b61dbbc1..65d92330 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 @@ -69,6 +69,14 @@ public interface SecretKeyRingEditorInterface { @Nonnull SecretKeyRingProtector protector) throws PGPException; + SecretKeyRingEditorInterface removeUserId(SelectUserId userIdSelector, + SecretKeyRingProtector protector) + throws PGPException; + + SecretKeyRingEditorInterface removeUserId(CharSequence userId, + SecretKeyRingProtector protector) + throws PGPException; + /** * Add a subkey to the key ring. * The subkey will be generated from the provided {@link KeySpec}. diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/util/KeyRingUtils.java b/pgpainless-core/src/main/java/org/pgpainless/key/util/KeyRingUtils.java index 9848ced9..400414c2 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/key/util/KeyRingUtils.java +++ b/pgpainless-core/src/main/java/org/pgpainless/key/util/KeyRingUtils.java @@ -159,52 +159,6 @@ public final class KeyRingUtils { return ring.getPublicKey(keyId) != null; } - /** - * Delete the given user-id and its certification signatures from the given key. - * - * @deprecated Deleting user-ids is highly discouraged, since it might lead to all sorts of problems - * (e.g. lost key properties). - * Instead, user-ids should only be revoked. - * - * @param secretKeys secret keys - * @param userId user-id - * @return modified secret keys - */ - @Deprecated - public static PGPSecretKeyRing deleteUserId(PGPSecretKeyRing secretKeys, String userId) { - PGPSecretKey secretKey = secretKeys.getSecretKey(); // user-ids are located on primary key only - PGPPublicKey publicKey = secretKey.getPublicKey(); // user-ids are placed on the public key part - publicKey = PGPPublicKey.removeCertification(publicKey, userId); - if (publicKey == null) { - throw new NoSuchElementException("User-ID " + userId + " not found on the key."); - } - secretKey = PGPSecretKey.replacePublicKey(secretKey, publicKey); - secretKeys = PGPSecretKeyRing.insertSecretKey(secretKeys, secretKey); - return secretKeys; - } - - /** - * Delete the given user-id and its certification signatures from the given certificate. - * - * @deprecated Deleting user-ids is highly discouraged, since it might lead to all sorts of problems - * (e.g. lost key properties). - * Instead, user-ids should only be revoked. - * - * @param publicKeys certificate - * @param userId user-id - * @return modified secret keys - */ - @Deprecated - public static PGPPublicKeyRing deleteUserId(PGPPublicKeyRing publicKeys, String userId) { - PGPPublicKey publicKey = publicKeys.getPublicKey(); // user-ids are located on primary key only - publicKey = PGPPublicKey.removeCertification(publicKey, userId); - if (publicKey == null) { - throw new NoSuchElementException("User-ID " + userId + " not found on the key."); - } - publicKeys = PGPPublicKeyRing.insertPublicKey(publicKeys, publicKey); - return publicKeys; - } - public static T injectCertification(T keyRing, PGPPublicKey certifiedKey, PGPSignature certification) { PGPSecretKeyRing secretKeys = null; PGPPublicKeyRing publicKeys; diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/util/KeyRingUtilTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/util/KeyRingUtilTest.java index 9f2546ae..45552664 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/util/KeyRingUtilTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/util/KeyRingUtilTest.java @@ -6,17 +6,14 @@ package org.pgpainless.key.util; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; -import java.util.NoSuchElementException; import java.util.Random; import org.bouncycastle.bcpg.attr.ImageAttribute; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPSignatureGenerator; @@ -33,49 +30,6 @@ import org.pgpainless.util.CollectionUtils; public class KeyRingUtilTest { - @Test - public void testDeleteUserIdFromSecretKeyRing() - throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("Alice", null); - - secretKeys = PGPainless.modifyKeyRing(secretKeys) - .addUserId("Bob", SecretKeyRingProtector.unprotectedKeys()) - .done(); - assertEquals(2, CollectionUtils.iteratorToList(secretKeys.getPublicKey().getUserIDs()).size()); - - secretKeys = KeyRingUtils.deleteUserId(secretKeys, "Bob"); - - assertEquals(1, CollectionUtils.iteratorToList(secretKeys.getPublicKey().getUserIDs()).size()); - } - - @Test - public void testDeleteUserIdFromPublicKeyRing() - throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("Alice", null); - - secretKeys = PGPainless.modifyKeyRing(secretKeys) - .addUserId("Bob", SecretKeyRingProtector.unprotectedKeys()) - .done(); - PGPPublicKeyRing publicKeys = PGPainless.extractCertificate(secretKeys); - assertEquals(2, CollectionUtils.iteratorToList(publicKeys.getPublicKey().getUserIDs()).size()); - - publicKeys = KeyRingUtils.deleteUserId(publicKeys, "Alice"); - - assertEquals(1, CollectionUtils.iteratorToList(publicKeys.getPublicKey().getUserIDs()).size()); - } - - @Test - public void testDeleteNonexistentUserIdFromKeyRingThrows() - throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { - PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() - .modernKeyRing("Alice", null); - - assertThrows(NoSuchElementException.class, - () -> KeyRingUtils.deleteUserId(secretKeys, "Charlie")); - } - @Test public void testInjectCertification() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()