org.spongycastle.openpgp.PGPObjectFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pg Show documentation
Show all versions of pg Show documentation
Spongy Castle is a package-rename (org.bouncycastle.* to org.spongycastle.*) of Bouncy Castle
intended for the Android platform. Android unfortunately ships with a stripped-down version of
Bouncy Castle, which prevents easy upgrades - Spongy Castle overcomes this and provides a full,
up-to-date version of the Bouncy Castle cryptographic libs.
The newest version!
package org.spongycastle.openpgp;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.spongycastle.bcpg.BCPGInputStream;
import org.spongycastle.bcpg.PacketTags;
import org.spongycastle.openpgp.operator.KeyFingerPrintCalculator;
import org.spongycastle.util.Iterable;
/**
* General class for reading a PGP object stream.
*
* Note: if this class finds a {@link PGPPublicKey} or a {@link PGPSecretKey} it will create a
* {@link PGPPublicKeyRing}, or a {@link PGPSecretKeyRing} for each key found. If all you are trying
* to do is read a key ring file use either {@link PGPPublicKeyRingCollection} or
* {@link PGPSecretKeyRingCollection}.
*
* This factory supports reading the following types of objects:
*
* - {@link PacketTags#SIGNATURE} - produces a {@link PGPSignatureList}
* - {@link PacketTags#SECRET_KEY} - produces a {@link PGPSecretKeyRing}
* - {@link PacketTags#PUBLIC_KEY} - produces a {@link PGPPublicKeyRing}
* - {@link PacketTags#PUBLIC_SUBKEY} - produces a {@link PGPPublicKey}
* - {@link PacketTags#COMPRESSED_DATA} - produces a {@link PGPCompressedData}
* - {@link PacketTags#LITERAL_DATA} - produces a {@link PGPLiteralData}
* - {@link PacketTags#PUBLIC_KEY_ENC_SESSION} - produces a {@link PGPEncryptedDataList}
* - {@link PacketTags#SYMMETRIC_KEY_ENC_SESSION} - produces a {@link PGPEncryptedDataList}
* - {@link PacketTags#ONE_PASS_SIGNATURE} - produces a {@link PGPOnePassSignatureList}
* - {@link PacketTags#MARKER} - produces a {@link PGPMarker}
*
*
*/
public class PGPObjectFactory
implements Iterable
{
private BCPGInputStream in;
private KeyFingerPrintCalculator fingerPrintCalculator;
/**
* Create an object factory suitable for reading PGP objects such as keys, key rings and key
* ring collections, or PGP encrypted data.
*
* @param in stream to read PGP data from.
* @param fingerPrintCalculator calculator to use in key finger print calculations.
*/
public PGPObjectFactory(
InputStream in,
KeyFingerPrintCalculator fingerPrintCalculator)
{
this.in = new BCPGInputStream(in);
this.fingerPrintCalculator = fingerPrintCalculator;
}
/**
* Create an object factory suitable for reading PGP objects such as keys, key rings and key
* ring collections, or PGP encrypted data.
*
* @param bytes PGP encoded data.
* @param fingerPrintCalculator calculator to use in key finger print calculations.
*/
public PGPObjectFactory(
byte[] bytes,
KeyFingerPrintCalculator fingerPrintCalculator)
{
this(new ByteArrayInputStream(bytes), fingerPrintCalculator);
}
/**
* Return the next object in the stream, or null
if the end of stream is reached.
*
* @return one of the supported objects - see class docs for details.
* @throws IOException if an error occurs reading from the wrapped stream or parsing data.
*/
public Object nextObject()
throws IOException
{
List l;
switch (in.nextPacketTag())
{
case -1:
return null;
case PacketTags.SIGNATURE:
l = new ArrayList();
while (in.nextPacketTag() == PacketTags.SIGNATURE)
{
try
{
l.add(new PGPSignature(in));
}
catch (PGPException e)
{
throw new IOException("can't create signature object: " + e);
}
}
return new PGPSignatureList((PGPSignature[])l.toArray(new PGPSignature[l.size()]));
case PacketTags.SECRET_KEY:
try
{
return new PGPSecretKeyRing(in, fingerPrintCalculator);
}
catch (PGPException e)
{
throw new IOException("can't create secret key object: " + e);
}
case PacketTags.PUBLIC_KEY:
return new PGPPublicKeyRing(in, fingerPrintCalculator);
case PacketTags.PUBLIC_SUBKEY:
try
{
return PGPPublicKeyRing.readSubkey(in, fingerPrintCalculator);
}
catch (PGPException e)
{
throw new IOException("processing error: " + e.getMessage());
}
case PacketTags.COMPRESSED_DATA:
return new PGPCompressedData(in);
case PacketTags.LITERAL_DATA:
return new PGPLiteralData(in);
case PacketTags.PUBLIC_KEY_ENC_SESSION:
case PacketTags.SYMMETRIC_KEY_ENC_SESSION:
return new PGPEncryptedDataList(in);
case PacketTags.ONE_PASS_SIGNATURE:
l = new ArrayList();
while (in.nextPacketTag() == PacketTags.ONE_PASS_SIGNATURE)
{
try
{
l.add(new PGPOnePassSignature(in));
}
catch (PGPException e)
{
throw new IOException("can't create one pass signature object: " + e);
}
}
return new PGPOnePassSignatureList((PGPOnePassSignature[])l.toArray(new PGPOnePassSignature[l.size()]));
case PacketTags.MARKER:
return new PGPMarker(in);
case PacketTags.EXPERIMENTAL_1:
case PacketTags.EXPERIMENTAL_2:
case PacketTags.EXPERIMENTAL_3:
case PacketTags.EXPERIMENTAL_4:
return in.readPacket();
}
throw new IOException("unknown object in stream: " + in.nextPacketTag());
}
/**
* Support method for Iterable where available.
*/
public Iterator iterator()
{
return new Iterator()
{
private Object obj = getObject();
public boolean hasNext()
{
return obj != null;
}
public Object next()
{
Object rv = obj;
obj = getObject();;
return rv;
}
public void remove()
{
throw new UnsupportedOperationException("Cannot remove element from factory.");
}
private Object getObject()
{
try
{
return PGPObjectFactory.this.nextObject();
}
catch (IOException e)
{
throw new PGPRuntimeOperationException("Iterator failed to get next object: " + e.getMessage(), e);
}
}
};
}
}