1package org.bouncycastle.asn1.pkcs;
2
3import org.bouncycastle.asn1.ASN1Encodable;
4import org.bouncycastle.asn1.ASN1EncodableVector;
5import org.bouncycastle.asn1.ASN1InputStream;
6import org.bouncycastle.asn1.ASN1OctetString;
7import org.bouncycastle.asn1.ASN1Sequence;
8import org.bouncycastle.asn1.ASN1Set;
9import org.bouncycastle.asn1.ASN1TaggedObject;
10import org.bouncycastle.asn1.DERInteger;
11import org.bouncycastle.asn1.DERObject;
12import org.bouncycastle.asn1.DEROctetString;
13import org.bouncycastle.asn1.DERSequence;
14import org.bouncycastle.asn1.DERTaggedObject;
15import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
16
17import java.io.IOException;
18import java.math.BigInteger;
19import java.util.Enumeration;
20
21public class PrivateKeyInfo
22    extends ASN1Encodable
23{
24    private DERObject               privKey;
25    private AlgorithmIdentifier     algId;
26    private ASN1Set                 attributes;
27
28    public static PrivateKeyInfo getInstance(
29        ASN1TaggedObject obj,
30        boolean          explicit)
31    {
32        return getInstance(ASN1Sequence.getInstance(obj, explicit));
33    }
34
35    public static PrivateKeyInfo getInstance(
36        Object  obj)
37    {
38        if (obj instanceof PrivateKeyInfo)
39        {
40            return (PrivateKeyInfo)obj;
41        }
42        else if (obj instanceof ASN1Sequence)
43        {
44            return new PrivateKeyInfo((ASN1Sequence)obj);
45        }
46
47        throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
48    }
49
50    public PrivateKeyInfo(
51        AlgorithmIdentifier algId,
52        DERObject           privateKey)
53    {
54        this(algId, privateKey, null);
55    }
56
57    public PrivateKeyInfo(
58        AlgorithmIdentifier algId,
59        DERObject           privateKey,
60        ASN1Set             attributes)
61    {
62        this.privKey = privateKey;
63        this.algId = algId;
64        this.attributes = attributes;
65    }
66
67    public PrivateKeyInfo(
68        ASN1Sequence  seq)
69    {
70        Enumeration e = seq.getObjects();
71
72        BigInteger  version = ((DERInteger)e.nextElement()).getValue();
73        if (version.intValue() != 0)
74        {
75            throw new IllegalArgumentException("wrong version for private key info");
76        }
77
78        algId = new AlgorithmIdentifier((ASN1Sequence)e.nextElement());
79
80        try
81        {
82            ASN1InputStream         aIn = new ASN1InputStream(((ASN1OctetString)e.nextElement()).getOctets());
83
84            privKey = aIn.readObject();
85        }
86        catch (IOException ex)
87        {
88            throw new IllegalArgumentException("Error recoverying private key from sequence");
89        }
90
91        if (e.hasMoreElements())
92        {
93           attributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
94        }
95    }
96
97    public AlgorithmIdentifier getAlgorithmId()
98    {
99        return algId;
100    }
101
102    public DERObject getPrivateKey()
103    {
104        return privKey;
105    }
106
107    public ASN1Set getAttributes()
108    {
109        return attributes;
110    }
111
112    /**
113     * write out an RSA private key with its associated information
114     * as described in PKCS8.
115     * <pre>
116     *      PrivateKeyInfo ::= SEQUENCE {
117     *                              version Version,
118     *                              privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
119     *                              privateKey PrivateKey,
120     *                              attributes [0] IMPLICIT Attributes OPTIONAL
121     *                          }
122     *      Version ::= INTEGER {v1(0)} (v1,...)
123     *
124     *      PrivateKey ::= OCTET STRING
125     *
126     *      Attributes ::= SET OF Attribute
127     * </pre>
128     */
129    public DERObject toASN1Object()
130    {
131        ASN1EncodableVector v = new ASN1EncodableVector();
132
133        v.add(new DERInteger(0));
134        v.add(algId);
135        v.add(new DEROctetString(privKey));
136
137        if (attributes != null)
138        {
139            v.add(new DERTaggedObject(false, 0, attributes));
140        }
141
142        return new DERSequence(v);
143    }
144}
145