1package org.bouncycastle.jcajce.provider.asymmetric.dsa;
2
3import java.io.IOException;
4import java.io.ObjectInputStream;
5import java.io.ObjectOutputStream;
6import java.math.BigInteger;
7import java.security.interfaces.DSAParams;
8import java.security.interfaces.DSAPrivateKey;
9import java.security.spec.DSAParameterSpec;
10import java.security.spec.DSAPrivateKeySpec;
11import java.util.Enumeration;
12
13import org.bouncycastle.asn1.ASN1Encodable;
14import org.bouncycastle.asn1.ASN1Integer;
15import org.bouncycastle.asn1.ASN1ObjectIdentifier;
16import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
17import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
18import org.bouncycastle.asn1.x509.DSAParameter;
19import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
20import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
21import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
22import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl;
23import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
24
25public class BCDSAPrivateKey
26    implements DSAPrivateKey, PKCS12BagAttributeCarrier
27{
28    private static final long serialVersionUID = -4677259546958385734L;
29
30    private BigInteger          x;
31    private transient DSAParams dsaSpec;
32
33    private transient PKCS12BagAttributeCarrierImpl attrCarrier = new PKCS12BagAttributeCarrierImpl();
34
35    protected BCDSAPrivateKey()
36    {
37    }
38
39    BCDSAPrivateKey(
40        DSAPrivateKey key)
41    {
42        this.x = key.getX();
43        this.dsaSpec = key.getParams();
44    }
45
46    BCDSAPrivateKey(
47        DSAPrivateKeySpec spec)
48    {
49        this.x = spec.getX();
50        this.dsaSpec = new DSAParameterSpec(spec.getP(), spec.getQ(), spec.getG());
51    }
52
53    public BCDSAPrivateKey(
54        PrivateKeyInfo info)
55        throws IOException
56    {
57        DSAParameter    params = DSAParameter.getInstance(info.getPrivateKeyAlgorithm().getParameters());
58        ASN1Integer      derX = (ASN1Integer)info.parsePrivateKey();
59
60        this.x = derX.getValue();
61        this.dsaSpec = new DSAParameterSpec(params.getP(), params.getQ(), params.getG());
62    }
63
64    BCDSAPrivateKey(
65        DSAPrivateKeyParameters params)
66    {
67        this.x = params.getX();
68        this.dsaSpec = new DSAParameterSpec(params.getParameters().getP(), params.getParameters().getQ(), params.getParameters().getG());
69    }
70
71    public String getAlgorithm()
72    {
73        return "DSA";
74    }
75
76    /**
77     * return the encoding format we produce in getEncoded().
78     *
79     * @return the string "PKCS#8"
80     */
81    public String getFormat()
82    {
83        return "PKCS#8";
84    }
85
86    /**
87     * Return a PKCS8 representation of the key. The sequence returned
88     * represents a full PrivateKeyInfo object.
89     *
90     * @return a PKCS8 representation of the key.
91     */
92    public byte[] getEncoded()
93    {
94        return KeyUtil.getEncodedPrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG()).toASN1Primitive()), new ASN1Integer(getX()));
95    }
96
97    public DSAParams getParams()
98    {
99        return dsaSpec;
100    }
101
102    public BigInteger getX()
103    {
104        return x;
105    }
106
107    public boolean equals(
108        Object o)
109    {
110        if (!(o instanceof DSAPrivateKey))
111        {
112            return false;
113        }
114
115        DSAPrivateKey other = (DSAPrivateKey)o;
116
117        return this.getX().equals(other.getX())
118            && this.getParams().getG().equals(other.getParams().getG())
119            && this.getParams().getP().equals(other.getParams().getP())
120            && this.getParams().getQ().equals(other.getParams().getQ());
121    }
122
123    public int hashCode()
124    {
125        return this.getX().hashCode() ^ this.getParams().getG().hashCode()
126                ^ this.getParams().getP().hashCode() ^ this.getParams().getQ().hashCode();
127    }
128
129    public void setBagAttribute(
130        ASN1ObjectIdentifier oid,
131        ASN1Encodable attribute)
132    {
133        attrCarrier.setBagAttribute(oid, attribute);
134    }
135
136    public ASN1Encodable getBagAttribute(
137        ASN1ObjectIdentifier oid)
138    {
139        return attrCarrier.getBagAttribute(oid);
140    }
141
142    public Enumeration getBagAttributeKeys()
143    {
144        return attrCarrier.getBagAttributeKeys();
145    }
146
147    private void readObject(
148        ObjectInputStream in)
149        throws IOException, ClassNotFoundException
150    {
151        in.defaultReadObject();
152
153        this.dsaSpec = new DSAParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject());
154        this.attrCarrier = new PKCS12BagAttributeCarrierImpl();
155    }
156
157    private void writeObject(
158        ObjectOutputStream out)
159        throws IOException
160    {
161        out.defaultWriteObject();
162
163        out.writeObject(dsaSpec.getP());
164        out.writeObject(dsaSpec.getQ());
165        out.writeObject(dsaSpec.getG());
166    }
167}
168