mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-23 12:52:07 +01:00
Added PGPKeyRingCollection. Added tests to KeyRingReaderTest to cover parsing of private/pub keys combinations.
This commit is contained in:
parent
8e569e7931
commit
43647f3145
3 changed files with 147 additions and 0 deletions
|
@ -0,0 +1,94 @@
|
||||||
|
package org.pgpainless.key.collection;
|
||||||
|
|
||||||
|
import org.bouncycastle.openpgp.*;
|
||||||
|
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class describes a logic of handling a collection of different {@link PGPKeyRing}. The logic was inspired by
|
||||||
|
* {@link PGPSecretKeyRingCollection} and {@link PGPPublicKeyRingCollection}.
|
||||||
|
*/
|
||||||
|
public class PGPKeyRingCollection {
|
||||||
|
private PGPSecretKeyRingCollection pgpSecretKeyRingCollection;
|
||||||
|
private PGPPublicKeyRingCollection pgpPublicKeyRingCollection;
|
||||||
|
|
||||||
|
public PGPKeyRingCollection(@Nonnull byte[] encoding, @Nonnull KeyFingerPrintCalculator fingerPrintCalculator,
|
||||||
|
boolean isSilent) throws IOException, PGPException {
|
||||||
|
this(new ByteArrayInputStream(encoding), fingerPrintCalculator, isSilent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a {@link PGPKeyRingCollection} from the passed in input stream.
|
||||||
|
*
|
||||||
|
* @param in input stream containing data
|
||||||
|
* @param isSilent flag indicating that unsupported objects will be ignored
|
||||||
|
* @throws IOException if a problem parsing the base stream occurs
|
||||||
|
* @throws PGPException if an object is encountered which isn't a {@link PGPSecretKeyRing} or {@link PGPPublicKeyRing}
|
||||||
|
*/
|
||||||
|
public PGPKeyRingCollection(@Nonnull InputStream in, @Nonnull KeyFingerPrintCalculator fingerPrintCalculator,
|
||||||
|
boolean isSilent) throws IOException, PGPException {
|
||||||
|
PGPObjectFactory pgpFact = new PGPObjectFactory(in, fingerPrintCalculator);
|
||||||
|
Object obj;
|
||||||
|
|
||||||
|
List<PGPSecretKeyRing> secretKeyRings = new ArrayList<>();
|
||||||
|
List<PGPPublicKeyRing> publicKeyRings = new ArrayList<>();
|
||||||
|
|
||||||
|
while ((obj = pgpFact.nextObject()) != null) {
|
||||||
|
if (obj instanceof PGPSecretKeyRing) {
|
||||||
|
secretKeyRings.add((PGPSecretKeyRing) obj);
|
||||||
|
} else if (obj instanceof PGPPublicKeyRing) {
|
||||||
|
publicKeyRings.add((PGPPublicKeyRing) obj);
|
||||||
|
} else if (!isSilent) {
|
||||||
|
throw new PGPException(obj.getClass().getName() + " found where " +
|
||||||
|
PGPSecretKeyRing.class.getSimpleName() + " or " +
|
||||||
|
PGPPublicKeyRing.class.getSimpleName() + " expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pgpSecretKeyRingCollection = new PGPSecretKeyRingCollection(secretKeyRings);
|
||||||
|
pgpPublicKeyRingCollection = new PGPPublicKeyRingCollection(publicKeyRings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PGPKeyRingCollection(Collection<PGPKeyRing> collection, boolean isSilent) throws IOException, PGPException {
|
||||||
|
List<PGPSecretKeyRing> secretKeyRings = new ArrayList<>();
|
||||||
|
List<PGPPublicKeyRing> publicKeyRings = new ArrayList<>();
|
||||||
|
|
||||||
|
for (PGPKeyRing pgpKeyRing : collection) {
|
||||||
|
if (pgpKeyRing instanceof PGPSecretKeyRing) {
|
||||||
|
secretKeyRings.add((PGPSecretKeyRing) pgpKeyRing);
|
||||||
|
} else if (pgpKeyRing instanceof PGPPublicKeyRing) {
|
||||||
|
publicKeyRings.add((PGPPublicKeyRing) pgpKeyRing);
|
||||||
|
} else if (!isSilent) {
|
||||||
|
throw new PGPException(pgpKeyRing.getClass().getName() + " found where " +
|
||||||
|
PGPSecretKeyRing.class.getSimpleName() + " or " +
|
||||||
|
PGPPublicKeyRing.class.getSimpleName() + " expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pgpSecretKeyRingCollection = new PGPSecretKeyRingCollection(secretKeyRings);
|
||||||
|
pgpPublicKeyRingCollection = new PGPPublicKeyRingCollection(publicKeyRings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PGPSecretKeyRingCollection getPGPSecretKeyRingCollection() {
|
||||||
|
return pgpSecretKeyRingCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PGPPublicKeyRingCollection getPgpPublicKeyRingCollection() {
|
||||||
|
return pgpPublicKeyRingCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of rings in this collection.
|
||||||
|
*
|
||||||
|
* @return total size of {@link PGPSecretKeyRingCollection} and {@link PGPPublicKeyRingCollection}
|
||||||
|
* in this collection
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return pgpSecretKeyRingCollection.size() + pgpPublicKeyRingCollection.size();
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||||
import org.bouncycastle.openpgp.PGPUtil;
|
import org.bouncycastle.openpgp.PGPUtil;
|
||||||
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
|
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
|
||||||
import org.pgpainless.implementation.ImplementationFactory;
|
import org.pgpainless.implementation.ImplementationFactory;
|
||||||
|
import org.pgpainless.key.collection.PGPKeyRingCollection;
|
||||||
|
|
||||||
public class KeyRingReader {
|
public class KeyRingReader {
|
||||||
|
|
||||||
|
@ -84,6 +85,19 @@ public class KeyRingReader {
|
||||||
return secretKeyRingCollection(asciiArmored.getBytes(UTF8));
|
return secretKeyRingCollection(asciiArmored.getBytes(UTF8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PGPKeyRingCollection keyRingCollection(@Nonnull InputStream inputStream, boolean isSilent)
|
||||||
|
throws IOException, PGPException {
|
||||||
|
return readKeyRingCollection(inputStream, isSilent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PGPKeyRingCollection keyRingCollection(@Nonnull byte[] bytes, boolean isSilent) throws IOException, PGPException {
|
||||||
|
return keyRingCollection(new ByteArrayInputStream(bytes), isSilent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PGPKeyRingCollection keyRingCollection(@Nonnull String asciiArmored, boolean isSilent) throws IOException, PGPException {
|
||||||
|
return keyRingCollection(asciiArmored.getBytes(UTF8), isSilent);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
STATIC METHODS
|
STATIC METHODS
|
||||||
*/
|
*/
|
||||||
|
@ -114,6 +128,14 @@ public class KeyRingReader {
|
||||||
ImplementationFactory.getInstance().getKeyFingerprintCalculator());
|
ImplementationFactory.getInstance().getKeyFingerprintCalculator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PGPKeyRingCollection readKeyRingCollection(@Nonnull InputStream inputStream, boolean isSilent)
|
||||||
|
throws IOException, PGPException {
|
||||||
|
return new PGPKeyRingCollection(
|
||||||
|
getDecoderStream(inputStream),
|
||||||
|
ImplementationFactory.getInstance().getKeyFingerprintCalculator(),
|
||||||
|
isSilent);
|
||||||
|
}
|
||||||
|
|
||||||
private static void validateStreamsNotBothNull(InputStream publicIn, InputStream secretIn) {
|
private static void validateStreamsNotBothNull(InputStream publicIn, InputStream secretIn) {
|
||||||
if (publicIn == null && secretIn == null) {
|
if (publicIn == null && secretIn == null) {
|
||||||
throw new NullPointerException("publicIn and secretIn cannot be BOTH null.");
|
throw new NullPointerException("publicIn and secretIn cannot be BOTH null.");
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.bouncycastle.openpgp.*;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.implementation.ImplementationFactory;
|
import org.pgpainless.implementation.ImplementationFactory;
|
||||||
|
import org.pgpainless.key.collection.PGPKeyRingCollection;
|
||||||
import org.pgpainless.key.util.KeyRingUtils;
|
import org.pgpainless.key.util.KeyRingUtils;
|
||||||
|
|
||||||
class KeyRingReaderTest {
|
class KeyRingReaderTest {
|
||||||
|
@ -189,12 +190,42 @@ class KeyRingReaderTest {
|
||||||
assertEquals(10, getPgpSecretKeyRingsFromResource("10_prv_keys_binary.key").size());
|
assertEquals(10, getPgpSecretKeyRingsFromResource("10_prv_keys_binary.key").size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Many armored keys(private or pub) where each has own -----BEGIN PGP ... KEY BLOCK-----...-----END PGP ... KEY BLOCK-----
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void parseKeysMultiplyArmoredOwnHeader() throws IOException, PGPException, URISyntaxException {
|
||||||
|
assertEquals(10, getPGPKeyRingsFromResource("10_prv_and_pub_keys_armored_own_header.asc").size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Many armored keys(private or pub) where each has own -----BEGIN PGP ... KEY BLOCK-----...-----END PGP ... KEY BLOCK-----
|
||||||
|
* Each of those blocks can have a different count of keys.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void parseKeysMultiplyArmoredOwnWithSingleHeader() throws IOException, PGPException, URISyntaxException {
|
||||||
|
assertEquals(10, getPGPKeyRingsFromResource("10_prv_and_pub_keys_armored_own_with_single_header.asc").size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Many binary keys(private or pub)
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void parseKeysMultiplyBinary() throws IOException, PGPException, URISyntaxException {
|
||||||
|
assertEquals(10, getPGPKeyRingsFromResource("10_prv_and_pub_keys_binary.key").size());
|
||||||
|
}
|
||||||
|
|
||||||
private InputStream getFileInputStreamFromResource(String fileName) throws IOException, URISyntaxException {
|
private InputStream getFileInputStreamFromResource(String fileName) throws IOException, URISyntaxException {
|
||||||
URL resource = getClass().getClassLoader().getResource(fileName);
|
URL resource = getClass().getClassLoader().getResource(fileName);
|
||||||
assert resource != null;
|
assert resource != null;
|
||||||
return new FileInputStream(new File(resource.toURI()));
|
return new FileInputStream(new File(resource.toURI()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PGPKeyRingCollection getPGPKeyRingsFromResource(String fileName)
|
||||||
|
throws IOException, URISyntaxException, PGPException {
|
||||||
|
return PGPainless.readKeyRing().keyRingCollection(getFileInputStreamFromResource(fileName), true);
|
||||||
|
}
|
||||||
|
|
||||||
private PGPPublicKeyRingCollection getPgpPublicKeyRingsFromResource(String fileName)
|
private PGPPublicKeyRingCollection getPgpPublicKeyRingsFromResource(String fileName)
|
||||||
throws IOException, URISyntaxException, PGPException {
|
throws IOException, URISyntaxException, PGPException {
|
||||||
return PGPainless.readKeyRing().publicKeyRingCollection(getFileInputStreamFromResource(fileName));
|
return PGPainless.readKeyRing().publicKeyRingCollection(getFileInputStreamFromResource(fileName));
|
||||||
|
|
Loading…
Reference in a new issue