1package org.bouncycastle.jcajce.provider.asymmetric.ec;
2
3import java.io.IOException;
4import java.math.BigInteger;
5import java.security.InvalidKeyException;
6import java.security.PrivateKey;
7import java.security.PublicKey;
8
9import org.bouncycastle.asn1.ASN1EncodableVector;
10import org.bouncycastle.asn1.ASN1Encoding;
11import org.bouncycastle.asn1.ASN1Integer;
12import org.bouncycastle.asn1.ASN1Primitive;
13import org.bouncycastle.asn1.ASN1Sequence;
14import org.bouncycastle.asn1.DERSequence;
15import org.bouncycastle.crypto.CipherParameters;
16import org.bouncycastle.crypto.DSA;
17import org.bouncycastle.crypto.Digest;
18import org.bouncycastle.crypto.digests.NullDigest;
19// BEGIN android-added
20import org.bouncycastle.crypto.digests.AndroidDigestFactory;
21// END android-added
22// BEGIN android-removed
23// import org.bouncycastle.crypto.digests.RIPEMD160Digest;
24// import org.bouncycastle.crypto.digests.SHA1Digest;
25// import org.bouncycastle.crypto.digests.SHA224Digest;
26// import org.bouncycastle.crypto.digests.SHA256Digest;
27// import org.bouncycastle.crypto.digests.SHA384Digest;
28// import org.bouncycastle.crypto.digests.SHA512Digest;
29// END android-removed
30import org.bouncycastle.crypto.params.ParametersWithRandom;
31import org.bouncycastle.crypto.signers.ECDSASigner;
32// BEGIN android-removed
33// import org.bouncycastle.crypto.signers.ECNRSigner;
34// import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
35// END android-removed
36import org.bouncycastle.jcajce.provider.asymmetric.util.DSABase;
37import org.bouncycastle.jcajce.provider.asymmetric.util.DSAEncoder;
38import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
39
40public class SignatureSpi
41    extends DSABase
42{
43    SignatureSpi(Digest digest, DSA signer, DSAEncoder encoder)
44    {
45        super(digest, signer, encoder);
46    }
47
48    protected void engineInitVerify(PublicKey publicKey)
49        throws InvalidKeyException
50    {
51        CipherParameters param = ECUtil.generatePublicKeyParameter(publicKey);
52
53        digest.reset();
54        signer.init(false, param);
55    }
56
57    protected void engineInitSign(
58        PrivateKey privateKey)
59        throws InvalidKeyException
60    {
61        CipherParameters param = ECUtil.generatePrivateKeyParameter(privateKey);
62
63        digest.reset();
64
65        if (appRandom != null)
66        {
67            signer.init(true, new ParametersWithRandom(param, appRandom));
68        }
69        else
70        {
71            signer.init(true, param);
72        }
73    }
74
75    static public class ecDSA
76        extends SignatureSpi
77    {
78        public ecDSA()
79        {
80            // BEGIN android-changed
81            super(AndroidDigestFactory.getSHA1(), new ECDSASigner(), new StdDSAEncoder());
82            // END android-changed
83        }
84    }
85
86    // BEGIN android-removed
87    // static public class ecDetDSA
88    //     extends SignatureSpi
89    // {
90    //     public ecDetDSA()
91    //     {
92    //         super(new SHA1Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA1Digest())), new StdDSAEncoder());
93    //     }
94    // }
95    // END android-removed
96
97    static public class ecDSAnone
98        extends SignatureSpi
99    {
100        public ecDSAnone()
101        {
102            super(new NullDigest(), new ECDSASigner(), new StdDSAEncoder());
103        }
104    }
105
106    static public class ecDSA224
107        extends SignatureSpi
108    {
109        public ecDSA224()
110        {
111            // BEGIN android-changed
112            super(AndroidDigestFactory.getSHA224(), new ECDSASigner(), new StdDSAEncoder());
113            // END android-changed
114        }
115    }
116
117    // BEGIN android-removed
118    // static public class ecDetDSA224
119    //     extends SignatureSpi
120    // {
121    //     public ecDetDSA224()
122    //     {
123    //         super(new SHA224Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA224Digest())), new StdDSAEncoder());
124    //     }
125    // }
126    // END android-removed
127
128    static public class ecDSA256
129        extends SignatureSpi
130    {
131        public ecDSA256()
132        {
133            // BEGIN android-changed
134            super(AndroidDigestFactory.getSHA256(), new ECDSASigner(), new StdDSAEncoder());
135            // END android-changed
136        }
137    }
138
139    // BEGIN android-removed
140    // static public class ecDetDSA256
141    //     extends SignatureSpi
142    // {
143    //     public ecDetDSA256()
144    //     {
145    //         super(new SHA256Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())), new StdDSAEncoder());
146    //     }
147    // }
148    // END android-removed
149
150    static public class ecDSA384
151        extends SignatureSpi
152    {
153        public ecDSA384()
154        {
155            // BEGIN android-changed
156            super(AndroidDigestFactory.getSHA384(), new ECDSASigner(), new StdDSAEncoder());
157            // END android-changed
158        }
159    }
160
161    // BEGIN android-removed
162    // static public class ecDetDSA384
163    //     extends SignatureSpi
164    // {
165    //     public ecDetDSA384()
166    //     {
167    //         super(new SHA384Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA384Digest())), new StdDSAEncoder());
168    //     }
169    // }
170    // END android-removed
171
172    static public class ecDSA512
173        extends SignatureSpi
174    {
175        public ecDSA512()
176        {
177            // BEGIN android-changed
178            super(AndroidDigestFactory.getSHA512(), new ECDSASigner(), new StdDSAEncoder());
179            // END android-changed
180        }
181    }
182
183    // BEGIN android-removed
184    // static public class ecDetDSA512
185    //     extends SignatureSpi
186    // {
187    //     public ecDetDSA512()
188    //     {
189    //         super(new SHA512Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA512Digest())), new StdDSAEncoder());
190    //     }
191    // }
192    //
193    // static public class ecDSARipeMD160
194    //     extends SignatureSpi
195    // {
196    //     public ecDSARipeMD160()
197    //     {
198    //         super(new RIPEMD160Digest(), new ECDSASigner(), new StdDSAEncoder());
199    //     }
200    // }
201    //
202    // static public class ecNR
203    //     extends SignatureSpi
204    // {
205    //     public ecNR()
206    //     {
207    //         super(new SHA1Digest(), new ECNRSigner(), new StdDSAEncoder());
208    //     }
209    // }
210    //
211    // static public class ecNR224
212    //     extends SignatureSpi
213    // {
214    //     public ecNR224()
215    //     {
216    //         super(new SHA224Digest(), new ECNRSigner(), new StdDSAEncoder());
217    //     }
218    // }
219    //
220    // static public class ecNR256
221    //     extends SignatureSpi
222    // {
223    //     public ecNR256()
224    //     {
225    //         super(new SHA256Digest(), new ECNRSigner(), new StdDSAEncoder());
226    //     }
227    // }
228    //
229    // static public class ecNR384
230    //     extends SignatureSpi
231    // {
232    //     public ecNR384()
233    //     {
234    //         super(new SHA384Digest(), new ECNRSigner(), new StdDSAEncoder());
235    //     }
236    // }
237    //
238    // static public class ecNR512
239    //     extends SignatureSpi
240    // {
241    //     public ecNR512()
242    //     {
243    //         super(new SHA512Digest(), new ECNRSigner(), new StdDSAEncoder());
244    //     }
245    // }
246    //
247    // static public class ecCVCDSA
248    //     extends SignatureSpi
249    // {
250    //     public ecCVCDSA()
251    //     {
252    //         super(new SHA1Digest(), new ECDSASigner(), new CVCDSAEncoder());
253    //     }
254    // }
255    //
256    // static public class ecCVCDSA224
257    //     extends SignatureSpi
258    // {
259    //     public ecCVCDSA224()
260    //     {
261    //         super(new SHA224Digest(), new ECDSASigner(), new CVCDSAEncoder());
262    //     }
263    // }
264    //
265    // static public class ecCVCDSA256
266    //     extends SignatureSpi
267    // {
268    //     public ecCVCDSA256()
269    //     {
270    //         super(new SHA256Digest(), new ECDSASigner(), new CVCDSAEncoder());
271    //     }
272    // }
273    //
274    // static public class ecCVCDSA384
275    //     extends SignatureSpi
276    // {
277    //     public ecCVCDSA384()
278    //     {
279    //         super(new SHA384Digest(), new ECDSASigner(), new CVCDSAEncoder());
280    //     }
281    // }
282    //
283    // static public class ecCVCDSA512
284    //     extends SignatureSpi
285    // {
286    //     public ecCVCDSA512()
287    //     {
288    //         super(new SHA512Digest(), new ECDSASigner(), new CVCDSAEncoder());
289    //     }
290    // }
291    // END android-removed
292
293    private static class StdDSAEncoder
294        implements DSAEncoder
295    {
296        public byte[] encode(
297            BigInteger r,
298            BigInteger s)
299            throws IOException
300        {
301            ASN1EncodableVector v = new ASN1EncodableVector();
302
303            v.add(new ASN1Integer(r));
304            v.add(new ASN1Integer(s));
305
306            return new DERSequence(v).getEncoded(ASN1Encoding.DER);
307        }
308
309        public BigInteger[] decode(
310            byte[] encoding)
311            throws IOException
312        {
313            ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding);
314            BigInteger[] sig = new BigInteger[2];
315
316            sig[0] = ASN1Integer.getInstance(s.getObjectAt(0)).getValue();
317            sig[1] = ASN1Integer.getInstance(s.getObjectAt(1)).getValue();
318
319            return sig;
320        }
321    }
322
323    private static class CVCDSAEncoder
324        implements DSAEncoder
325    {
326        public byte[] encode(
327            BigInteger r,
328            BigInteger s)
329            throws IOException
330        {
331            byte[] first = makeUnsigned(r);
332            byte[] second = makeUnsigned(s);
333            byte[] res;
334
335            if (first.length > second.length)
336            {
337                res = new byte[first.length * 2];
338            }
339            else
340            {
341                res = new byte[second.length * 2];
342            }
343
344            System.arraycopy(first, 0, res, res.length / 2 - first.length, first.length);
345            System.arraycopy(second, 0, res, res.length - second.length, second.length);
346
347            return res;
348        }
349
350
351        private byte[] makeUnsigned(BigInteger val)
352        {
353            byte[] res = val.toByteArray();
354
355            if (res[0] == 0)
356            {
357                byte[] tmp = new byte[res.length - 1];
358
359                System.arraycopy(res, 1, tmp, 0, tmp.length);
360
361                return tmp;
362            }
363
364            return res;
365        }
366
367        public BigInteger[] decode(
368            byte[] encoding)
369            throws IOException
370        {
371            BigInteger[] sig = new BigInteger[2];
372
373            byte[] first = new byte[encoding.length / 2];
374            byte[] second = new byte[encoding.length / 2];
375
376            System.arraycopy(encoding, 0, first, 0, first.length);
377            System.arraycopy(encoding, first.length, second, 0, second.length);
378
379            sig[0] = new BigInteger(1, first);
380            sig[1] = new BigInteger(1, second);
381
382            return sig;
383        }
384    }
385}
386