All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.openpgp.PGPObjectFactory Maven / Gradle / Ivy

Go to download

The Bouncy Castle Java APIs for the OpenPGP Protocol. The APIs are designed primarily to be used in conjunction with the BC FIPS provider. The APIs may also be used with other providers although if being used in a FIPS context it is the responsibility of the user to ensure that any other providers used are FIPS certified and used appropriately.

There is a newer version: 2.0.9
Show 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