aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/PGPObjectFactory.java
blob: 73b11b9a18350a06376e4ac986bf8f126fabdd0e (plain)
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
package org.spongycastle.openpgp;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.spongycastle.bcpg.BCPGInputStream;
import org.spongycastle.bcpg.PacketTags;
import org.spongycastle.openpgp.operator.KeyFingerPrintCalculator;
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;

/**
 * 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 PGPPublicKeyRingCollection or PGPSecretKeyRingCollection.
 */
public class PGPObjectFactory
{
    private BCPGInputStream in;
    private KeyFingerPrintCalculator fingerPrintCalculator;

    public PGPObjectFactory(
        InputStream in)
    {
        this(in, new JcaKeyFingerprintCalculator());
    }

    /**
     * Create an object factor suitable for reading keys, key rings and key ring collections.
     *
     * @param in stream to read 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;
    }

    public PGPObjectFactory(
        byte[] bytes)
    {
        this(new ByteArrayInputStream(bytes));
    }

    /**
     * Create an object factor suitable for reading keys, key rings and key ring collections.
     *
     * @param bytes stream to read from
     * @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 is reached.
     * 
     * @return Object
     * @throws IOException on a parse error
     */
    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.SECRET_SUBKEY:
            try
            {
                return PGPSecretKeyRing.readSubkey(in, fingerPrintCalculator);
            }
            catch (PGPException e)
            {
                throw new IOException("processing error: " + e.getMessage());
            }
        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());
    }
}