OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / org / apache / harmony / security / provider / crypto / SHA1withDSA_SignatureImpl.java
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17
18 package org.apache.harmony.security.provider.crypto;
19
20 import java.math.BigInteger;
21 import java.security.InvalidKeyException;
22 import java.security.InvalidParameterException;
23 import java.security.MessageDigest;
24 import java.security.NoSuchAlgorithmException;
25 import java.security.PrivateKey;
26 import java.security.PublicKey;
27 import java.security.SecureRandom;
28 import java.security.Signature;
29 import java.security.SignatureException;
30 import java.security.interfaces.DSAKey;
31 import java.security.interfaces.DSAParams;
32 import java.security.interfaces.DSAPrivateKey;
33 import java.security.interfaces.DSAPublicKey;
34
35 public class SHA1withDSA_SignatureImpl extends Signature {
36
37     private MessageDigest msgDigest;
38
39     private DSAKey dsaKey;
40
41     /**
42      * The solo constructor.
43      */
44     public SHA1withDSA_SignatureImpl() throws NoSuchAlgorithmException {
45
46         super("SHA1withDSA");
47
48         msgDigest = MessageDigest.getInstance("SHA1");
49     }
50
51     /**
52      * Deprecated method.
53      *
54      * @return
55      *    null
56      */
57     protected Object engineGetParameter(String param)
58             throws InvalidParameterException {
59         if (param == null) {
60             throw new NullPointerException();
61         }
62         return null;
63     }
64
65     /**
66      * Initializes this signature object with PrivateKey object
67      * passed as argument to the method.
68      *
69      * @params
70      *    privateKey DSAPrivateKey object
71      * @throws
72      *    InvalidKeyException if privateKey is not DSAPrivateKey object
73      */
74     protected void engineInitSign(PrivateKey privateKey)
75             throws InvalidKeyException {
76
77         DSAParams params;
78
79         // parameters and private key
80         BigInteger p, q, x;
81
82         int n;
83
84         if (privateKey == null || !(privateKey instanceof DSAPrivateKey)) {
85             throw new InvalidKeyException();
86         }
87
88         params = ((DSAPrivateKey) privateKey).getParams();
89         p = params.getP();
90         q = params.getQ();
91         x = ((DSAPrivateKey) privateKey).getX();
92
93         // checks described in DSA standard
94         n = p.bitLength();
95         if (p.compareTo(BigInteger.valueOf(1)) != 1 || n < 512 || n > 1024 || (n & 077) != 0) {
96             throw new InvalidKeyException("bad p");
97         }
98         if (q.signum() != 1 && q.bitLength() != 160) {
99             throw new InvalidKeyException("bad q");
100         }
101         if (x.signum() != 1 || x.compareTo(q) != -1) {
102             throw new InvalidKeyException("x <= 0 || x >= q");
103         }
104
105         dsaKey = (DSAKey) privateKey;
106
107         msgDigest.reset();
108     }
109
110     /**
111      * Initializes this signature object with PublicKey object
112      * passed as argument to the method.
113      *
114      * @params
115      *    publicKey DSAPublicKey object
116      * @throws
117      *    InvalidKeyException if publicKey is not DSAPublicKey object
118      */
119     protected void engineInitVerify(PublicKey publicKey)
120             throws InvalidKeyException {
121
122         // parameters and public key
123         BigInteger p, q, y;
124
125         int n1;
126
127         if (publicKey == null || !(publicKey instanceof DSAPublicKey)) {
128             throw new InvalidKeyException("publicKey is not an instance of DSAPublicKey");
129         }
130
131         DSAParams params = ((DSAPublicKey) publicKey).getParams();
132         p = params.getP();
133         q = params.getQ();
134         y = ((DSAPublicKey) publicKey).getY();
135
136         // checks described in DSA standard
137         n1 = p.bitLength();
138         if (p.compareTo(BigInteger.valueOf(1)) != 1 || n1 < 512 || n1 > 1024 || (n1 & 077) != 0) {
139             throw new InvalidKeyException("bad p");
140         }
141         if (q.signum() != 1 || q.bitLength() != 160) {
142             throw new InvalidKeyException("bad q");
143         }
144         if (y.signum() != 1) {
145             throw new InvalidKeyException("y <= 0");
146         }
147
148         dsaKey = (DSAKey) publicKey;
149
150         msgDigest.reset();
151     }
152
153     /*
154      * Deprecated method.
155      *
156      * @throws
157      *    InvalidParameterException
158      */
159     protected void engineSetParameter(String param, Object value) throws InvalidParameterException {
160         if (param == null) {
161             throw new NullPointerException("param == null");
162         }
163         throw new InvalidParameterException("invalid parameter for this engine");
164     }
165
166     /**
167      * Returns signature bytes as byte array containing
168      * ASN1 representation for two BigInteger objects
169      * which is SEQUENCE of two INTEGERS.
170      * Length of sequence varies from less than 46 to 48.
171      *
172      * Resets object to the state it was in
173      * when previous call to either "initSign" method was called.
174      *
175      * @return
176      *    byte array containing signature in ASN1 representation
177      * @throws
178      *    SignatureException if object's state is not SIGN or
179      *                       signature algorithm cannot process data
180      */
181
182     protected byte[] engineSign() throws SignatureException {
183
184         // names of below BigIntegers are the same as they are defined in DSA standard
185         BigInteger r = null;
186         BigInteger s = null;
187         BigInteger k = null;
188
189         // parameters and private key
190         BigInteger p, q, g, x;
191
192         // BigInteger for message digest
193         BigInteger digestBI;
194
195         // various byte array being used in computing signature
196         byte[] randomBytes;
197         byte[] rBytes;
198         byte[] sBytes;
199         byte[] signature;
200
201         int n, n1, n2;
202
203         DSAParams params;
204
205         if (appRandom == null) {
206             appRandom = new SecureRandom();
207         }
208
209         params = dsaKey.getParams();
210         p = params.getP();
211         q = params.getQ();
212         g = params.getG();
213         x = ((DSAPrivateKey) dsaKey).getX();
214
215         // forming signature according algorithm described in chapter 5 of DSA standard
216
217         digestBI = new BigInteger(1, msgDigest.digest());
218
219         randomBytes = new byte[20];
220
221         for (;;) {
222
223             appRandom.nextBytes(randomBytes);
224
225             k = new BigInteger(1, randomBytes);
226             if (k.compareTo(q) != -1) {
227                 continue;
228             }
229             r = g.modPow(k, p).mod(q);
230             if (r.signum() == 0) {
231                 continue;
232             }
233
234             s = k.modInverse(q).multiply(digestBI.add(x.multiply(r)).mod(q))
235                     .mod(q);
236
237             if (s.signum() != 0) {
238                 break;
239             }
240         }
241
242         // forming signature's ASN1 representation which is SEQUENCE of two INTEGERs
243         //
244         rBytes = r.toByteArray();
245         n1 = rBytes.length;
246         if ((rBytes[0] & 0x80) != 0) {
247             n1++;
248         }
249         sBytes = s.toByteArray();
250         n2 = sBytes.length;
251         if ((sBytes[0] & 0x80) != 0) {
252             n2++;
253         }
254
255         signature = new byte[6 + n1 + n2]; // 48 is max. possible length of signature
256         signature[0] = (byte) 0x30; // ASN1 SEQUENCE tag
257         signature[1] = (byte) (4 + n1 + n2); // total length of two INTEGERs
258         signature[2] = (byte) 0x02; // ASN1 INTEGER tag
259         signature[3] = (byte) n1; // length of r
260         signature[4 + n1] = (byte) 0x02; // ASN1 INTEGER tag
261         signature[5 + n1] = (byte) n2; // length of s
262
263         if (n1 == rBytes.length) {
264             n = 4;
265         } else {
266             n = 5;
267         }
268         System.arraycopy(rBytes, 0, signature, n, rBytes.length);
269
270         if (n2 == sBytes.length) {
271             n = 6 + n1;
272         } else {
273             n = 7 + n1;
274         }
275         System.arraycopy(sBytes, 0, signature, n, sBytes.length);
276
277         return signature;
278     }
279
280     /**
281      * Updates data to sign or to verify.
282      *
283      * @params
284      *    b byte to update
285      * @throws
286      *    SignatureException if object was not initialized for signing or verifying
287      */
288     protected void engineUpdate(byte b) throws SignatureException {
289
290         msgDigest.update(b);
291     }
292
293     /**
294      * Updates data to sign or to verify.
295      *
296      * @params
297      *    b byte array containing bytes to update
298      * @params
299      *    off offset in byte array to start from
300      * @params
301      *    len number of bytes to use for updating
302      * @throws
303      *    SignatureException if object was not initialized for signing or verifying
304      */
305     protected void engineUpdate(byte[] b, int off, int len)
306             throws SignatureException {
307
308         msgDigest.update(b, off, len);
309     }
310
311     private boolean checkSignature(byte[] sigBytes, int offset, int length)
312             throws SignatureException {
313
314         // names of below BigIntegers are the same as they are defined in DSA standard
315         BigInteger r, s, w;
316         BigInteger u1, u2, v;
317
318         // parameters and public key
319         BigInteger p, q, g, y;
320
321         DSAParams params;
322
323         int n1, n2;
324
325         byte[] bytes;
326         byte[] digest;
327
328         // checking up on signature's ASN1
329         try {
330             byte dummy;
331             n1 = sigBytes[offset + 3];
332             n2 = sigBytes[offset + n1 + 5];
333
334             if (sigBytes[offset + 0] != 0x30 || sigBytes[offset + 2] != 2
335                     || sigBytes[offset + n1 + 4] != 2
336                     || sigBytes[offset + 1] != (n1 + n2 + 4) || n1 > 21
337                     || n2 > 21
338                     || (length != 0 && (sigBytes[offset + 1] + 2) > length)) {
339                 throw new SignatureException("signature bytes have invalid encoding");
340             }
341
342             dummy = sigBytes[5 + n1 + n2]; // to check length of sigBytes
343         } catch (ArrayIndexOutOfBoundsException e) {
344             throw new SignatureException("bad argument: byte[] is too small");
345         }
346
347         digest = msgDigest.digest();
348
349         bytes = new byte[n1];
350         System.arraycopy(sigBytes, offset + 4, bytes, 0, n1);
351         r = new BigInteger(bytes);
352
353         bytes = new byte[n2];
354         System.arraycopy(sigBytes, offset + 6 + n1, bytes, 0, n2);
355         s = new BigInteger(bytes);
356
357         params = dsaKey.getParams();
358         p = params.getP();
359         q = params.getQ();
360         g = params.getG();
361         y = ((DSAPublicKey) dsaKey).getY();
362
363         // forming signature according algorithm described in chapter 6 of DSA standard
364
365         if (r.signum() != 1 || r.compareTo(q) != -1 || s.signum() != 1
366                 || s.compareTo(q) != -1) {
367             return false;
368         }
369
370         w = s.modInverse(q);
371
372         u1 = (new BigInteger(1, digest)).multiply(w).mod(q);
373         u2 = r.multiply(w).mod(q);
374
375         v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
376
377         if (v.compareTo(r) != 0) {
378             return false;
379         }
380         return true;
381     }
382
383     /**
384      * Verifies the signature bytes.
385      *
386      * @params
387      *    sigBytes byte array with signature bytes to verify.
388      * @return
389      *    true if signature bytes were verified, false otherwise
390      * @throws
391      *    SignatureException if object's state is not VERIFY or
392      *                       signature format is not ASN1 representation or
393      *                       signature algorithm cannot process data
394      */
395     protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
396         if (sigBytes == null) {
397             throw new NullPointerException("sigBytes == null");
398         }
399
400         return checkSignature(sigBytes, 0, 0);
401     }
402
403     /**
404      * Verifies the signature bytes.
405      *
406      * @params
407      *    sigBytes byte array with signature bytes to verify.
408      * @params
409      *    offset index in sigBytes to start from
410      * @params
411      *    length number of bytes allotted for signature
412      * @return
413      *    true if signature bytes were verified, false otherwise
414      * @throws
415      *    SignatureException if object's state is not VERIFY or
416      *                       signature format is not ASN1 representation or
417      *                       signature algorithm cannot process data
418      */
419     protected boolean engineVerify(byte[] sigBytes, int offset, int length)
420             throws SignatureException {
421         return checkSignature(sigBytes, offset, length);
422     }
423 }