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