DSASigner.java revision 5db505e1f6a68c8d5dfdb0fed0b8607dea7bed96
1package org.bouncycastle.jcajce.provider.asymmetric.dsa;
2
3import java.io.IOException;
4import java.math.BigInteger;
5import java.security.InvalidKeyException;
6import java.security.PrivateKey;
7import java.security.PublicKey;
8import java.security.SecureRandom;
9import java.security.SignatureException;
10import java.security.SignatureSpi;
11import java.security.interfaces.DSAKey;
12import java.security.spec.AlgorithmParameterSpec;
13
14import org.bouncycastle.asn1.ASN1Encoding;
15import org.bouncycastle.asn1.ASN1Integer;
16import org.bouncycastle.asn1.ASN1Primitive;
17import org.bouncycastle.asn1.ASN1Sequence;
18import org.bouncycastle.asn1.DERSequence;
19import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
20import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
21import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
22import org.bouncycastle.crypto.CipherParameters;
23import org.bouncycastle.crypto.DSA;
24import org.bouncycastle.crypto.Digest;
25import org.bouncycastle.crypto.digests.NullDigest;
26// BEGIN android-added
27import org.bouncycastle.crypto.digests.AndroidDigestFactory;
28// END android-added
29// BEGIN android-removed
30// import org.bouncycastle.crypto.digests.SHA1Digest;
31// import org.bouncycastle.crypto.digests.SHA224Digest;
32// import org.bouncycastle.crypto.digests.SHA256Digest;
33// import org.bouncycastle.crypto.digests.SHA384Digest;
34// import org.bouncycastle.crypto.digests.SHA512Digest;
35// END android-removed
36import org.bouncycastle.crypto.params.ParametersWithRandom;
37// BEGIN android-removed
38// import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
39// END android-removed
40
41public class DSASigner
42    extends SignatureSpi
43    implements PKCSObjectIdentifiers, X509ObjectIdentifiers
44{
45    private Digest                  digest;
46    private DSA                     signer;
47    private SecureRandom            random;
48
49    protected DSASigner(
50        Digest digest,
51        DSA signer)
52    {
53        this.digest = digest;
54        this.signer = signer;
55    }
56
57    protected void engineInitVerify(
58        PublicKey   publicKey)
59        throws InvalidKeyException
60    {
61        CipherParameters    param;
62
63        if (publicKey instanceof DSAKey)
64        {
65            param = DSAUtil.generatePublicKeyParameter(publicKey);
66        }
67        else
68        {
69            try
70            {
71                byte[]  bytes = publicKey.getEncoded();
72
73                publicKey = new BCDSAPublicKey(SubjectPublicKeyInfo.getInstance(bytes));
74
75                if (publicKey instanceof DSAKey)
76                {
77                    param = DSAUtil.generatePublicKeyParameter(publicKey);
78                }
79                else
80                {
81                    throw new InvalidKeyException("can't recognise key type in DSA based signer");
82                }
83            }
84            catch (Exception e)
85            {
86                throw new InvalidKeyException("can't recognise key type in DSA based signer");
87            }
88        }
89
90        digest.reset();
91        signer.init(false, param);
92    }
93
94    protected void engineInitSign(
95        PrivateKey      privateKey,
96        SecureRandom    random)
97        throws InvalidKeyException
98    {
99        this.random = random;
100        engineInitSign(privateKey);
101    }
102
103    protected void engineInitSign(
104        PrivateKey  privateKey)
105        throws InvalidKeyException
106    {
107        CipherParameters    param;
108
109        param = DSAUtil.generatePrivateKeyParameter(privateKey);
110
111        if (random != null)
112        {
113            param = new ParametersWithRandom(param, random);
114        }
115
116        digest.reset();
117        signer.init(true, param);
118    }
119
120    protected void engineUpdate(
121        byte    b)
122        throws SignatureException
123    {
124        digest.update(b);
125    }
126
127    protected void engineUpdate(
128        byte[]  b,
129        int     off,
130        int     len)
131        throws SignatureException
132    {
133        digest.update(b, off, len);
134    }
135
136    protected byte[] engineSign()
137        throws SignatureException
138    {
139        byte[]  hash = new byte[digest.getDigestSize()];
140
141        digest.doFinal(hash, 0);
142
143        try
144        {
145            BigInteger[]    sig = signer.generateSignature(hash);
146
147            return derEncode(sig[0], sig[1]);
148        }
149        catch (Exception e)
150        {
151            throw new SignatureException(e.toString());
152        }
153    }
154
155    protected boolean engineVerify(
156        byte[]  sigBytes)
157        throws SignatureException
158    {
159        byte[]  hash = new byte[digest.getDigestSize()];
160
161        digest.doFinal(hash, 0);
162
163        BigInteger[]    sig;
164
165        try
166        {
167            sig = derDecode(sigBytes);
168        }
169        catch (Exception e)
170        {
171            throw new SignatureException("error decoding signature bytes.");
172        }
173
174        return signer.verifySignature(hash, sig[0], sig[1]);
175    }
176
177    protected void engineSetParameter(
178        AlgorithmParameterSpec params)
179    {
180        throw new UnsupportedOperationException("engineSetParameter unsupported");
181    }
182
183    /**
184     * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)">
185     */
186    protected void engineSetParameter(
187        String  param,
188        Object  value)
189    {
190        throw new UnsupportedOperationException("engineSetParameter unsupported");
191    }
192
193    /**
194     * @deprecated
195     */
196    protected Object engineGetParameter(
197        String      param)
198    {
199        throw new UnsupportedOperationException("engineSetParameter unsupported");
200    }
201
202    private byte[] derEncode(
203        BigInteger  r,
204        BigInteger  s)
205        throws IOException
206    {
207        ASN1Integer[] rs = new ASN1Integer[]{ new ASN1Integer(r), new ASN1Integer(s) };
208        return new DERSequence(rs).getEncoded(ASN1Encoding.DER);
209    }
210
211    private BigInteger[] derDecode(
212        byte[]  encoding)
213        throws IOException
214    {
215        ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding);
216        return new BigInteger[]{
217            ((ASN1Integer)s.getObjectAt(0)).getValue(),
218            ((ASN1Integer)s.getObjectAt(1)).getValue()
219        };
220    }
221
222    static public class stdDSA
223        extends DSASigner
224    {
225        public stdDSA()
226        {
227            // BEGIN android-changed
228            super(AndroidDigestFactory.getSHA1(), new org.bouncycastle.crypto.signers.DSASigner());
229            // END android-changed
230        }
231    }
232
233    // BEGIN android-removed
234    // static public class detDSA
235    //     extends DSASigner
236    // {
237    //     public detDSA()
238    //     {
239    //         super(new SHA1Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA1Digest())));
240    //     }
241    // }
242    // END android-removed
243
244    static public class dsa224
245        extends DSASigner
246    {
247        public dsa224()
248        {
249            // BEGIN android-changed
250            super(AndroidDigestFactory.getSHA224(), new org.bouncycastle.crypto.signers.DSASigner());
251            // END android-changed
252        }
253    }
254
255    // BEGIN android-removed
256    // static public class detDSA224
257    //     extends DSASigner
258    // {
259    //     public detDSA224()
260    //     {
261    //         super(new SHA224Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA224Digest())));
262    //     }
263    // }
264    // END android-removed
265
266    static public class dsa256
267        extends DSASigner
268    {
269        public dsa256()
270        {
271            // BEGIN android-changed
272            super(AndroidDigestFactory.getSHA256(), new org.bouncycastle.crypto.signers.DSASigner());
273            // END android-changed
274        }
275    }
276
277    // BEGIN android-removed
278    // static public class detDSA256
279    //     extends DSASigner
280    // {
281    //     public detDSA256()
282    //     {
283    //         super(new SHA256Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA256Digest())));
284    //     }
285    // }
286    //
287    // static public class dsa384
288    //     extends DSASigner
289    // {
290    //     public dsa384()
291    //     {
292    //         super(new SHA384Digest(), new org.bouncycastle.crypto.signers.DSASigner());
293    //     }
294    // }
295    //
296    // static public class detDSA384
297    //     extends DSASigner
298    // {
299    //     public detDSA384()
300    //     {
301    //         super(new SHA384Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA384Digest())));
302    //     }
303    // }
304    //
305    // static public class dsa512
306    //     extends DSASigner
307    // {
308    //     public dsa512()
309    //     {
310    //         super(new SHA512Digest(), new org.bouncycastle.crypto.signers.DSASigner());
311    //     }
312    // }
313    //
314    // static public class detDSA512
315    //     extends DSASigner
316    // {
317    //     public detDSA512()
318    //     {
319    //         super(new SHA512Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA512Digest())));
320    //     }
321    // }
322    // END android-removed
323
324    static public class noneDSA
325        extends DSASigner
326    {
327        public noneDSA()
328        {
329            super(new NullDigest(), new org.bouncycastle.crypto.signers.DSASigner());
330        }
331    }
332}
333