Add util methods

This commit is contained in:
Paul Schaub 2018-06-21 15:18:19 +02:00
parent 396590f4c2
commit 29fbf21d01
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
2 changed files with 166 additions and 3 deletions

View File

@ -20,18 +20,33 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import de.vanitasvitae.crypto.pgpainless.algorithm.KeyFlag;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
public class BCUtil {
private static final Logger LOGGER = Logger.getLogger(BCUtil.class.getName());
/*
PGPXxxKeyRing -> PGPXxxKeyRingCollection
*/
public static PGPPublicKeyRingCollection keyRingsToKeyRingCollection(PGPPublicKeyRing... rings)
throws IOException, PGPException {
return new PGPPublicKeyRingCollection(Arrays.asList(rings));
@ -42,6 +57,10 @@ public class BCUtil {
return new PGPSecretKeyRingCollection(Arrays.asList(rings));
}
/*
PGPSecretKeyRing -> PGPPublicKeyRing
*/
public static PGPPublicKeyRing publicKeyRingFromSecretKeyRing(PGPSecretKeyRing secring) {
List<PGPPublicKey> list = new ArrayList<>();
for (Iterator<PGPPublicKey> i = secring.getPublicKeys(); i.hasNext(); ) {
@ -60,4 +79,111 @@ public class BCUtil {
throw new AssertionError(e);
}
}
/*
PGPXxxKeyRingCollection -> PGPXxxKeyRing
*/
public static PGPSecretKeyRing getKeyRingFromCollection(PGPSecretKeyRingCollection collection, Long id)
throws PGPException {
PGPSecretKeyRing uncleanedRing = collection.getSecretKeyRing(id);
PGPPublicKeyRing publicKeys = publicKeyRingFromSecretKeyRing(uncleanedRing);
// Determine ids of signed keys
Set<Long> signedKeyIds = new HashSet<>();
signedKeyIds.add(id); // Add the signing key itself
Iterator<PGPPublicKey> signedPubKeys = publicKeys.getKeysWithSignaturesBy(id);
while (signedPubKeys.hasNext()) {
signedKeyIds.add(signedPubKeys.next().getKeyID());
}
PGPSecretKeyRing cleanedRing = uncleanedRing;
Iterator<PGPSecretKey> secretKeys = uncleanedRing.getSecretKeys();
while (secretKeys.hasNext()) {
PGPSecretKey secretKey = secretKeys.next();
if (!signedKeyIds.contains(secretKey.getKeyID())) {
cleanedRing = PGPSecretKeyRing.removeSecretKey(cleanedRing, secretKey);
}
}
return cleanedRing;
}
public static PGPPublicKeyRing getKeyRingFromCollection(PGPPublicKeyRingCollection collection, Long id)
throws PGPException {
return removeUnsignedKeysFromKeyRing(collection.getPublicKeyRing(id), id);
}
public static PGPPublicKeyRing removeUnsignedKeysFromKeyRing(PGPPublicKeyRing ring, Long masterKeyId) {
Set<Long> signedKeyIds = new HashSet<>();
signedKeyIds.add(masterKeyId);
Iterator<PGPPublicKey> signedKeys = ring.getKeysWithSignaturesBy(masterKeyId);
while (signedKeys.hasNext()) {
signedKeyIds.add(signedKeys.next().getKeyID());
}
PGPPublicKeyRing cleaned = ring;
Iterator<PGPPublicKey> publicKeys = ring.getPublicKeys();
while (publicKeys.hasNext()) {
PGPPublicKey publicKey = publicKeys.next();
if (!signedKeyIds.contains(publicKey.getKeyID())) {
cleaned = PGPPublicKeyRing.removePublicKey(cleaned, publicKey);
}
}
return cleaned;
}
public static PGPPublicKey getMasterKeyFrom(PGPPublicKeyRing ring) {
Iterator<PGPPublicKey> it = ring.getPublicKeys();
while (it.hasNext()) {
PGPPublicKey k = it.next();
if (k.isMasterKey()) {
return k;
}
}
return null;
}
public static Set<Long> signingKeyIds(PGPSecretKeyRing ring) {
Set<Long> ids = new HashSet<>();
Iterator<PGPPublicKey> it = ring.getPublicKeys();
while (it.hasNext()) {
PGPPublicKey k = it.next();
boolean signingKey = false;
Iterator sit = k.getSignatures();
while (sit.hasNext()) {
Object n = sit.next();
if (!(n instanceof PGPSignature)) {
continue;
}
PGPSignature s = (PGPSignature) n;
if (!s.hasSubpackets()) {
continue;
}
try {
s.verifyCertification(ring.getPublicKey(s.getKeyID()));
} catch (PGPException e) {
LOGGER.log(Level.WARNING, "Could not verify signature on " + Long.toHexString(k.getKeyID()) + " made by " + Long.toHexString(s.getKeyID()));
continue;
}
PGPSignatureSubpacketVector hashed = s.getHashedSubPackets();
if (KeyFlag.fromInteger(hashed.getKeyFlags()).contains(KeyFlag.SIGN_DATA)) {
signingKey = true;
break;
}
}
if (signingKey) {
ids.add(k.getKeyID());
}
}
return ids;
}
}

View File

@ -22,36 +22,73 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import de.vanitasvitae.crypto.pgpainless.util.BCUtil;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.junit.Test;
public class BCUtilTest extends AbstractPGPainlessTest {
private static final Logger LOGGER = Logger.getLogger(BCUtil.class.getName());
@Test
public void test()
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException,
IOException {
PGPSecretKeyRing sec = PGPainless.generateKeyRing().simpleEcKeyRing("donald@duck.tails");
PGPPublicKeyRing pub = BCUtil.publicKeyRingFromSecretKeyRing(sec);
LOGGER.log(Level.INFO, "Main ID: " + sec.getPublicKey().getKeyID() + " " + pub.getPublicKey().getKeyID());
int secSize = 0;
Iterator<PGPPublicKey> secPubIt = sec.getPublicKeys();
while (secPubIt.hasNext()) {
secPubIt.next();
PGPPublicKey k = secPubIt.next();
LOGGER.log(Level.INFO, "" + k.getKeyID() + " " + k.isEncryptionKey() + " " + k.isMasterKey());
secSize++;
}
LOGGER.log(Level.INFO, "After BCUtil.publickKeyRingFromSecretKeyRing()");
int pubSize = 0;
Iterator<PGPPublicKey> pubPubIt = pub.getPublicKeys();
while (pubPubIt.hasNext()) {
pubPubIt.next();
PGPPublicKey k = pubPubIt.next();
LOGGER.log(Level.INFO, "" + k.getKeyID() + " " + k.isEncryptionKey() + " " + k.isMasterKey());
pubSize++;
}
LOGGER.log(Level.INFO, " Pub: " + pubSize + " Sec: " + secSize);
assertEquals(secSize, pubSize);
PGPSecretKeyRingCollection secCol = BCUtil.keyRingsToKeyRingCollection(sec);
int secColSize = 0;
Iterator<PGPSecretKeyRing> secColIt = secCol.getKeyRings();
while (secColIt.hasNext()) {
PGPSecretKeyRing r = secColIt.next();
LOGGER.log(Level.INFO, "" + r.getPublicKey().getKeyID());
secColSize++;
}
LOGGER.log(Level.INFO, "SecCol: " + secColSize);
PGPPublicKeyRingCollection pubCol = BCUtil.keyRingsToKeyRingCollection(pub);
int pubColSize = 0;
Iterator<PGPPublicKeyRing> pubColIt = pubCol.getKeyRings();
while (pubColIt.hasNext()) {
PGPPublicKeyRing r = pubColIt.next();
LOGGER.log(Level.INFO, "" + r.getPublicKey().getKeyID());
pubColSize++;
}
LOGGER.log(Level.INFO, "PubCol: " + pubColSize);
}
}