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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org.apache.harmony.security.provider.crypto;
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;
35 public class SHA1withDSA_SignatureImpl extends Signature {
37 private MessageDigest msgDigest;
39 private DSAKey dsaKey;
42 * The solo constructor.
44 public SHA1withDSA_SignatureImpl() throws NoSuchAlgorithmException {
48 msgDigest = MessageDigest.getInstance("SHA1");
57 protected Object engineGetParameter(String param)
58 throws InvalidParameterException {
60 throw new NullPointerException();
66 * Initializes this signature object with PrivateKey object
67 * passed as argument to the method.
70 * privateKey DSAPrivateKey object
72 * InvalidKeyException if privateKey is not DSAPrivateKey object
74 protected void engineInitSign(PrivateKey privateKey)
75 throws InvalidKeyException {
79 // parameters and private key
84 if (privateKey == null || !(privateKey instanceof DSAPrivateKey)) {
85 throw new InvalidKeyException();
88 params = ((DSAPrivateKey) privateKey).getParams();
91 x = ((DSAPrivateKey) privateKey).getX();
93 // checks described in DSA standard
95 if (p.compareTo(BigInteger.valueOf(1)) != 1 || n < 512 || n > 1024 || (n & 077) != 0) {
96 throw new InvalidKeyException("bad p");
98 if (q.signum() != 1 && q.bitLength() != 160) {
99 throw new InvalidKeyException("bad q");
101 if (x.signum() != 1 || x.compareTo(q) != -1) {
102 throw new InvalidKeyException("x <= 0 || x >= q");
105 dsaKey = (DSAKey) privateKey;
111 * Initializes this signature object with PublicKey object
112 * passed as argument to the method.
115 * publicKey DSAPublicKey object
117 * InvalidKeyException if publicKey is not DSAPublicKey object
119 protected void engineInitVerify(PublicKey publicKey)
120 throws InvalidKeyException {
122 // parameters and public key
127 if (publicKey == null || !(publicKey instanceof DSAPublicKey)) {
128 throw new InvalidKeyException("publicKey is not an instance of DSAPublicKey");
131 DSAParams params = ((DSAPublicKey) publicKey).getParams();
134 y = ((DSAPublicKey) publicKey).getY();
136 // checks described in DSA standard
138 if (p.compareTo(BigInteger.valueOf(1)) != 1 || n1 < 512 || n1 > 1024 || (n1 & 077) != 0) {
139 throw new InvalidKeyException("bad p");
141 if (q.signum() != 1 || q.bitLength() != 160) {
142 throw new InvalidKeyException("bad q");
144 if (y.signum() != 1) {
145 throw new InvalidKeyException("y <= 0");
148 dsaKey = (DSAKey) publicKey;
157 * InvalidParameterException
159 protected void engineSetParameter(String param, Object value) throws InvalidParameterException {
161 throw new NullPointerException("param == null");
163 throw new InvalidParameterException("invalid parameter for this engine");
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.
172 * Resets object to the state it was in
173 * when previous call to either "initSign" method was called.
176 * byte array containing signature in ASN1 representation
178 * SignatureException if object's state is not SIGN or
179 * signature algorithm cannot process data
182 protected byte[] engineSign() throws SignatureException {
184 // names of below BigIntegers are the same as they are defined in DSA standard
189 // parameters and private key
190 BigInteger p, q, g, x;
192 // BigInteger for message digest
195 // various byte array being used in computing signature
205 if (appRandom == null) {
206 appRandom = new SecureRandom();
209 params = dsaKey.getParams();
213 x = ((DSAPrivateKey) dsaKey).getX();
215 // forming signature according algorithm described in chapter 5 of DSA standard
217 digestBI = new BigInteger(1, msgDigest.digest());
219 randomBytes = new byte[20];
223 appRandom.nextBytes(randomBytes);
225 k = new BigInteger(1, randomBytes);
226 if (k.compareTo(q) != -1) {
229 r = g.modPow(k, p).mod(q);
230 if (r.signum() == 0) {
234 s = k.modInverse(q).multiply(digestBI.add(x.multiply(r)).mod(q))
237 if (s.signum() != 0) {
242 // forming signature's ASN1 representation which is SEQUENCE of two INTEGERs
244 rBytes = r.toByteArray();
246 if ((rBytes[0] & 0x80) != 0) {
249 sBytes = s.toByteArray();
251 if ((sBytes[0] & 0x80) != 0) {
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
263 if (n1 == rBytes.length) {
268 System.arraycopy(rBytes, 0, signature, n, rBytes.length);
270 if (n2 == sBytes.length) {
275 System.arraycopy(sBytes, 0, signature, n, sBytes.length);
281 * Updates data to sign or to verify.
286 * SignatureException if object was not initialized for signing or verifying
288 protected void engineUpdate(byte b) throws SignatureException {
294 * Updates data to sign or to verify.
297 * b byte array containing bytes to update
299 * off offset in byte array to start from
301 * len number of bytes to use for updating
303 * SignatureException if object was not initialized for signing or verifying
305 protected void engineUpdate(byte[] b, int off, int len)
306 throws SignatureException {
308 msgDigest.update(b, off, len);
311 private boolean checkSignature(byte[] sigBytes, int offset, int length)
312 throws SignatureException {
314 // names of below BigIntegers are the same as they are defined in DSA standard
316 BigInteger u1, u2, v;
318 // parameters and public key
319 BigInteger p, q, g, y;
328 // checking up on signature's ASN1
331 n1 = sigBytes[offset + 3];
332 n2 = sigBytes[offset + n1 + 5];
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
338 || (length != 0 && (sigBytes[offset + 1] + 2) > length)) {
339 throw new SignatureException("signature bytes have invalid encoding");
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");
347 digest = msgDigest.digest();
349 bytes = new byte[n1];
350 System.arraycopy(sigBytes, offset + 4, bytes, 0, n1);
351 r = new BigInteger(bytes);
353 bytes = new byte[n2];
354 System.arraycopy(sigBytes, offset + 6 + n1, bytes, 0, n2);
355 s = new BigInteger(bytes);
357 params = dsaKey.getParams();
361 y = ((DSAPublicKey) dsaKey).getY();
363 // forming signature according algorithm described in chapter 6 of DSA standard
365 if (r.signum() != 1 || r.compareTo(q) != -1 || s.signum() != 1
366 || s.compareTo(q) != -1) {
372 u1 = (new BigInteger(1, digest)).multiply(w).mod(q);
373 u2 = r.multiply(w).mod(q);
375 v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
377 if (v.compareTo(r) != 0) {
384 * Verifies the signature bytes.
387 * sigBytes byte array with signature bytes to verify.
389 * true if signature bytes were verified, false otherwise
391 * SignatureException if object's state is not VERIFY or
392 * signature format is not ASN1 representation or
393 * signature algorithm cannot process data
395 protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
396 if (sigBytes == null) {
397 throw new NullPointerException("sigBytes == null");
400 return checkSignature(sigBytes, 0, 0);
404 * Verifies the signature bytes.
407 * sigBytes byte array with signature bytes to verify.
409 * offset index in sigBytes to start from
411 * length number of bytes allotted for signature
413 * true if signature bytes were verified, false otherwise
415 * SignatureException if object's state is not VERIFY or
416 * signature format is not ASN1 representation or
417 * signature algorithm cannot process data
419 protected boolean engineVerify(byte[] sigBytes, int offset, int length)
420 throws SignatureException {
421 return checkSignature(sigBytes, offset, length);