1package org.bouncycastle.jce.provider;
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.DSAPublicKey;
9import java.security.spec.DSAParameterSpec;
10import java.security.spec.DSAPublicKeySpec;
11
12import org.bouncycastle.asn1.ASN1Encodable;
13import org.bouncycastle.asn1.ASN1Encoding;
14import org.bouncycastle.asn1.ASN1Integer;
15import org.bouncycastle.asn1.DERNull;
16import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
17import org.bouncycastle.asn1.x509.DSAParameter;
18import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
19import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
20import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
21
22public class JDKDSAPublicKey
23    implements DSAPublicKey
24{
25    private static final long serialVersionUID = 1752452449903495175L;
26
27    private BigInteger      y;
28    private DSAParams       dsaSpec;
29
30    JDKDSAPublicKey(
31        DSAPublicKeySpec    spec)
32    {
33        this.y = spec.getY();
34        this.dsaSpec = new DSAParameterSpec(spec.getP(), spec.getQ(), spec.getG());
35    }
36
37    JDKDSAPublicKey(
38        DSAPublicKey    key)
39    {
40        this.y = key.getY();
41        this.dsaSpec = key.getParams();
42    }
43
44    JDKDSAPublicKey(
45        DSAPublicKeyParameters  params)
46    {
47        this.y = params.getY();
48        this.dsaSpec = new DSAParameterSpec(params.getParameters().getP(), params.getParameters().getQ(), params.getParameters().getG());
49    }
50
51    JDKDSAPublicKey(
52        BigInteger        y,
53        DSAParameterSpec  dsaSpec)
54    {
55        this.y = y;
56        this.dsaSpec = dsaSpec;
57    }
58
59    JDKDSAPublicKey(
60        SubjectPublicKeyInfo    info)
61    {
62
63        ASN1Integer              derY;
64
65        try
66        {
67            derY = (ASN1Integer)info.parsePublicKey();
68        }
69        catch (IOException e)
70        {
71            throw new IllegalArgumentException("invalid info structure in DSA public key");
72        }
73
74        this.y = derY.getValue();
75
76        if (isNotNull(info.getAlgorithm().getParameters()))
77        {
78            DSAParameter params = DSAParameter.getInstance(info.getAlgorithm().getParameters());
79
80            this.dsaSpec = new DSAParameterSpec(params.getP(), params.getQ(), params.getG());
81        }
82    }
83
84    private boolean isNotNull(ASN1Encodable parameters)
85    {
86        return parameters != null && !DERNull.INSTANCE.equals(parameters);
87    }
88
89    public String getAlgorithm()
90    {
91        return "DSA";
92    }
93
94    public String getFormat()
95    {
96        return "X.509";
97    }
98
99    public byte[] getEncoded()
100    {
101        try
102        {
103            if (dsaSpec == null)
104            {
105                return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new ASN1Integer(y)).getEncoded(ASN1Encoding.DER);
106            }
107
108            return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG())), new ASN1Integer(y)).getEncoded(ASN1Encoding.DER);
109        }
110        catch (IOException e)
111        {
112            return null;
113        }
114    }
115
116    public DSAParams getParams()
117    {
118        return dsaSpec;
119    }
120
121    public BigInteger getY()
122    {
123        return y;
124    }
125
126    public String toString()
127    {
128        StringBuffer    buf = new StringBuffer();
129        String          nl = System.getProperty("line.separator");
130
131        buf.append("DSA Public Key").append(nl);
132        buf.append("            y: ").append(this.getY().toString(16)).append(nl);
133
134        return buf.toString();
135    }
136
137    public int hashCode()
138    {
139        return this.getY().hashCode() ^ this.getParams().getG().hashCode()
140                ^ this.getParams().getP().hashCode() ^ this.getParams().getQ().hashCode();
141    }
142
143    public boolean equals(
144        Object o)
145    {
146        if (!(o instanceof DSAPublicKey))
147        {
148            return false;
149        }
150
151        DSAPublicKey other = (DSAPublicKey)o;
152
153        return this.getY().equals(other.getY())
154            && this.getParams().getG().equals(other.getParams().getG())
155            && this.getParams().getP().equals(other.getParams().getP())
156            && this.getParams().getQ().equals(other.getParams().getQ());
157    }
158
159    private void readObject(
160        ObjectInputStream in)
161        throws IOException, ClassNotFoundException
162    {
163        this.y = (BigInteger)in.readObject();
164        this.dsaSpec = new DSAParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject());
165    }
166
167    private void writeObject(
168        ObjectOutputStream out)
169        throws IOException
170    {
171        out.writeObject(y);
172        out.writeObject(dsaSpec.getP());
173        out.writeObject(dsaSpec.getQ());
174        out.writeObject(dsaSpec.getG());
175    }
176}
177