1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-06-23 03:54:49 +02:00

Implement revocation of subkeys

This commit is contained in:
Paul Schaub 2020-11-13 14:32:29 +01:00
parent b4967db1a2
commit 9b2ad24bda
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
4 changed files with 124 additions and 3 deletions

View file

@ -55,6 +55,7 @@ import org.pgpainless.key.protection.PasswordBasedSecretKeyRingProtector;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.key.protection.UnprotectedKeysProtector;
import org.pgpainless.key.protection.passphrase_provider.SolitaryPassphraseProvider;
import org.pgpainless.key.util.KeyRingUtils;
import org.pgpainless.key.util.OpenPgpKeyAttributeUtil;
import org.pgpainless.util.NotYetImplementedException;
import org.pgpainless.util.Passphrase;
@ -274,8 +275,32 @@ public class KeyRingEditor implements KeyRingEditorInterface {
}
@Override
public KeyRingEditorInterface revokeSubKey(OpenPgpV4Fingerprint fingerprint, SecretKeyRingProtector protector) {
throw new NotYetImplementedException();
public KeyRingEditorInterface revokeSubKey(OpenPgpV4Fingerprint fingerprint, SecretKeyRingProtector protector)
throws PGPException {
PGPSecretKey primaryKey = secretKeyRing.getSecretKey();
PGPPrivateKey privateKey = primaryKey.extractPrivateKey(protector.getDecryptor(primaryKey.getKeyID()));
PGPPublicKey revokeeSubKey = secretKeyRing.getPublicKey(fingerprint.getKeyId());
if (revokeeSubKey == null) {
throw new NoSuchElementException("No subkey with fingerprint " + fingerprint + " found.");
}
PGPContentSignerBuilder contentSignerBuilder = new BcPGPContentSignerBuilder(
primaryKey.getPublicKey().getAlgorithm(),
defaultDigestHashAlgorithm.getAlgorithmId());
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
signatureGenerator.init(SignatureType.SUBKEY_REVOCATION.getCode(), privateKey);
// Generate revocation
PGPSignature subKeyRevocation = signatureGenerator.generateCertification(primaryKey.getPublicKey(), revokeeSubKey);
revokeeSubKey = PGPPublicKey.addCertification(revokeeSubKey, subKeyRevocation);
// Inject revoked public key into key ring
PGPPublicKeyRing publicKeyRing = KeyRingUtils.publicKeyRingFrom(secretKeyRing);
publicKeyRing = PGPPublicKeyRing.insertPublicKey(publicKeyRing, revokeeSubKey);
secretKeyRing = PGPSecretKeyRing.replacePublicKeys(secretKeyRing, publicKeyRing);
return this;
}
@Override

View file

@ -102,7 +102,7 @@ public interface KeyRingEditorInterface {
* @param fingerprint fingerprint of the subkey to be revoked
* @return the builder
*/
KeyRingEditorInterface revokeSubKey(OpenPgpV4Fingerprint fingerprint, SecretKeyRingProtector secretKeyRingProtector);
KeyRingEditorInterface revokeSubKey(OpenPgpV4Fingerprint fingerprint, SecretKeyRingProtector secretKeyRingProtector) throws PGPException;
/**
* Revoke the subkey binding signature of a subkey.

View file

@ -0,0 +1,37 @@
/*
* Copyright 2020 Paul Schaub.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.pgpainless.key.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
public class KeyRingUtils {
public static PGPPublicKeyRing publicKeyRingFrom(PGPSecretKeyRing secretKeys) {
List<PGPPublicKey> publicKeyList = new ArrayList<>();
Iterator<PGPPublicKey> publicKeyIterator = secretKeys.getPublicKeys();
while (publicKeyIterator.hasNext()) {
publicKeyList.add(publicKeyIterator.next());
}
PGPPublicKeyRing publicKeyRing = new PGPPublicKeyRing(publicKeyList);
return publicKeyRing;
}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright 2020 Paul Schaub.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.pgpainless.key.modification;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Iterator;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.junit.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.TestKeys;
import org.pgpainless.key.protection.PasswordBasedSecretKeyRingProtector;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.util.Passphrase;
public class RevokeSubKeyTest {
@Test
public void revokeSukeyTest() throws IOException, PGPException {
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
Iterator<PGPSecretKey> keysIterator = secretKeys.iterator();
PGPSecretKey primaryKey = keysIterator.next();
PGPSecretKey subKey = keysIterator.next();
assertFalse(subKey.getPublicKey().hasRevocation());
SecretKeyRingProtector protector = PasswordBasedSecretKeyRingProtector
.forKey(secretKeys, Passphrase.fromPassword("password123"));
secretKeys = PGPainless.modifyKeyRing(secretKeys)
.revokeSubKey(new OpenPgpV4Fingerprint(subKey), protector)
.done();
keysIterator = secretKeys.iterator();
primaryKey = keysIterator.next();
subKey = keysIterator.next();
assertTrue(subKey.getPublicKey().hasRevocation());
}
}