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