|
RIPEMD160WithISO9796Part1AndRSASignatureImpl |
|
1 /* $RCSfile: RIPEMD160WithISO9796Part1AndRSASignatureImpl.java,v $
2 * $Revision: 1.4 $
3 * $Date: 2002/11/23 11:09:56 $
4 * $Author: uwe_guenther $
5 * $State: Exp $
6 *
7 * Created on December 20, 2001 6:36 PM
8 *
9 * Copyright (C) 2001 Uwe Guenther <uwe@cscc.de>
10 *
11 * This file is part of the jhbci JCE-ServiceProvider. The jhbci JCE-
12 * ServiceProvider is a library, written in JavaTM, that should be
13 * used in HBCI banking applications (clients and may be servers),
14 * to do cryptographic operations.
15 *
16 * The jhbci library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License as published by the Free Software Foundation; either
19 * version 2.1 of the License, or (at your option) any later version.
20 *
21 * The jhbci library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
31
32 package de.cscc.crypto.provider;
33
34 import java.security.AlgorithmParameters;
35 import java.security.InvalidAlgorithmParameterException;
36 import java.security.InvalidKeyException;
37 import java.security.PrivateKey;
38 import java.security.PublicKey;
39 import java.security.SecureRandom;
40 import java.security.SignatureException;
41 import java.security.interfaces.RSAKey;
42 import java.security.interfaces.RSAPrivateKey;
43 import java.security.interfaces.RSAPublicKey;
44 import java.security.spec.AlgorithmParameterSpec;
45
46 /**
47 * RIPEMD160WithISO9796Part1AndRSASignatureImpl Class.
48 *
49 * @author <a href=mailto:uwe@cscc.de>Uwe Günther</a>
50 *
51 * @version $Revision: 1.4 $
52 */
53 final class RIPEMD160WithISO9796Part1AndRSASignatureImpl implements Cloneable {
54
55 /** The RIPEMD160 message digest object. */
56 private RIPEMD160MessageDigestImpl md =
57 new RIPEMD160MessageDigestImpl();
58
59 /** The RIPEMD160 ISO9796-1:1991 codec object. */
60 private ISO9796Part1RSACodec codec = new ISO9796Part1RSACodec();
61
62 /**
63 * The length of the signature in bits according to the modulus of the
64 * RSA key.
65 */
66 private int ks;
67
68 /** The object state variable. */
69 private State state = State.UNINITIALIZED;
70
71
72 /** Creates new RIPEMD160WithISO9796Part1AndRSASignatureImpl. */
73 public RIPEMD160WithISO9796Part1AndRSASignatureImpl() {
74 }
75
76 /**
77 * Creates and returns a copy of this object.
78 *
79 * @return a clone of this instance.
80 * @throws CloneNotSupportedException if the object's class does not
81 * support the <code>Cloneable</code> interface. Subclasses
82 * that override the <code>clone</code> method can also
83 * throw this exception to indicate that an instance cannot
84 * be cloned.
85 */
86 public Object clone() throws CloneNotSupportedException {
87 RIPEMD160WithISO9796Part1AndRSASignatureImpl result =
88 (RIPEMD160WithISO9796Part1AndRSASignatureImpl) super.clone();
89 result.md = (RIPEMD160MessageDigestImpl) this.md.clone();
90 result.codec = (ISO9796Part1RSACodec) this.codec.clone();
91 return result;
92 }
93
94 /**
95 * Indicates whether some other object is "equal to" this one.
96 *
97 * @param obj the reference object with which to compare.
98 * @return <code>true</code> if this object is the same as the obj
99 * argument; <code>false</code> otherwise.
100 * @see #hashCode()
101 * @see java.util.Hashtable
102 */
103 public boolean equals(Object obj) {
104 //Only for performance.
105 if (this == obj) {
106 return true;
107 }
108
109 //If obj == null then instanceof returns false, see JLS 15.20.2
110 if (!(obj instanceof RIPEMD160WithISO9796Part1AndRSASignatureImpl)) {
111 return false;
112 }
113
114 RIPEMD160WithISO9796Part1AndRSASignatureImpl other =
115 (RIPEMD160WithISO9796Part1AndRSASignatureImpl)obj;
116
117 return this.md.equals(other.md) &&
118 this.codec.equals(other.codec) &&
119 this.ks == other.ks &&
120 this.state == other.state;
121 }
122
123 /**
124 * Returns a hash code value for the object.
125 *
126 * @return a hash code value for this object.
127 * @see java.lang.Object#equals(java.lang.Object)
128 * @see java.util.Hashtable
129 */
130 public int hashCode() {
131 int result = 17;
132 result = 37*result + this.md.hashCode();
133 result = 37*result + this.codec.hashCode();
134 result = 37*result + this.ks;
135 result = 37*result + this.state.hashCode();
136 return result;
137 }
138
139 /**
140 * Returns a string representation of the object.
141 *
142 * @return a string representation of the object.
143 */
144 public String toString() {
145 return "[RIPEMD160WithISO9796-1AndRSA - state: " + this.state + "]";
146 }
147
148 /**
149 * Initializes this signature object with the specified
150 * private key for signing operations.
151 *
152 * @param privateKey the private key of the identity whose signature
153 * will be generated.
154 *
155 * @throws InvalidKeyException if the key is improperly encoded, parameters
156 * are missing, and so on.
157 */
158 void initSign(PrivateKey privateKey) throws InvalidKeyException {
159 if (privateKey == null) {
160 throw new NullPointerException("Parameter privateKey is null.");
161 }
162 if (privateKey instanceof RSAPrivateKey) {
163 this.ks = ((RSAKey) privateKey).getModulus().bitLength() - 1;
164 } else {
165 throw new InvalidKeyException("Inappropriate Key.");
166 }
167 this.codec.initEncode(privateKey);
168 this.state = State.SIGN;
169 this.md.reset();
170 }
171
172 /**
173 * Initializes this signature object with the specified
174 * private key and source of randomness for signing operations.
175 *
176 * <p>This concrete method has been added to this previously-defined
177 * abstract class. (For backwards compatibility, it cannot be abstract.)
178 *
179 * @param privateKey the private key of the identity whose signature
180 * will be generated.
181 * @param random the source of randomness
182 *
183 * @throws InvalidKeyException if the key is improperly encoded, parameters
184 * are missing, and so on.
185 */
186 void initSign(PrivateKey privateKey, SecureRandom random)
187 throws InvalidKeyException {
188 initSign(privateKey);
189 }
190
191 /**
192 * Initializes this signature object with the specified
193 * public key for verification operations.
194 *
195 * @param publicKey the public key of the identity whose signature is
196 * going to be verified.
197 *
198 * @throws InvalidKeyException if the key is improperly
199 * encoded, parameters are missing, and so on.
200 */
201 void initVerify(PublicKey publicKey) throws InvalidKeyException {
202 if (publicKey == null) {
203 throw new NullPointerException("Parameter publicKey is null.");
204 }
205 if (publicKey instanceof RSAPublicKey) {
206 this.ks = ((RSAKey) publicKey).getModulus().bitLength() - 1;
207 } else {
208 throw new InvalidKeyException("Inappropriate Key.");
209 }
210 this.codec.initDecode(publicKey);
211 this.state = State.VERIFY;
212 this.md.reset();
213 }
214
215 /**
216 * Updates the data to be signed or verified
217 * using the specified byte.
218 *
219 * @param value the byte to use for the update.
220 *
221 * @throws SignatureException if the engine is not initialized
222 * properly.
223 */
224 void update(byte value) throws SignatureException {
225 if (this.state == State.UNINITIALIZED) {
226 throw new SignatureException("Signature is not initialized.");
227 }
228 this.md.update(value);
229 }
230
231 /**
232 * Updates the data to be signed or verified, using the
233 * specified array of bytes, starting at the specified offset.
234 *
235 * @param values the array of bytes
236 * @param offset the offset to start from in the array of bytes
237 * @param len the number of bytes to use, starting at offset
238 *
239 * @throws SignatureException if the engine is not initialized
240 * properly
241 * @throws NullPointerException if outbuf is null.
242 * @throws IllegalArgumentException if offset or len is negative, or the
243 * sum of offset and len is greater than length of the values array.
244 */
245 void update(byte[] values, int offset, int len) throws SignatureException {
246 if (this.state == State.UNINITIALIZED) {
247 throw new SignatureException("Signature is not initialized.");
248 }
249 if (values == null) {
250 throw new NullPointerException("Parameter values is null.");
251 }
252 if (offset < 0) {
253 throw new IllegalArgumentException("Parameter offset is less " +
254 "than zero.");
255 }
256 if (len < 0) {
257 throw new IllegalArgumentException("Parameter len is less " +
258 "than zero.");
259 }
260 if (offset + len > values.length) {
261 throw new IllegalArgumentException("Parameter offset + len is " +
262 "greater than outbuf.length .");
263 }
264 this.md.update(values, offset, len);
265 }
266
267 /**
268 * Returns the signature bytes of all the data
269 * updated so far.
270 * The format of the signature depends on the underlying
271 * signature scheme.
272 *
273 * @return the signature bytes of the signing operation's result.
274 *
275 * @throws SignatureException if the engine is not initialized properly.
276 */
277 byte[] sign() throws SignatureException {
278 if (this.state != State.SIGN) {
279 throw new SignatureException("Signature is not in SIGN state.");
280 }
281
282 try {
283 ISO9796Part1BitString messageDigest =
284 new ISO9796Part1BitString(this.md.digest(), 160);
285
286 ISO9796Part1BitString signature =
287 this.codec.encodeMessage(messageDigest, false);
288
289 /*
290 if (signature.getBitLength() == this.ks) {
291 return signature.getBitString();
292 } else {
293 throw new SignatureException(
294 "Calculated Signature has a wrong length.");
295 }
296 */
297 return signature.getBitString();
298
299 } finally {
300 //If something goes wrong we should reset the md without fail!
301 //Also, if nothing goes wrong we should reset the md too.
302 this.md.reset();
303 }
304 }
305
306 /**
307 * Finishes this signature operation and stores the resulting signature
308 * bytes in the provided buffer <code>outbuf</code>, starting at
309 * <code>offset</code>.
310 * The format of the signature depends on the underlying
311 * signature scheme.
312 *
313 * <p>The signature implementation is reset to its initial state
314 * (the state it was in after a call to one of the
315 * <code>engineInitSign</code> methods)
316 * and can be reused to generate further signatures with the same private
317 * key.
318 *
319 * This method should be abstract, but we leave it concrete for
320 * binary compatibility. Knowledgeable providers should override this
321 * method.
322 *
323 * @param outbuf buffer for the signature result.
324 *
325 * @param offset offset into <code>outbuf</code> where the signature is
326 * stored.
327 *
328 * @param len number of bytes within <code>outbuf</code> allotted for the
329 * signature.
330 * Both this default implementation and the SUN provider do not
331 * return partial digests. If the value of this parameter is less
332 * than the actual signature length, this method will throw a
333 * SignatureException.
334 * This parameter is ignored if its value is greater than or equal to
335 * the actual signature length.
336 *
337 * @return the number of bytes placed into <code>outbuf</code>
338 *
339 * @throws SignatureException if an error occurs or <code>len</code>
340 * is less than the actual signature length.
341 * @throws NullPointerException if outbuf is null.
342 * @throws IllegalArgumentException if offset or len is negative, or the
343 * sum of offset and len is greater than length of the outbuf array.
344 */
345 int sign(byte[] outbuf, int offset, int len) throws SignatureException {
346 if (this.state != State.SIGN) {
347 throw new SignatureException("Signature is not in SIGN state.");
348 }
349 if (outbuf == null) {
350 throw new NullPointerException("Parameter outbuf is null.");
351 }
352 if (offset < 0) {
353 throw new IllegalArgumentException("Parameter offset is less " +
354 "than zero.");
355 }
356 if (len < 0) {
357 throw new IllegalArgumentException("Parameter len is less " +
358 "than zero.");
359 }
360 if (offset + len > outbuf.length) {
361 throw new IllegalArgumentException("Parameter offset + len is " +
362 "greater than outbuf.length .");
363 }
364 if (((ks + 7) / 8) > len) {
365 throw new SignatureException("Existing space in outbuf is less "
366 + "than the signature length would be.");
367 }
368
369 //Calculate the Signature with sign()
370 byte[] result = sign();
371
372 //Copy the Signature into the outbuf starting at offset.
373 System.arraycopy(result, 0, outbuf, offset, result.length);
374
375 //Return the number of bytes placed into outbuf.
376 return result.length;
377 }
378
379 /**
380 * Verifies the passed-in signature.
381 *
382 * @param sigBytes the signature bytes to be verified.
383 *
384 * @return true if the signature was verified, false if not.
385 *
386 * @throws SignatureException if the engine is not initialized
387 * properly, or the passed-in signature is improperly encoded or
388 * of the wrong type, etc.
389 */
390 boolean verify(byte[] sigBytes) throws SignatureException {
391 if (this.state != State.VERIFY) {
392 throw new SignatureException("Signature is not in VERIFY state.");
393 }
394 if (sigBytes == null) {
395 throw new NullPointerException("Parameter signBytes is null.");
396 }
397
398 try {
399 ISO9796Part1BitString sigma =
400 new ISO9796Part1BitString (sigBytes, this.ks);
401
402 ISO9796Part1BitString recoveredMessageDigest =
403 this.codec.decodeSignature(sigma);
404
405 if (recoveredMessageDigest == null) {
406 return false;
407
408 } else { //(message != null)
409 ISO9796Part1BitString messageDigest =
410 new ISO9796Part1BitString(this.md.digest(), 160);
411
412 if (recoveredMessageDigest.equals(messageDigest)) {
413 return true;
414 } else {
415 return false;
416 }
417 }
418 } finally {
419 //If something goes wrong we should reset the md without fail!
420 //Also, if nothing goes wrong we should reset the md too.
421 this.md.reset();
422 }
423 }
424
425 /**
426 * Verifies the passed-in signature in the specified array
427 * of bytes, starting at the specified offset.
428 *
429 * <p> Note: Subclasses should overwrite the default implementation.
430 *
431 *
432 * @param sigBytes the signature bytes to be verified.
433 * @param offset the offset to start from in the array of bytes.
434 * @param leng the number of bytes to use, starting at offset.
435 *
436 * @return true if the signature was verified, false if not.
437 *
438 * @throws SignatureException if the engine is not initialized
439 * properly, or the passed-in signature is improperly encoded or
440 * of the wrong type, etc.
441 */
442 boolean verify(byte[] sigBytes, int offset, int len)
443 throws SignatureException {
444 if (this.state != State.VERIFY) {
445 throw new SignatureException("Signature is not in VERIFY state.");
446 }
447 if (sigBytes == null) {
448 throw new NullPointerException("Parameter signBytes is null.");
449 }
450 if (offset < 0) {
451 throw new IllegalArgumentException("Parameter offset is less " +
452 "than zero.");
453 }
454 if (len < 0) {
455 throw new IllegalArgumentException("Parameter len is less " +
456 "than zero.");
457 }
458 if (offset + len > sigBytes.length) {
459 throw new IllegalArgumentException("Parameter offset + len is " +
460 "greater than outbuf.length .");
461 }
462 if (((ks + 7) / 8) != len) {
463 throw new SignatureException("Signature in sigBytes is not " +
464 ((ks + 7) / 8) + "bytes long.");
465 }
466
467 //Create a temporaly byte array that holds the 'sigBytes'.
468 byte[] tempSigBytes = new byte[len];
469
470 //Copy the 'sigBytes' to 'tempSigBytes'.
471 System.arraycopy(sigBytes, offset, tempSigBytes, 0, len);
472
473 //Invoke the verify(byte[]) method with the 'tempSigBytesArray'.
474 return verify(tempSigBytes);
475 }
476
477 /**
478 * <p>This method is overridden by providers to initialize
479 * this signature engine with the specified parameter set.
480 *
481 * @param params the parameters
482 *
483 * @exception UnsupportedOperationException if this method is not
484 * overridden by a provider
485 *
486 * @throws InvalidAlgorithmParameterException if this method is
487 * overridden by a provider and the the given parameters
488 * are inappropriate for this signature engine
489 */
490 void setParameter(AlgorithmParameterSpec params)
491 throws InvalidAlgorithmParameterException {
492 throw new UnsupportedOperationException("AlgorithmParameters are not " +
493 "supported for this signature.");
494 }
495
496 /**
497 * <p>This method is overridden by providers to return the
498 * parameters used with this signature engine, or null
499 * if this signature engine does not use any parameters.
500 *
501 * <p>The returned parameters may be the same that were used to initialize
502 * this signature engine, or may contain a combination of default and
503 * randomly generated parameter values used by the underlying signature
504 * implementation if this signature engine requires algorithm parameters
505 * but was not initialized with any.
506 *
507 * @return the parameters used with this signature engine, or null if this
508 * signature engine does not use any parameters
509 *
510 * @throws UnsupportedOperationException if this method is
511 * not overridden by a provider
512 */
513 AlgorithmParameters getParameters() {
514 throw new UnsupportedOperationException("AlgorithmParameters are not " +
515 "supported for this signature.");
516 }
517
518 /** Type safe enum for the enclosing class object state. */
519 private final static class State {
520 /** Name odf the state. */
521 private final String name;
522
523 /** Constructor need only to called within this class. */
524 private State(String name) {
525 this.name = name;
526 }
527
528 /**
529 * Returns a string representation of the object.
530 *
531 * @return a string representation of the object.
532 */
533 public String toString() {
534 return this.name;
535 }
536
537 /** State constante if the enclosing class isn't initialized. */
538 private static final State UNINITIALIZED =
539 new State("Uninitialized");
540
541 /** State constante if the enclossing class is in Sign mode. */
542 private static final State SIGN = new State("Sign");
543
544 /** State constante if the enclossing class is in Verify mode. */
545 private static final State VERIFY = new State("Verify");
546 }
547
548 }
549
|
RIPEMD160WithISO9796Part1AndRSASignatureImpl |
|