org.bouncycastle.openpgp.PGPObjectFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcpg-jdk14 Show documentation
Show all versions of bcpg-jdk14 Show documentation
The Bouncy Castle Java API for handling the OpenPGP protocol. This jar contains the OpenPGP API for JDK 1.4. The APIs can be used in conjunction with a JCE/JCA provider such as the one provided with the Bouncy Castle Cryptography APIs.
The newest version!
package org.bouncycastle.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 java.util.NoSuchElementException;
import org.bouncycastle.bcpg.BCPGInputStream;
import org.bouncycastle.bcpg.PacketTags;
import org.bouncycastle.bcpg.UnknownPacket;
import org.bouncycastle.bcpg.UnsupportedPacketVersionException;
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
import org.bouncycastle.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;
private boolean throwForUnknownCriticalPackets = false;
/**
* 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 = BCPGInputStream.wrap(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.RESERVED:
case PacketTags.EXPERIMENTAL_1:
case PacketTags.EXPERIMENTAL_2:
case PacketTags.EXPERIMENTAL_3:
case PacketTags.EXPERIMENTAL_4:
return in.readPacket();
case PacketTags.SIGNATURE:
l = new ArrayList();
while (in.nextPacketTag() == PacketTags.SIGNATURE)
{
try
{
l.add(new PGPSignature(in));
}
catch (UnsupportedPacketVersionException e)
{
// Signatures of unsupported version MUST BE ignored
// see: https://tests.sequoia-pgp.org/#Detached_signatures_with_unknown_packets
continue;
}
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:
case PacketTags.SYMMETRIC_KEY_ENC:
case PacketTags.SYM_ENC_INTEGRITY_PRO:
case PacketTags.AEAD_ENC_DATA:
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.PADDING:
return new PGPPadding(in);
}
int tag = in.nextPacketTag();
UnknownPacket unknownPacket = (UnknownPacket)in.readPacket();
if (throwForUnknownCriticalPackets && unknownPacket.isCritical())
{
// Leave the error message intact for backwards compatibility
throw new IOException("unknown object in stream: " + tag);
}
return unknownPacket;
}
/**
* Support method for Iterable where available.
*/
public Iterator iterator()
{
return new Iterator()
{
private boolean triedNext = false;
private Object obj = null;
public boolean hasNext()
{
if (!triedNext)
{
triedNext = true;
obj = getObject();
}
return obj != null;
}
public Object next()
{
if (!hasNext())
{
throw new NoSuchElementException();
}
triedNext = false;
return obj;
}
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);
}
}
};
}
/**
* If set to true, the object factory will throw an {@link IOException} if it encounters an unknown packet with a
* packet tag within the critical range (0 - 39).
*
* @param throwException whether to throw
* @return object factory
*/
public PGPObjectFactory setThrowForUnknownCriticalPackets(boolean throwException)
{
this.throwForUnknownCriticalPackets = throwException;
return this;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy