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.spec.AlgorithmParameterSpec;
12
13import org.bouncycastle.asn1.ASN1Encoding;
14import org.bouncycastle.asn1.ASN1Integer;
15import org.bouncycastle.asn1.ASN1Primitive;
16import org.bouncycastle.asn1.ASN1Sequence;
17import org.bouncycastle.asn1.DERSequence;
18import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
19import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
20import org.bouncycastle.crypto.CipherParameters;
21import org.bouncycastle.crypto.DSA;
22import org.bouncycastle.crypto.Digest;
23import org.bouncycastle.crypto.digests.NullDigest;
24// BEGIN android-added
25import org.bouncycastle.crypto.digests.AndroidDigestFactory;
26// END android-added
27// BEGIN android-removed
28// import org.bouncycastle.crypto.digests.SHA1Digest;
29// import org.bouncycastle.crypto.digests.SHA224Digest;
30// import org.bouncycastle.crypto.digests.SHA256Digest;
31// import org.bouncycastle.crypto.digests.SHA384Digest;
32// import org.bouncycastle.crypto.digests.SHA512Digest;
33// END android-removed
34// BEGIN android-added
35import org.bouncycastle.crypto.params.DSAKeyParameters;
36import org.bouncycastle.crypto.params.DSAParameters;
37// END android-added
38import org.bouncycastle.crypto.params.ParametersWithRandom;
39// BEGIN android-removed
40// import org.bouncycastle.crypto.digests.SHA1Digest;
41// import org.bouncycastle.crypto.params.ParametersWithRandom;
42// import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
43// import org.bouncycastle.crypto.util.DigestFactory;
44// END android-removed
45import org.bouncycastle.util.Arrays;
46
47public class DSASigner
48    extends SignatureSpi
49    implements PKCSObjectIdentifiers, X509ObjectIdentifiers
50{
51    private Digest                  digest;
52    private DSA                     signer;
53    private SecureRandom            random;
54
55    protected DSASigner(
56        Digest digest,
57        DSA signer)
58    {
59        this.digest = digest;
60        this.signer = signer;
61    }
62
63    protected void engineInitVerify(
64        PublicKey   publicKey)
65        throws InvalidKeyException
66    {
67        CipherParameters    param = DSAUtil.generatePublicKeyParameter(publicKey);
68
69        digest.reset();
70        signer.init(false, param);
71    }
72
73    protected void engineInitSign(
74        PrivateKey      privateKey,
75        SecureRandom    random)
76        throws InvalidKeyException
77    {
78        this.random = random;
79        engineInitSign(privateKey);
80    }
81
82    protected void engineInitSign(
83        PrivateKey  privateKey)
84        throws InvalidKeyException
85    {
86        CipherParameters    param;
87
88        param = DSAUtil.generatePrivateKeyParameter(privateKey);
89        // BEGIN android-added
90        DSAParameters dsaParam = ((DSAKeyParameters) param).getParameters();
91        checkKey(dsaParam);
92        // END android-added
93
94        if (random != null)
95        {
96            param = new ParametersWithRandom(param, random);
97        }
98
99        digest.reset();
100        signer.init(true, param);
101    }
102
103    protected void engineUpdate(
104        byte    b)
105        throws SignatureException
106    {
107        digest.update(b);
108    }
109
110    protected void engineUpdate(
111        byte[]  b,
112        int     off,
113        int     len)
114        throws SignatureException
115    {
116        digest.update(b, off, len);
117    }
118
119    protected byte[] engineSign()
120        throws SignatureException
121    {
122        byte[]  hash = new byte[digest.getDigestSize()];
123
124        digest.doFinal(hash, 0);
125
126        try
127        {
128            BigInteger[]    sig = signer.generateSignature(hash);
129
130            return derEncode(sig[0], sig[1]);
131        }
132        catch (Exception e)
133        {
134            throw new SignatureException(e.toString());
135        }
136    }
137
138    protected boolean engineVerify(
139        byte[]  sigBytes)
140        throws SignatureException
141    {
142        byte[]  hash = new byte[digest.getDigestSize()];
143
144        digest.doFinal(hash, 0);
145
146        BigInteger[]    sig;
147
148        try
149        {
150            sig = derDecode(sigBytes);
151        }
152        catch (Exception e)
153        {
154            throw new SignatureException("error decoding signature bytes.");
155        }
156
157        return signer.verifySignature(hash, sig[0], sig[1]);
158    }
159
160    protected void engineSetParameter(
161        AlgorithmParameterSpec params)
162    {
163        throw new UnsupportedOperationException("engineSetParameter unsupported");
164    }
165
166    // BEGIN android-added
167    protected void checkKey(DSAParameters params) throws InvalidKeyException {
168        int valueL = params.getP().bitLength();
169        int valueN = params.getQ().bitLength();
170        int digestSize = digest.getDigestSize();
171
172        // The checks are consistent with DSAParametersGenerator's init method.
173        if ((valueL < 1024 || valueL > 3072) || valueL % 1024 != 0) {
174            throw new InvalidKeyException("valueL values must be between 1024 and 3072 and a multiple of 1024");
175        } else if (valueL == 1024 && valueN != 160) {
176            throw new InvalidKeyException("valueN must be 160 for valueL = 1024");
177        } else if (valueL == 2048 && (valueN != 224 && valueN != 256)) {
178            throw new InvalidKeyException("valueN must be 224 or 256 for valueL = 2048");
179        } else if (valueL == 3072 && valueN != 256) {
180            throw new InvalidKeyException("valueN must be 256 for valueL = 3072");
181        }
182        if (!(digest instanceof NullDigest) && valueN > digestSize * 8) {
183            throw new InvalidKeyException("Key is too strong for this signature algorithm");
184        }
185    }
186
187    // END android-added
188    /**
189     * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)">
190     */
191    protected void engineSetParameter(
192        String  param,
193        Object  value)
194    {
195        throw new UnsupportedOperationException("engineSetParameter unsupported");
196    }
197
198    /**
199     * @deprecated
200     */
201    protected Object engineGetParameter(
202        String      param)
203    {
204        throw new UnsupportedOperationException("engineSetParameter unsupported");
205    }
206
207    private byte[] derEncode(
208        BigInteger  r,
209        BigInteger  s)
210        throws IOException
211    {
212        ASN1Integer[] rs = new ASN1Integer[]{ new ASN1Integer(r), new ASN1Integer(s) };
213        return new DERSequence(rs).getEncoded(ASN1Encoding.DER);
214    }
215
216    private BigInteger[] derDecode(
217        byte[]  encoding)
218        throws IOException
219    {
220        ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding);
221        if (s.size() != 2)
222        {
223            throw new IOException("malformed signature");
224        }
225        if (!Arrays.areEqual(encoding, s.getEncoded(ASN1Encoding.DER)))
226        {
227            throw new IOException("malformed signature");
228        }
229
230        return new BigInteger[]{
231            ((ASN1Integer)s.getObjectAt(0)).getValue(),
232            ((ASN1Integer)s.getObjectAt(1)).getValue()
233        };
234    }
235
236    static public class stdDSA
237        extends DSASigner
238    {
239        public stdDSA()
240        {
241            // BEGIN android-changed
242            super(AndroidDigestFactory.getSHA1(), new org.bouncycastle.crypto.signers.DSASigner());
243            // END android-changed
244        }
245    }
246
247    // BEGIN android-removed
248    // static public class detDSA
249    //     extends DSASigner
250    // {
251    //     public detDSA()
252    //     {
253    //         super(DigestFactory.createSHA1(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA1())));
254    //     }
255    // }
256
257    static public class dsa224
258        extends DSASigner
259    {
260        public dsa224()
261        {
262            // BEGIN android-changed
263            super(AndroidDigestFactory.getSHA224(), new org.bouncycastle.crypto.signers.DSASigner());
264            // END android-changed
265        }
266    }
267
268    // BEGIN android-removed
269    // static public class detDSA224
270    //     extends DSASigner
271    // {
272    //     public detDSA224()
273    //     {
274    //         super(DigestFactory.createSHA224(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA224())));
275    //     }
276    // }
277
278    static public class dsa256
279        extends DSASigner
280    {
281        public dsa256()
282        {
283            // BEGIN android-changed
284            super(AndroidDigestFactory.getSHA256(), new org.bouncycastle.crypto.signers.DSASigner());
285            // END android-changed
286        }
287    }
288    // BEGIN android-removed
289    // static public class detDSA256
290    //     extends DSASigner
291    // {
292    //     public detDSA256()
293    //     {
294    //         super(DigestFactory.createSHA256(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA256())));
295    //     }
296    // }
297    //
298    // static public class dsa384
299    //     extends DSASigner
300    // {
301    //     public dsa384()
302    //     {
303    //         super(DigestFactory.createSHA384(), new org.bouncycastle.crypto.signers.DSASigner());
304    //     }
305    // }
306    //
307    // static public class detDSA384
308    //     extends DSASigner
309    // {
310    //     public detDSA384()
311    //     {
312    //         super(DigestFactory.createSHA384(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA384())));
313    //     }
314    // }
315    //
316    // static public class dsa512
317    //     extends DSASigner
318    // {
319    //     public dsa512()
320    //     {
321    //         super(DigestFactory.createSHA512(), new org.bouncycastle.crypto.signers.DSASigner());
322    //     }
323    // }
324    //
325    // static public class detDSA512
326    //     extends DSASigner
327    // {
328    //     public detDSA512()
329    //     {
330    //         super(DigestFactory.createSHA512(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA512())));
331    //     }
332    // }
333    //
334    // static public class dsaSha3_224
335    //     extends DSASigner
336    // {
337    //     public dsaSha3_224()
338    //     {
339    //         super(DigestFactory.createSHA3_224(), new org.bouncycastle.crypto.signers.DSASigner());
340    //     }
341    // }
342    //
343    // static public class detDSASha3_224
344    //     extends DSASigner
345    // {
346    //     public detDSASha3_224()
347    //     {
348    //         super(DigestFactory.createSHA3_224(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_224())));
349    //     }
350    // }
351    //
352    // static public class dsaSha3_256
353    //     extends DSASigner
354    // {
355    //     public dsaSha3_256()
356    //     {
357    //         super(DigestFactory.createSHA3_256(), new org.bouncycastle.crypto.signers.DSASigner());
358    //     }
359    // }
360    //
361    // static public class detDSASha3_256
362    //     extends DSASigner
363    // {
364    //     public detDSASha3_256()
365    //     {
366    //         super(DigestFactory.createSHA3_256(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_256())));
367    //     }
368    // }
369    //
370    // static public class dsaSha3_384
371    //     extends DSASigner
372    // {
373    //     public dsaSha3_384()
374    //     {
375    //         super(DigestFactory.createSHA3_384(), new org.bouncycastle.crypto.signers.DSASigner());
376    //     }
377    // }
378    //
379    // static public class detDSASha3_384
380    //     extends DSASigner
381    // {
382    //     public detDSASha3_384()
383    //     {
384    //         super(DigestFactory.createSHA3_384(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_384())));
385    //     }
386    // }
387    //
388    // static public class dsaSha3_512
389    //     extends DSASigner
390    // {
391    //     public dsaSha3_512()
392    //     {
393    //         super(DigestFactory.createSHA3_512(), new org.bouncycastle.crypto.signers.DSASigner());
394    //     }
395    // }
396    //
397    // static public class detDSASha3_512
398    //     extends DSASigner
399    // {
400    //     public detDSASha3_512()
401    //     {
402    //         super(DigestFactory.createSHA3_512(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_512())));
403    //     }
404    // }
405    // END android-removed
406
407    static public class noneDSA
408        extends DSASigner
409    {
410        public noneDSA()
411        {
412            super(new NullDigest(), new org.bouncycastle.crypto.signers.DSASigner());
413        }
414    }
415}
416