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