mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-17 18:02:05 +01:00
Add util methods
This commit is contained in:
parent
396590f4c2
commit
29fbf21d01
2 changed files with 166 additions and 3 deletions
|
@ -20,18 +20,33 @@ import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
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.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKey;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
|
|
||||||
public class BCUtil {
|
public class BCUtil {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(BCUtil.class.getName());
|
||||||
|
|
||||||
|
/*
|
||||||
|
PGPXxxKeyRing -> PGPXxxKeyRingCollection
|
||||||
|
*/
|
||||||
public static PGPPublicKeyRingCollection keyRingsToKeyRingCollection(PGPPublicKeyRing... rings)
|
public static PGPPublicKeyRingCollection keyRingsToKeyRingCollection(PGPPublicKeyRing... rings)
|
||||||
throws IOException, PGPException {
|
throws IOException, PGPException {
|
||||||
return new PGPPublicKeyRingCollection(Arrays.asList(rings));
|
return new PGPPublicKeyRingCollection(Arrays.asList(rings));
|
||||||
|
@ -42,6 +57,10 @@ public class BCUtil {
|
||||||
return new PGPSecretKeyRingCollection(Arrays.asList(rings));
|
return new PGPSecretKeyRingCollection(Arrays.asList(rings));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
PGPSecretKeyRing -> PGPPublicKeyRing
|
||||||
|
*/
|
||||||
|
|
||||||
public static PGPPublicKeyRing publicKeyRingFromSecretKeyRing(PGPSecretKeyRing secring) {
|
public static PGPPublicKeyRing publicKeyRingFromSecretKeyRing(PGPSecretKeyRing secring) {
|
||||||
List<PGPPublicKey> list = new ArrayList<>();
|
List<PGPPublicKey> list = new ArrayList<>();
|
||||||
for (Iterator<PGPPublicKey> i = secring.getPublicKeys(); i.hasNext(); ) {
|
for (Iterator<PGPPublicKey> i = secring.getPublicKeys(); i.hasNext(); ) {
|
||||||
|
@ -60,4 +79,111 @@ public class BCUtil {
|
||||||
throw new AssertionError(e);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -22,36 +22,73 @@ import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.util.BCUtil;
|
import de.vanitasvitae.crypto.pgpainless.util.BCUtil;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class BCUtilTest extends AbstractPGPainlessTest {
|
public class BCUtilTest extends AbstractPGPainlessTest {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(BCUtil.class.getName());
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test()
|
public void test()
|
||||||
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
|
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException,
|
||||||
|
IOException {
|
||||||
PGPSecretKeyRing sec = PGPainless.generateKeyRing().simpleEcKeyRing("donald@duck.tails");
|
PGPSecretKeyRing sec = PGPainless.generateKeyRing().simpleEcKeyRing("donald@duck.tails");
|
||||||
PGPPublicKeyRing pub = BCUtil.publicKeyRingFromSecretKeyRing(sec);
|
PGPPublicKeyRing pub = BCUtil.publicKeyRingFromSecretKeyRing(sec);
|
||||||
|
|
||||||
|
LOGGER.log(Level.INFO, "Main ID: " + sec.getPublicKey().getKeyID() + " " + pub.getPublicKey().getKeyID());
|
||||||
|
|
||||||
int secSize = 0;
|
int secSize = 0;
|
||||||
Iterator<PGPPublicKey> secPubIt = sec.getPublicKeys();
|
Iterator<PGPPublicKey> secPubIt = sec.getPublicKeys();
|
||||||
while (secPubIt.hasNext()) {
|
while (secPubIt.hasNext()) {
|
||||||
secPubIt.next();
|
PGPPublicKey k = secPubIt.next();
|
||||||
|
LOGGER.log(Level.INFO, "" + k.getKeyID() + " " + k.isEncryptionKey() + " " + k.isMasterKey());
|
||||||
secSize++;
|
secSize++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGGER.log(Level.INFO, "After BCUtil.publickKeyRingFromSecretKeyRing()");
|
||||||
int pubSize = 0;
|
int pubSize = 0;
|
||||||
Iterator<PGPPublicKey> pubPubIt = pub.getPublicKeys();
|
Iterator<PGPPublicKey> pubPubIt = pub.getPublicKeys();
|
||||||
while (pubPubIt.hasNext()) {
|
while (pubPubIt.hasNext()) {
|
||||||
pubPubIt.next();
|
PGPPublicKey k = pubPubIt.next();
|
||||||
|
LOGGER.log(Level.INFO, "" + k.getKeyID() + " " + k.isEncryptionKey() + " " + k.isMasterKey());
|
||||||
pubSize++;
|
pubSize++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGGER.log(Level.INFO, " Pub: " + pubSize + " Sec: " + secSize);
|
||||||
assertEquals(secSize, pubSize);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue