using System; using System.Collections; using System.IO; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Bcpg.OpenPgp { /// /// General class for reading a PGP object stream. ///

/// Note: if this class finds a PgpPublicKey or a PgpSecretKey it /// will create a PgpPublicKeyRing, or a PgpSecretKeyRing for each /// key found. If all you are trying to do is read a key ring file use /// either PgpPublicKeyRingBundle or PgpSecretKeyRingBundle.

///
public class PgpObjectFactory { private readonly BcpgInputStream bcpgIn; public PgpObjectFactory( Stream inputStream) { this.bcpgIn = BcpgInputStream.Wrap(inputStream); } public PgpObjectFactory( byte[] bytes) : this(new MemoryStream(bytes, false)) { } /// Return the next object in the stream, or null if the end is reached. /// On a parse error public PgpObject NextPgpObject() { PacketTag tag = bcpgIn.NextPacketTag(); if ((int) tag == -1) return null; switch (tag) { case PacketTag.Signature: { IList l = Platform.CreateArrayList(); while (bcpgIn.NextPacketTag() == PacketTag.Signature) { try { l.Add(new PgpSignature(bcpgIn)); } catch (PgpException e) { throw new IOException("can't create signature object: " + e); } } PgpSignature[] sigs = new PgpSignature[l.Count]; for (int i = 0; i < l.Count; ++i) { sigs[i] = (PgpSignature)l[i]; } return new PgpSignatureList(sigs); } case PacketTag.SecretKey: try { return new PgpSecretKeyRing(bcpgIn); } catch (PgpException e) { throw new IOException("can't create secret key object: " + e); } case PacketTag.PublicKey: return new PgpPublicKeyRing(bcpgIn); // TODO Make PgpPublicKey a PgpObject or return a PgpPublicKeyRing // case PacketTag.PublicSubkey: // return PgpPublicKeyRing.ReadSubkey(bcpgIn); case PacketTag.CompressedData: return new PgpCompressedData(bcpgIn); case PacketTag.LiteralData: return new PgpLiteralData(bcpgIn); case PacketTag.PublicKeyEncryptedSession: case PacketTag.SymmetricKeyEncryptedSessionKey: return new PgpEncryptedDataList(bcpgIn); case PacketTag.OnePassSignature: { IList l = Platform.CreateArrayList(); while (bcpgIn.NextPacketTag() == PacketTag.OnePassSignature) { try { l.Add(new PgpOnePassSignature(bcpgIn)); } catch (PgpException e) { throw new IOException("can't create one pass signature object: " + e); } } PgpOnePassSignature[] sigs = new PgpOnePassSignature[l.Count]; for (int i = 0; i < l.Count; ++i) { sigs[i] = (PgpOnePassSignature)l[i]; } return new PgpOnePassSignatureList(sigs); } case PacketTag.Marker: return new PgpMarker(bcpgIn); case PacketTag.Experimental1: case PacketTag.Experimental2: case PacketTag.Experimental3: case PacketTag.Experimental4: return new PgpExperimental(bcpgIn); } throw new IOException("unknown object in stream " + bcpgIn.NextPacketTag()); } [Obsolete("Use NextPgpObject() instead")] public object NextObject() { return NextPgpObject(); } /// /// Return all available objects in a list. /// /// An IList containing all objects from this factory, in order. public IList AllPgpObjects() { IList result = Platform.CreateArrayList(); PgpObject pgpObject; while ((pgpObject = NextPgpObject()) != null) { result.Add(pgpObject); } return result; } } }