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.operator.KeyFingerPrintCalculator;
|
||||
import org.pgpainless.implementation.ImplementationFactory;
|
||||
import org.pgpainless.key.collection.PGPKeyRingCollection;
|
||||
|
||||
public class KeyRingReader {
|
||||
|
||||
|
@ -84,6 +85,19 @@ public class KeyRingReader {
|
|||
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
|
||||
*/
|
||||
|
@ -114,6 +128,14 @@ public class KeyRingReader {
|
|||
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) {
|
||||
if (publicIn == null && secretIn == 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.pgpainless.PGPainless;
|
||||
import org.pgpainless.implementation.ImplementationFactory;
|
||||
import org.pgpainless.key.collection.PGPKeyRingCollection;
|
||||
import org.pgpainless.key.util.KeyRingUtils;
|
||||
|
||||
class KeyRingReaderTest {
|
||||
|
@ -189,12 +190,42 @@ class KeyRingReaderTest {
|
|||
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 {
|
||||
URL resource = getClass().getClassLoader().getResource(fileName);
|
||||
assert resource != null;
|
||||
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)
|
||||
throws IOException, URISyntaxException, PGPException {
|
||||
return PGPainless.readKeyRing().publicKeyRingCollection(getFileInputStreamFromResource(fileName));
|
||||
|
|
Loading…
Reference in a new issue