summary refs log tree commit diff
path: root/crypto/src/openpgp/PgpObjectFactory.cs
blob: 1f1c32c837a0065d837e2e0fc36f047bd78bef1a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
using System;
using System.Collections;
using System.IO;

using Org.BouncyCastle.Utilities;

namespace Org.BouncyCastle.Bcpg.OpenPgp
{
	/// <remarks>
    /// General class for reading a PGP object stream.
    /// <p>
    /// 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.</p>
	/// </remarks>
	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))
        {
        }

		/// <summary>Return the next object in the stream, or null if the end is reached.</summary>
		/// <exception cref="IOException">On a parse error</exception>
        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();
		}

		/// <summary>
		/// Return all available objects in a list.
		/// </summary>
		/// <returns>An <c>IList</c> containing all objects from this factory, in order.</returns>
		public IList AllPgpObjects()
		{
            IList result = Platform.CreateArrayList();
			PgpObject pgpObject;
			while ((pgpObject = NextPgpObject()) != null)
			{
				result.Add(pgpObject);
			}
			return result;
		}

        /// <summary>
        /// Read all available objects, returning only those that are assignable to the specified type.
        /// </summary>
        /// <param name="type">The type of objects to return. All other objects are ignored.</param>
        /// <returns>An <c>IList</c> containing the filtered objects from this factory, in order.</returns>
        public IList FilterPgpObjects(Type type)
        {
            IList result = Platform.CreateArrayList();
            PgpObject pgpObject;
            while ((pgpObject = NextPgpObject()) != null)
            {
                if (type.IsInstanceOfType(pgpObject))
                {
                    result.Add(pgpObject);
                }
            }
            return result;
        }
    }
}