mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-26 22:32:07 +01:00
Remove support for deleting user-ids and subkeys. Use revoke* instead.
This commit is contained in:
parent
2ac10e7bc7
commit
e4d1aa7edf
3 changed files with 15 additions and 116 deletions
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
package org.pgpainless.key.modification.secretkeyring;
|
package org.pgpainless.key.modification.secretkeyring;
|
||||||
|
|
||||||
import static org.pgpainless.util.CollectionUtils.iteratorToList;
|
|
||||||
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -56,7 +54,6 @@ import org.pgpainless.key.util.RevocationAttributes;
|
||||||
import org.pgpainless.signature.SignatureUtils;
|
import org.pgpainless.signature.SignatureUtils;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorUtil;
|
import org.pgpainless.signature.subpackets.SignatureSubpacketGeneratorUtil;
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
import org.pgpainless.util.selection.userid.SelectUserId;
|
|
||||||
|
|
||||||
public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
||||||
|
|
||||||
|
@ -122,34 +119,6 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
||||||
return userId;
|
return userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SecretKeyRingEditorInterface deleteUserId(String userId, SecretKeyRingProtector protector) {
|
|
||||||
return deleteUserIds(SelectUserId.exactMatch(userId), protector);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SecretKeyRingEditorInterface deleteUserIds(SelectUserId selectionStrategy, SecretKeyRingProtector secretKeyRingProtector) {
|
|
||||||
List<PGPPublicKey> publicKeys = new ArrayList<>();
|
|
||||||
Iterator<PGPPublicKey> publicKeyIterator = secretKeyRing.getPublicKeys();
|
|
||||||
PGPPublicKey primaryKey = publicKeyIterator.next();
|
|
||||||
List<String> matchingUserIds = selectionStrategy.selectUserIds(iteratorToList(primaryKey.getUserIDs()));
|
|
||||||
if (matchingUserIds.isEmpty()) {
|
|
||||||
throw new NoSuchElementException("Key does not have a matching user-id attribute.");
|
|
||||||
}
|
|
||||||
for (String userId : matchingUserIds) {
|
|
||||||
primaryKey = PGPPublicKey.removeCertification(primaryKey, userId);
|
|
||||||
}
|
|
||||||
publicKeys.add(primaryKey);
|
|
||||||
|
|
||||||
while (publicKeyIterator.hasNext()) {
|
|
||||||
publicKeys.add(publicKeyIterator.next());
|
|
||||||
}
|
|
||||||
|
|
||||||
PGPPublicKeyRing publicKeyRing = new PGPPublicKeyRing(publicKeys);
|
|
||||||
secretKeyRing = PGPSecretKeyRing.replacePublicKeys(secretKeyRing, publicKeyRing);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SecretKeyRingEditorInterface addSubKey(@Nonnull KeySpec keySpec,
|
public SecretKeyRingEditorInterface addSubKey(@Nonnull KeySpec keySpec,
|
||||||
@Nonnull Passphrase subKeyPassphrase,
|
@Nonnull Passphrase subKeyPassphrase,
|
||||||
|
@ -213,29 +182,6 @@ public class SecretKeyRingEditor implements SecretKeyRingEditorInterface {
|
||||||
return secretKey;
|
return secretKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SecretKeyRingEditorInterface deleteSubKey(OpenPgpFingerprint fingerprint,
|
|
||||||
SecretKeyRingProtector protector) {
|
|
||||||
return deleteSubKey(fingerprint.getKeyId(), protector);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SecretKeyRingEditorInterface deleteSubKey(long subKeyId,
|
|
||||||
SecretKeyRingProtector protector) {
|
|
||||||
if (secretKeyRing.getSecretKey().getKeyID() == subKeyId) {
|
|
||||||
throw new IllegalArgumentException("You cannot delete the primary key of this key ring.");
|
|
||||||
}
|
|
||||||
|
|
||||||
PGPSecretKey deleteMe = secretKeyRing.getSecretKey(subKeyId);
|
|
||||||
if (deleteMe == null) {
|
|
||||||
throw new NoSuchElementException("KeyRing does not contain a key with keyId " + Long.toHexString(subKeyId));
|
|
||||||
}
|
|
||||||
|
|
||||||
PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.removeSecretKey(secretKeyRing, deleteMe);
|
|
||||||
secretKeyRing = newKeyRing;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SecretKeyRingEditorInterface revoke(SecretKeyRingProtector secretKeyRingProtector,
|
public SecretKeyRingEditorInterface revoke(SecretKeyRingProtector secretKeyRingProtector,
|
||||||
RevocationAttributes revocationAttributes)
|
RevocationAttributes revocationAttributes)
|
||||||
|
|
|
@ -22,7 +22,6 @@ import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
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.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
import org.pgpainless.util.selection.userid.SelectUserId;
|
|
||||||
|
|
||||||
public interface SecretKeyRingEditorInterface {
|
public interface SecretKeyRingEditorInterface {
|
||||||
|
|
||||||
|
@ -46,35 +45,6 @@ public interface SecretKeyRingEditorInterface {
|
||||||
*/
|
*/
|
||||||
SecretKeyRingEditorInterface addUserId(String userId, SecretKeyRingProtector secretKeyRingProtector) throws PGPException;
|
SecretKeyRingEditorInterface addUserId(String userId, SecretKeyRingProtector secretKeyRingProtector) throws PGPException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a user-id from the key ring.
|
|
||||||
*
|
|
||||||
* @param userId exact user-id to be removed
|
|
||||||
* @param secretKeyRingProtector protector to unlock the secret key
|
|
||||||
* @return the builder
|
|
||||||
*/
|
|
||||||
SecretKeyRingEditorInterface deleteUserId(String userId, SecretKeyRingProtector secretKeyRingProtector);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a user-id from the key ring.
|
|
||||||
*
|
|
||||||
* @param userId exact user-id to be removed
|
|
||||||
* @param secretKeyRingProtector protector to unlock the secret key
|
|
||||||
* @return the builder
|
|
||||||
*/
|
|
||||||
default SecretKeyRingEditorInterface deleteUserId(UserId userId, SecretKeyRingProtector secretKeyRingProtector) {
|
|
||||||
return deleteUserId(userId.toString(), secretKeyRingProtector);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete all user-ids from the key, which match the provided {@link SelectUserId} strategy.
|
|
||||||
*
|
|
||||||
* @param selectionStrategy strategy to select user-ids
|
|
||||||
* @param secretKeyRingProtector protector to unlock the secret key
|
|
||||||
* @return the builder
|
|
||||||
*/
|
|
||||||
SecretKeyRingEditorInterface deleteUserIds(SelectUserId selectionStrategy, SecretKeyRingProtector secretKeyRingProtector);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a subkey to the key ring.
|
* Add a subkey to the key ring.
|
||||||
* The subkey will be generated from the provided {@link KeySpec}.
|
* The subkey will be generated from the provided {@link KeySpec}.
|
||||||
|
@ -94,29 +64,6 @@ public interface SecretKeyRingEditorInterface {
|
||||||
PGPSignatureSubpacketVector unhashedSubpackets,
|
PGPSignatureSubpacketVector unhashedSubpackets,
|
||||||
SecretKeyRingProtector subKeyProtector, SecretKeyRingProtector keyRingProtector)
|
SecretKeyRingProtector subKeyProtector, SecretKeyRingProtector keyRingProtector)
|
||||||
throws PGPException;
|
throws PGPException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a subkey from the key ring.
|
|
||||||
* The subkey with the provided fingerprint will be remove from the key ring.
|
|
||||||
* If no suitable subkey is found, a {@link java.util.NoSuchElementException} will be thrown.
|
|
||||||
*
|
|
||||||
* @param fingerprint fingerprint of the subkey to be removed
|
|
||||||
* @param secretKeyRingProtector protector to unlock the secret key ring
|
|
||||||
* @return the builder
|
|
||||||
*/
|
|
||||||
SecretKeyRingEditorInterface deleteSubKey(OpenPgpFingerprint fingerprint, SecretKeyRingProtector secretKeyRingProtector);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a subkey from the key ring.
|
|
||||||
* The subkey with the provided key-id will be removed from the key ring.
|
|
||||||
* If no suitable subkey is found, a {@link java.util.NoSuchElementException} will be thrown.
|
|
||||||
*
|
|
||||||
* @param subKeyId id of the subkey
|
|
||||||
* @param secretKeyRingProtector protector to unlock the secret key ring
|
|
||||||
* @return the builder
|
|
||||||
*/
|
|
||||||
SecretKeyRingEditorInterface deleteSubKey(long subKeyId, SecretKeyRingProtector secretKeyRingProtector);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revoke the key ring.
|
* Revoke the key ring.
|
||||||
* The revocation will be a hard revocation, rendering the whole key invalid for any past or future signatures.
|
* The revocation will be a hard revocation, rendering the whole key invalid for any past or future signatures.
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.implementation.ImplementationFactory;
|
import org.pgpainless.implementation.ImplementationFactory;
|
||||||
import org.pgpainless.key.TestKeys;
|
import org.pgpainless.key.TestKeys;
|
||||||
|
import org.pgpainless.key.info.KeyRingInfo;
|
||||||
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.protection.UnprotectedKeysProtector;
|
import org.pgpainless.key.protection.UnprotectedKeysProtector;
|
||||||
|
@ -30,11 +31,12 @@ public class AddUserIdTest {
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("org.pgpainless.util.TestImplementationFactoryProvider#provideImplementationFactories")
|
@MethodSource("org.pgpainless.util.TestImplementationFactoryProvider#provideImplementationFactories")
|
||||||
public void addUserIdToExistingKeyRing(ImplementationFactory implementationFactory) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
|
public void addUserIdToExistingKeyRing(ImplementationFactory implementationFactory) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException, InterruptedException {
|
||||||
ImplementationFactory.setFactoryImplementation(implementationFactory);
|
ImplementationFactory.setFactoryImplementation(implementationFactory);
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("alice@wonderland.lit", "rabb1th0le");
|
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("alice@wonderland.lit", "rabb1th0le");
|
||||||
|
|
||||||
Iterator<String> userIds = secretKeys.getSecretKey().getPublicKey().getUserIDs();
|
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
||||||
|
Iterator<String> userIds = info.getValidUserIds().iterator();
|
||||||
assertEquals("alice@wonderland.lit", userIds.next());
|
assertEquals("alice@wonderland.lit", userIds.next());
|
||||||
assertFalse(userIds.hasNext());
|
assertFalse(userIds.hasNext());
|
||||||
|
|
||||||
|
@ -43,16 +45,18 @@ public class AddUserIdTest {
|
||||||
.addUserId("cheshirecat@wonderland.lit", protector)
|
.addUserId("cheshirecat@wonderland.lit", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
userIds = secretKeys.getPublicKey().getUserIDs();
|
info = PGPainless.inspectKeyRing(secretKeys);
|
||||||
|
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 = PGPainless.modifyKeyRing(secretKeys)
|
||||||
.deleteUserId("cheshirecat@wonderland.lit", protector)
|
.revokeUserId("cheshirecat@wonderland.lit", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
userIds = secretKeys.getPublicKey().getUserIDs();
|
info = PGPainless.inspectKeyRing(secretKeys);
|
||||||
|
userIds = info.getValidUserIds().iterator();
|
||||||
assertEquals("alice@wonderland.lit", userIds.next());
|
assertEquals("alice@wonderland.lit", userIds.next());
|
||||||
assertFalse(userIds.hasNext());
|
assertFalse(userIds.hasNext());
|
||||||
}
|
}
|
||||||
|
@ -64,7 +68,7 @@ public class AddUserIdTest {
|
||||||
|
|
||||||
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
|
||||||
assertThrows(NoSuchElementException.class, () -> PGPainless.modifyKeyRing(secretKeys)
|
assertThrows(NoSuchElementException.class, () -> PGPainless.modifyKeyRing(secretKeys)
|
||||||
.deleteUserId("invalid@user.id", new UnprotectedKeysProtector()));
|
.revokeUserId("invalid@user.id", new UnprotectedKeysProtector()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
|
@ -89,17 +93,19 @@ public class AddUserIdTest {
|
||||||
"-----END PGP PRIVATE KEY BLOCK-----\r\n";
|
"-----END PGP PRIVATE KEY BLOCK-----\r\n";
|
||||||
|
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(ARMORED_PRIVATE_KEY);
|
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(ARMORED_PRIVATE_KEY);
|
||||||
Iterator<String> userIds = secretKeys.getSecretKey().getPublicKey().getUserIDs();
|
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
||||||
|
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)
|
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
||||||
.deleteUserId("<user@example.com>", protector)
|
.revokeUserId("<user@example.com>", protector)
|
||||||
.addUserId("cheshirecat@wonderland.lit", protector)
|
.addUserId("cheshirecat@wonderland.lit", protector)
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
userIds = secretKeys.getSecretKey().getPublicKey().getUserIDs();
|
info = PGPainless.inspectKeyRing(secretKeys);
|
||||||
|
userIds = info.getValidUserIds().iterator();
|
||||||
assertEquals("cheshirecat@wonderland.lit", userIds.next());
|
assertEquals("cheshirecat@wonderland.lit", userIds.next());
|
||||||
assertFalse(userIds.hasNext());
|
assertFalse(userIds.hasNext());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue