001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.security.provider.crypto;
019:
020: import java.math.BigInteger;
021:
022: import java.security.PrivateKey;
023: import java.security.PublicKey;
024: import java.security.SecureRandom;
025: import java.security.Signature;
026:
027: import java.security.InvalidKeyException;
028: import java.security.InvalidParameterException;
029: import java.security.NoSuchAlgorithmException;
030: import java.security.SignatureException;
031:
032: import java.security.interfaces.DSAParams;
033: import java.security.interfaces.DSAKey;
034: import java.security.interfaces.DSAPrivateKey;
035: import java.security.interfaces.DSAPublicKey;
036:
037: import java.security.MessageDigest;
038:
039: import org.apache.harmony.security.internal.nls.Messages;
040:
041: public class SHA1withDSA_SignatureImpl extends Signature {
042:
043: private MessageDigest msgDigest;
044:
045: private DSAKey dsaKey;
046:
047: /**
048: * The solo constructor.
049: */
050: public SHA1withDSA_SignatureImpl() throws NoSuchAlgorithmException {
051:
052: super ("SHA1withDSA"); //$NON-NLS-1$
053:
054: msgDigest = MessageDigest.getInstance("SHA1"); //$NON-NLS-1$
055: }
056:
057: /**
058: * Deprecated method.
059: *
060: * @return
061: * null
062: */
063: protected Object engineGetParameter(String param)
064: throws InvalidParameterException {
065: if (param == null) {
066: throw new NullPointerException(Messages
067: .getString("security.01")); //$NON-NLS-1$
068: }
069: return null;
070: }
071:
072: /**
073: * Initializes this signature object with PrivateKey object
074: * passed as argument to the method.
075: *
076: * @params
077: * privateKey DSAPrivateKey object
078: * @throws
079: * InvalidKeyException if privateKey is not DSAPrivateKey object
080: */
081: protected void engineInitSign(PrivateKey privateKey)
082: throws InvalidKeyException {
083:
084: DSAParams params;
085:
086: // parameters and private key
087: BigInteger p, q, x;
088:
089: int n;
090:
091: if (privateKey == null
092: || !(privateKey instanceof DSAPrivateKey)) {
093: throw new InvalidKeyException(Messages
094: .getString("security.168")); //$NON-NLS-1$
095: }
096:
097: params = ((DSAPrivateKey) privateKey).getParams();
098: p = params.getP();
099: q = params.getQ();
100: x = ((DSAPrivateKey) privateKey).getX();
101:
102: // checks described in DSA standard
103: n = p.bitLength();
104: if (p.compareTo(BigInteger.valueOf(1)) != 1 || n < 512
105: || n > 1024 || (n & 077) != 0) {
106: throw new InvalidKeyException(Messages
107: .getString("security.169")); //$NON-NLS-1$
108: }
109: if (q.signum() != 1 && q.bitLength() != 160) {
110: throw new InvalidKeyException(Messages
111: .getString("security.16A")); //$NON-NLS-1$
112: }
113: if (x.signum() != 1 || x.compareTo(q) != -1) {
114: throw new InvalidKeyException(Messages
115: .getString("security.16B")); //$NON-NLS-1$
116: }
117:
118: dsaKey = (DSAKey) privateKey;
119:
120: msgDigest.reset();
121: }
122:
123: /**
124: * Initializes this signature object with PublicKey object
125: * passed as argument to the method.
126: *
127: * @params
128: * publicKey DSAPublicKey object
129: * @throws
130: * InvalidKeyException if publicKey is not DSAPublicKey object
131: */
132: protected void engineInitVerify(PublicKey publicKey)
133: throws InvalidKeyException {
134:
135: // parameters and public key
136: BigInteger p, q, y;
137:
138: int n1;
139:
140: if (publicKey == null || !(publicKey instanceof DSAPublicKey)) {
141: throw new InvalidKeyException(Messages
142: .getString("security.16C")); //$NON-NLS-1$
143: }
144:
145: DSAParams params = ((DSAPublicKey) publicKey).getParams();
146: p = params.getP();
147: q = params.getQ();
148: y = ((DSAPublicKey) publicKey).getY();
149:
150: // checks described in DSA standard
151: n1 = p.bitLength();
152: if (p.compareTo(BigInteger.valueOf(1)) != 1 || n1 < 512
153: || n1 > 1024 || (n1 & 077) != 0) {
154: throw new InvalidKeyException(Messages
155: .getString("security.169")); //$NON-NLS-1$
156: }
157: if (q.signum() != 1 || q.bitLength() != 160) {
158: throw new InvalidKeyException(Messages
159: .getString("security.16A")); //$NON-NLS-1$
160: }
161: if (y.signum() != 1) {
162: throw new InvalidKeyException(Messages
163: .getString("security.16D")); //$NON-NLS-1$
164: }
165:
166: dsaKey = (DSAKey) publicKey;
167:
168: msgDigest.reset();
169: }
170:
171: /*
172: * Deprecated method.
173: *
174: * @throws
175: * InvalidParameterException
176: */
177: protected void engineSetParameter(String param, Object value)
178: throws InvalidParameterException {
179: if (param == null) {
180: throw new NullPointerException(Messages.getString(
181: "security.83", "param")); //$NON-NLS-1$ //$NON-NLS-2$
182: }
183: throw new InvalidParameterException(Messages
184: .getString("security.16E")); //$NON-NLS-1$
185: }
186:
187: /**
188: * Returns signature bytes as byte array containing
189: * ASN1 representation for two BigInteger objects
190: * which is SEQUENCE of two INTEGERS.
191: * Length of sequence varies from less than 46 to 48.
192: *
193: * Resets object to the state it was in
194: * when previous call to either "initSign" method was called.
195: *
196: * @return
197: * byte array containing signature in ASN1 representation
198: * @throws
199: * SignatureException if object's state is not SIGN or
200: * signature algorithm cannot process data
201: */
202:
203: protected byte[] engineSign() throws SignatureException {
204:
205: // names of below BigIntegers are the same as they are defined in DSA standard
206: BigInteger r = null;
207: BigInteger s = null;
208: BigInteger k = null;
209:
210: // parameters and private key
211: BigInteger p, q, g, x;
212:
213: // BigInteger for message digest
214: BigInteger digestBI;
215:
216: // various byte array being used in computing signature
217: byte randomBytes[];
218: byte rBytes[], sBytes[], signature[];
219:
220: int n, n1, n2;
221:
222: DSAParams params;
223:
224: if (appRandom == null) {
225: appRandom = new SecureRandom();
226: }
227:
228: params = dsaKey.getParams();
229: p = params.getP();
230: q = params.getQ();
231: g = params.getG();
232: x = ((DSAPrivateKey) dsaKey).getX();
233:
234: // forming signature according algorithm described in chapter 5 of DSA standard
235:
236: digestBI = new BigInteger(1, msgDigest.digest());
237:
238: randomBytes = new byte[20];
239:
240: for (;;) {
241:
242: appRandom.nextBytes(randomBytes);
243:
244: k = new BigInteger(1, randomBytes);
245: if (k.compareTo(q) != -1) {
246: continue;
247: }
248: r = g.modPow(k, p).mod(q);
249: if (r.signum() == 0) {
250: continue;
251: }
252:
253: s = k.modInverse(q).multiply(
254: digestBI.add(x.multiply(r)).mod(q)).mod(q);
255:
256: if (s.signum() != 0) {
257: break;
258: }
259: }
260:
261: // forming signature's ASN1 representation which is SEQUENCE of two INTEGERs
262: //
263: rBytes = r.toByteArray();
264: n1 = rBytes.length;
265: if ((rBytes[0] & 0x80) != 0) {
266: n1++;
267: }
268: sBytes = s.toByteArray();
269: n2 = sBytes.length;
270: if ((sBytes[0] & 0x80) != 0) {
271: n2++;
272: }
273:
274: signature = new byte[6 + n1 + n2]; // 48 is max. possible length of signature
275: signature[0] = (byte) 0x30; // ASN1 SEQUENCE tag
276: signature[1] = (byte) (4 + n1 + n2); // total length of two INTEGERs
277: signature[2] = (byte) 0x02; // ASN1 INTEGER tag
278: signature[3] = (byte) n1; // length of r
279: signature[4 + n1] = (byte) 0x02; // ASN1 INTEGER tag
280: signature[5 + n1] = (byte) n2; // length of s
281:
282: if (n1 == rBytes.length) {
283: n = 4;
284: } else {
285: n = 5;
286: }
287: System.arraycopy(rBytes, 0, signature, n, rBytes.length);
288:
289: if (n2 == sBytes.length) {
290: n = 6 + n1;
291: } else {
292: n = 7 + n1;
293: }
294: System.arraycopy(sBytes, 0, signature, n, sBytes.length);
295:
296: return signature;
297: }
298:
299: /**
300: * Updates data to sign or to verify.
301: *
302: * @params
303: * b byte to update
304: * @throws
305: * SignatureException if object was not initialized for signing or verifying
306: */
307: protected void engineUpdate(byte b) throws SignatureException {
308:
309: msgDigest.update(b);
310: }
311:
312: /**
313: * Updates data to sign or to verify.
314: *
315: * @params
316: * b byte array containing bytes to update
317: * @params
318: * off offset in byte array to start from
319: * @params
320: * len number of bytes to use for updating
321: * @throws
322: * SignatureException if object was not initialized for signing or verifying
323: */
324: protected void engineUpdate(byte[] b, int off, int len)
325: throws SignatureException {
326:
327: msgDigest.update(b, off, len);
328: }
329:
330: private boolean checkSignature(byte[] sigBytes, int offset,
331: int length) throws SignatureException {
332:
333: // names of below BigIntegers are the same as they are defined in DSA standard
334: BigInteger r, s, w;
335: BigInteger u1, u2, v;
336:
337: // parameters and public key
338: BigInteger p, q, g, y;
339:
340: DSAParams params;
341:
342: int n1, n2;
343:
344: byte bytes[];
345: byte digest[];
346:
347: // checking up on signature's ASN1
348: try {
349: byte dummy;
350: n1 = sigBytes[offset + 3];
351: n2 = sigBytes[offset + n1 + 5];
352:
353: if (sigBytes[offset + 0] != 0x30
354: || sigBytes[offset + 2] != 2
355: || sigBytes[offset + n1 + 4] != 2
356: || sigBytes[offset + 1] != (n1 + n2 + 4)
357: || n1 > 21
358: || n2 > 21
359: || (length != 0 && (sigBytes[offset + 1] + 2) > length)) {
360: throw new SignatureException(Messages
361: .getString("security.16F")); //$NON-NLS-1$
362: }
363:
364: dummy = sigBytes[5 + n1 + n2]; // to check length of sigBytes
365: } catch (ArrayIndexOutOfBoundsException e) {
366: throw new SignatureException(Messages
367: .getString("security.170")); //$NON-NLS-1$
368: }
369:
370: digest = msgDigest.digest();
371:
372: bytes = new byte[n1];
373: System.arraycopy(sigBytes, offset + 4, bytes, 0, n1);
374: r = new BigInteger(bytes);
375:
376: bytes = new byte[n2];
377: System.arraycopy(sigBytes, offset + 6 + n1, bytes, 0, n2);
378: s = new BigInteger(bytes);
379:
380: params = dsaKey.getParams();
381: p = params.getP();
382: q = params.getQ();
383: g = params.getG();
384: y = ((DSAPublicKey) dsaKey).getY();
385:
386: // forming signature according algorithm described in chapter 6 of DSA standard
387:
388: if (r.signum() != 1 || r.compareTo(q) != -1 || s.signum() != 1
389: || s.compareTo(q) != -1) {
390: return false;
391: }
392:
393: w = s.modInverse(q);
394:
395: u1 = (new BigInteger(1, digest)).multiply(w).mod(q);
396: u2 = r.multiply(w).mod(q);
397:
398: v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
399:
400: if (v.compareTo(r) != 0) {
401: return false;
402: }
403: return true;
404: }
405:
406: /**
407: * Verifies the signature bytes.
408: *
409: * @params
410: * sigBytes byte array with signature bytes to verify.
411: * @return
412: * true if signature bytes were verified, false otherwise
413: * @throws
414: * SignatureException if object's state is not VERIFY or
415: * signature format is not ASN1 representation or
416: * signature algorithm cannot process data
417: */
418: protected boolean engineVerify(byte[] sigBytes)
419: throws SignatureException {
420:
421: if (sigBytes == null) {
422: throw new NullPointerException(Messages.getString(
423: "security.83", "sigBytes")); //$NON-NLS-1$ //$NON-NLS-2$
424: }
425:
426: return checkSignature(sigBytes, 0, 0);
427: }
428:
429: /**
430: * Verifies the signature bytes.
431: *
432: * @params
433: * sigBytes byte array with signature bytes to verify.
434: * @params
435: * offset index in sigBytes to start from
436: * @params
437: * length number of bytes allotted for signature
438: * @return
439: * true if signature bytes were verified, false otherwise
440: * @throws
441: * SignatureException if object's state is not VERIFY or
442: * signature format is not ASN1 representation or
443: * signature algorithm cannot process data
444: */
445: protected boolean engineVerify(byte[] sigBytes, int offset,
446: int length) throws SignatureException {
447: return checkSignature(sigBytes, offset, length);
448: }
449: }
|