|
ISO9796Part1RSACodec |
|
1 /* $RCSfile: ISO9796Part1RSACodec.java,v $
2 * $Revision: 1.5 $
3 * $Date: 2003/06/22 02:28:39 $
4 * $Author: uwe_guenther $
5 * $State: Exp $
6 *
7 * Created on December 27, 2001 10:50 AM
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.math.BigInteger;
35 import java.security.InvalidKeyException;
36 import java.security.PrivateKey;
37 import java.security.PublicKey;
38 import java.security.interfaces.RSAKey;
39 import java.security.interfaces.RSAPrivateCrtKey;
40 import java.security.interfaces.RSAPrivateKey;
41 import java.security.interfaces.RSAPublicKey;
42 import java.util.Arrays;
43 import java.util.logging.Level;
44 import java.util.logging.Logger;
45
46 import de.cscc.crypto.util.BigIntegerUtil;
47 import de.cscc.crypto.util.ByteUtil;
48
49 /**
50 * ISO9796Part1RSACodec Class.
51 *
52 * @author <a href=mailto:uwe@cscc.de>Uwe Günther</a>
53 *
54 * @version $Revision: 1.5 $
55 */
56 final class ISO9796Part1RSACodec implements Cloneable {
57
58 /*
59 * First we declare all Stuff needed for logging with
60 * java.util.logging.*
61 */
62
63 /** The logger for this class.*/
64 private static final Logger log =
65 Logger.getLogger(ISO9796Part1RSACodec.class.getName());
66
67
68 /**
69 * The Shadow function S according to ISO9796-1:1991.
70 *
71 * <p>The shadow function S that will be used in the encoding and decoding
72 * operations according to ISO9796-1:1991/5.3 and 6.2
73 *
74 * <pre>
75 * Definition of Permutation PI:
76 *
77 * µ 0123456789abcdef
78 * PI(µ) e358942f0db67ac1
79 * </pre>
80 *
81 * If nibble µ consists of the bits a4 a3 a2 a1, then under the
82 * permutation PI, its image denoted by PI(µ) consists of the bits:
83 *
84 * <pre>
85 * a4^a2^a1^1 : a4^a3^a1^1 : a4^a3^a2^1 : a3^a2^a1
86 * </pre>
87 *
88 * If the byte m consists of the nibble µ2 µ1, then under shadow S,
89 * its image denoted by S(m) consists of the nibbles PI(µ2) PI(µ1).
90 */
91 private static final byte[] SHADOW = {
92 (byte) 0xee, (byte) 0xe3, (byte) 0xe5, (byte) 0xe8,
93 (byte) 0xe9, (byte) 0xe4, (byte) 0xe2, (byte) 0xef,
94 (byte) 0xe0, (byte) 0xed, (byte) 0xeb, (byte) 0xe6,
95 (byte) 0xe7, (byte) 0xea, (byte) 0xec, (byte) 0xe1,
96 (byte) 0x3e, (byte) 0x33, (byte) 0x35, (byte) 0x38,
97 (byte) 0x39, (byte) 0x34, (byte) 0x32, (byte) 0x3f,
98 (byte) 0x30, (byte) 0x3d, (byte) 0x3b, (byte) 0x36,
99 (byte) 0x37, (byte) 0x3a, (byte) 0x3c, (byte) 0x31,
100 (byte) 0x5e, (byte) 0x53, (byte) 0x55, (byte) 0x58,
101 (byte) 0x59, (byte) 0x54, (byte) 0x52, (byte) 0x5f,
102 (byte) 0x50, (byte) 0x5d, (byte) 0x5b, (byte) 0x56,
103 (byte) 0x57, (byte) 0x5a, (byte) 0x5c, (byte) 0x51,
104 (byte) 0x8e, (byte) 0x83, (byte) 0x85, (byte) 0x88,
105 (byte) 0x89, (byte) 0x84, (byte) 0x82, (byte) 0x8f,
106 (byte) 0x80, (byte) 0x8d, (byte) 0x8b, (byte) 0x86,
107 (byte) 0x87, (byte) 0x8a, (byte) 0x8c, (byte) 0x81,
108 (byte) 0x9e, (byte) 0x93, (byte) 0x95, (byte) 0x98,
109 (byte) 0x99, (byte) 0x94, (byte) 0x92, (byte) 0x9f,
110 (byte) 0x90, (byte) 0x9d, (byte) 0x9b, (byte) 0x96,
111 (byte) 0x97, (byte) 0x9a, (byte) 0x9c, (byte) 0x91,
112 (byte) 0x4e, (byte) 0x43, (byte) 0x45, (byte) 0x48,
113 (byte) 0x49, (byte) 0x44, (byte) 0x42, (byte) 0x4f,
114 (byte) 0x40, (byte) 0x4d, (byte) 0x4b, (byte) 0x46,
115 (byte) 0x47, (byte) 0x4a, (byte) 0x4c, (byte) 0x41,
116 (byte) 0x2e, (byte) 0x23, (byte) 0x25, (byte) 0x28,
117 (byte) 0x29, (byte) 0x24, (byte) 0x22, (byte) 0x2f,
118 (byte) 0x20, (byte) 0x2d, (byte) 0x2b, (byte) 0x26,
119 (byte) 0x27, (byte) 0x2a, (byte) 0x2c, (byte) 0x21,
120 (byte) 0xfe, (byte) 0xf3, (byte) 0xf5, (byte) 0xf8,
121 (byte) 0xf9, (byte) 0xf4, (byte) 0xf2, (byte) 0xff,
122 (byte) 0xf0, (byte) 0xfd, (byte) 0xfb, (byte) 0xf6,
123 (byte) 0xf7, (byte) 0xfa, (byte) 0xfc, (byte) 0xf1,
124 (byte) 0x0e, (byte) 0x03, (byte) 0x05, (byte) 0x08,
125 (byte) 0x09, (byte) 0x04, (byte) 0x02, (byte) 0x0f,
126 (byte) 0x00, (byte) 0x0d, (byte) 0x0b, (byte) 0x06,
127 (byte) 0x07, (byte) 0x0a, (byte) 0x0c, (byte) 0x01,
128 (byte) 0xde, (byte) 0xd3, (byte) 0xd5, (byte) 0xd8,
129 (byte) 0xd9, (byte) 0xd4, (byte) 0xd2, (byte) 0xdf,
130 (byte) 0xd0, (byte) 0xdd, (byte) 0xdb, (byte) 0xd6,
131 (byte) 0xd7, (byte) 0xda, (byte) 0xdc, (byte) 0xd1,
132 (byte) 0xbe, (byte) 0xb3, (byte) 0xb5, (byte) 0xb8,
133 (byte) 0xb9, (byte) 0xb4, (byte) 0xb2, (byte) 0xbf,
134 (byte) 0xb0, (byte) 0xbd, (byte) 0xbb, (byte) 0xb6,
135 (byte) 0xb7, (byte) 0xba, (byte) 0xbc, (byte) 0xb1,
136 (byte) 0x6e, (byte) 0x63, (byte) 0x65, (byte) 0x68,
137 (byte) 0x69, (byte) 0x64, (byte) 0x62, (byte) 0x6f,
138 (byte) 0x60, (byte) 0x6d, (byte) 0x6b, (byte) 0x66,
139 (byte) 0x67, (byte) 0x6a, (byte) 0x6c, (byte) 0x61,
140 (byte) 0x7e, (byte) 0x73, (byte) 0x75, (byte) 0x78,
141 (byte) 0x79, (byte) 0x74, (byte) 0x72, (byte) 0x7f,
142 (byte) 0x70, (byte) 0x7d, (byte) 0x7b, (byte) 0x76,
143 (byte) 0x77, (byte) 0x7a, (byte) 0x7c, (byte) 0x71,
144 (byte) 0xae, (byte) 0xa3, (byte) 0xa5, (byte) 0xa8,
145 (byte) 0xa9, (byte) 0xa4, (byte) 0xa2, (byte) 0xaf,
146 (byte) 0xa0, (byte) 0xad, (byte) 0xab, (byte) 0xa6,
147 (byte) 0xa7, (byte) 0xaa, (byte) 0xac, (byte) 0xa1,
148 (byte) 0xce, (byte) 0xc3, (byte) 0xc5, (byte) 0xc8,
149 (byte) 0xc9, (byte) 0xc4, (byte) 0xc2, (byte) 0xcf,
150 (byte) 0xc0, (byte) 0xcd, (byte) 0xcb, (byte) 0xc6,
151 (byte) 0xc7, (byte) 0xca, (byte) 0xcc, (byte) 0xc1,
152 (byte) 0x1e, (byte) 0x13, (byte) 0x15, (byte) 0x18,
153 (byte) 0x19, (byte) 0x14, (byte) 0x12, (byte) 0x1f,
154 (byte) 0x10, (byte) 0x1d, (byte) 0x1b, (byte) 0x16,
155 (byte) 0x17, (byte) 0x1a, (byte) 0x1c, (byte) 0x11
156 };
157
158 /**
159 * The inverse PI function according to ISO9796-1:1991.
160 * See also the Shadow function S.
161 */
162 private static final byte[] PI_INV = {
163 (byte)0x08, (byte)0x0f, (byte)0x06, (byte)0x01,
164 (byte)0x05, (byte)0x02, (byte)0x0b, (byte)0x0c,
165 (byte)0x03, (byte)0x04, (byte)0x0d, (byte)0x0a,
166 (byte)0x0e, (byte)0x09, (byte)0x00, (byte)0x07
167 };
168
169 /** Frequently used BigIntegers */
170 private static final BigInteger ZERO = BigInteger.ZERO;
171 private static final BigInteger ONE = BigInteger.ONE;
172 private static final BigInteger TWO = BigInteger.valueOf(2L);
173 private static final BigInteger THREE = BigInteger.valueOf(3L);
174 private static final BigInteger FOUR = BigInteger.valueOf(4L);
175 private static final BigInteger FIVE = BigInteger.valueOf(5L);
176 private static final BigInteger SIX = BigInteger.valueOf(6L);
177 private static final BigInteger SEVEN = BigInteger.valueOf(7L);
178 private static final BigInteger EIGHT = BigInteger.valueOf(8L);
179 private static final BigInteger SIXTEEN = BigInteger.valueOf(16L);
180
181
182 /** The object state variable. */
183 private State state = State.UNINITIALIZED;
184
185 /**
186 * Holds the either the key for encoding or for decoding.
187 *
188 * <p> This can be an RSAPublicKeyImpl, RSAPrivateKeyImpl or an
189 * RSAPrivateCrtKeyImpl from this provider.
190 */
191 private RSAKey key;
192
193 /** Creates new ISO9796Part1RSACodec. */
194 ISO9796Part1RSACodec() {
195 }
196
197 /**
198 * Creates and returns a copy of this object.
199 *
200 * @return a clone of this instance.
201 * @throws CloneNotSupportedException if the object's class does not
202 * support the <code>Cloneable</code> interface. Subclasses
203 * that override the <code>clone</code> method can also
204 * throw this exception to indicate that an instance cannot
205 * be cloned.
206 */
207 public Object clone() throws CloneNotSupportedException {
208 //We copy only the object references, so we do a flat copy.
209 //This is ok, because the key is a immutable object and state
210 //is a typesafe enum.
211 return super.clone();
212 }
213
214 /**
215 * Indicates whether some other object is "equal to" this one.
216 *
217 * @param obj the reference object with which to compare.
218 * @return <code>true</code> if this object is the same as the obj
219 * argument; <code>false</code> otherwise.
220 * @see #hashCode()
221 * @see java.util.Hashtable
222 */
223 public boolean equals(Object obj) {
224 //Only for performance.
225 if (this == obj) {
226 return true;
227 }
228
229 //If obj == null then instanceof returns false, see JLS 15.20.2
230 if (!(obj instanceof ISO9796Part1RSACodec)) {
231 return false;
232 }
233
234 ISO9796Part1RSACodec other = (ISO9796Part1RSACodec)obj;
235
236 if (this.state == State.UNINITIALIZED) {
237 //Check if the other key is also null.
238 return this.key == other.key &&
239 this.state == other.state;
240 } else { //(this.state != State.UNINITIALIZED)
241 return this.key.equals(other.key) &&
242 this.state == other.state;
243 }
244 }
245
246 /**
247 * Returns a hash code value for the object.
248 *
249 * @return a hash code value for this object.
250 * @see java.lang.Object#equals(java.lang.Object)
251 * @see java.util.Hashtable
252 */
253 public int hashCode() {
254 //If key is null we can't invoke hashCode().
255 if (this.state == State.UNINITIALIZED) {
256 int result = 17;
257 result = 37*result + this.state.hashCode();
258 return result;
259 //So key isn't null and we can invoke hashCode().
260 } else {
261 int result = 17;
262 result = 37*result + this.key.hashCode();
263 result = 37*result + this.state.hashCode();
264 return result;
265 }
266 }
267
268 /**
269 * Returns a string representation of the object.
270 *
271 * @return a string representation of the object.
272 */
273 public String toString() {
274 return "[ISO9796Part1RSACodec - state: " + this.state + "]";
275 }
276
277 /**
278 * Initializes this codec object with the specified public key
279 * for encoding operations. We accept only RSAPublicKey or
280 * RSAPrivateCrtKey from this provider.
281 *
282 * @param privateKey the private key that will be used for
283 * encoding operations.
284 * @throws NullPointerException if privateKey is null.
285 * @throws InvalidKeyException if privateKey is not a RSAPrivateKey or a
286 * RSAPrivateCrtKey from this provider.
287 */
288 void initEncode(PrivateKey privateKey) throws InvalidKeyException {
289 if (privateKey == null) {
290 throw new NullPointerException("Parameter privateKey is null.");
291 }
292 if (privateKey instanceof RSAPrivateCrtKeyImpl) {
293 this.key = (RSAKey) privateKey;
294 } else if (privateKey instanceof RSAPrivateKeyImpl) {
295 this.key = (RSAKey) privateKey;
296 } else {
297 throw new InvalidKeyException("Inapproiate Key.");
298 }
299 this.state = State.ENCODE;
300 }
301
302 /**
303 * Initializes this codec object with the specified private key
304 * for decoding operatins. We accept only RSAPublicKey from this provider.
305 *
306 * @param publicKey the public key that will be used for
307 * decoding operations.
308 * @throws NullPointerException if publicKey is null.
309 * @throws InvalidKeyException if publicKey is not a RSAPublicKey from
310 * this provider.
311 */
312 void initDecode(PublicKey publicKey) throws InvalidKeyException {
313 if (publicKey == null) {
314 throw new NullPointerException("Parameter publicKey is null.");
315 }
316 if (publicKey instanceof RSAPublicKeyImpl) {
317 this.key = (RSAKey) publicKey;
318 } else {
319 throw new InvalidKeyException("Inapproiate Key.");
320 }
321 this.state = State.DECODE;
322 }
323
324 /**
325 * ISO9796-1 Message Encoding with RSA-Encryption.
326 *
327 * <p>This implementation is fully ISO9796-1 compatible.
328 *
329 * @param bitStringMessage the bit string that should be formated according
330 * to ISO9796-1 with usage of RSA for the sigma function.
331 * @param publicExponentEven should be true if the 'publicExponent' of the
332 * RSAPublicKey is a even number or false if the 'publicExponent' of the
333 * RSAPublicKey is odd.
334 * @return the with RSA signed ISO9796-1 formated representation of
335 * the message.
336 * @throws NullPointerException if bitStringMessage is null.
337 * @throws IllegalArgumentException if the 'messageBitLength' isn't be at
338 * most 8 times the largest integer less than or equal to (ks+3)/16.
339 * This means 'z' should less than or equal to (ks+3)/16. Where 'ks' is the
340 * modulus bit length aubtract by one.
341 * @throws IllegalStateException if this Codec object isn't initialized
342 * for encoding.
343 */
344 ISO9796Part1BitString encodeMessage(
345 ISO9796Part1BitString bitStringMessage, boolean publicExponentEven) {
346 //Debug method entry.
347 if (log.isLoggable(Level.FINER)) {
348 log.finer("Entering encodeMessage(<bitStringMessage="+
349 bitStringMessage+"> ,publicExponentEven=<"+publicExponentEven+">).");
350 }
351
352 //Debug Member usage.
353 if (log.isLoggable(Level.FINEST)) {
354 log.finest("Will use member <key=" + this.key + ">.");
355 log.finest("We are in <state=" + this.state + ">.");
356 }
357
358
359
360 //////
361 //
362 // Pre-Conditions check
363 //
364 //////
365
366 if (this.state != State.ENCODE) {
367 IllegalStateException e = new IllegalStateException(
368 "The ISO9796Part1RSACodec is not in the ENCODE state.");
369
370 if (log.isLoggable(Level.FINER)) {
371 log.finer("Throwing IllegalSateException, because (<state="+
372 this.state+"> != State.ENCODE). Exception: " + e);
373 }
374
375 throw e;
376 }
377 if (bitStringMessage == null) {
378 NullPointerException e = new NullPointerException(
379 "Parameter bitStringMessage is null.");
380
381 if (log.isLoggable(Level.FINER)) {
382 log.finer("Throwing NullPointerExeption, because " +
383 "(<bitStringMessage="+bitStringMessage+"> == null). " +
384 "Exception: " + e);
385 }
386
387 throw e;
388 }
389
390
391
392 //////
393 //
394 // Message Padding
395 //
396 //////
397
398 //'ks' is the length of the signatur bit string in bits. 'ks' is
399 //defined in ISO9796-1:1991/3 as the length of the modulus in bit ('k')
400 //minus one (ks = k - 1).
401 final int ks = this.key.getModulus().bitLength() - 1;
402
403 if (log.isLoggable(Level.FINEST)) {
404 log.finest("Have calculated <ks="+ks+
405 "> = <key.getModulus().bitLength()="+
406 this.key.getModulus().bitLength()+"> - 1." );
407 }
408
409 //'messageBitLength' is the length in bits of the message that should be
410 //encoded according to ISO9796-1WithRSA.
411 final int messageBitLength = bitStringMessage.getBitLength();
412
413 if (log.isLoggable(Level.FINEST)) {
414 log.finest("Have set <messageBitLength="+messageBitLength+
415 "> = <bitStringMessage.getBitLength()="+
416 bitStringMessage.getBitLength()+">.");
417 }
418
419 //'z' is the number of bytes in the padded message, denoted as 'mp'. If
420 //the 'messageBitLength' is not a multiple of 8 the 'message' will be
421 //padded with 0 to 7 zero bits in the padded messsage 'mp'.
422 final int z = (messageBitLength + 7) / 8;
423
424 if (log.isLoggable(Level.FINEST)) {
425 log.finest("Have calculated <z=" + z + "> = (<messageBitLength="+
426 messageBitLength+"> + 7) / 8.");
427 }
428
429 //Check if the 'messageBitLength' is be at most 8 times the largest
430 //integer less than or equal to (ks+3)/16. This means 'z' should less
431 //than or equal to (ks+3)/16. See (ISO9796-1:1991/5.1) for more details.
432 if ((z * 16) > (ks + 3)) {
433 IllegalArgumentException e = new IllegalArgumentException(
434 "Parameter bitStringMessage is to large for the modulus bit " +
435 "length of the given private key.");
436
437 if (log.isLoggable(Level.FINER)) {
438 log.finer("Throwing IllegalArgumentException, because " +
439 "((<z="+z+"> * 16) > (<ks="+ks+"> + 3)) ." +
440 "Exception: " + e);
441 }
442
443 throw e;
444 }
445
446 //Create the new byte array 'mp' with a length of 'z' bytes.
447 final byte[] mp = new byte[z];
448
449 if (log.isLoggable(Level.FINEST)) {
450 log.finest("Have created <mp"+ByteUtil.toHex(mp)+
451 "> = new byte[<z="+z+">]");
452 }
453
454 //The 'message' that should be encoded according to ISO9796-1WithRSA.
455 final byte[] message = bitStringMessage.getBitString();
456
457 if (log.isLoggable(Level.FINEST)) {
458 log.finest("Have set <message=" + ByteUtil.toHex(message) +
459 "> = <bitStringMessage.getBitString()=" +
460 ByteUtil.toHex(bitStringMessage.getBitString()) + ">.");
461 }
462
463 //Copy the 'message' into 'mp' where all bytes are right-justified.
464 System.arraycopy(message, message.length - mp.length, mp, 0, mp.length);
465
466 if (log.isLoggable(Level.FINEST)) {
467 log.finest("Have copied <message=" + ByteUtil.toHex(message) +
468 "> into <mp=" + ByteUtil.toHex(mp) + "> aligned to the right.");
469 }
470
471 //'r' is the number of padded zeros plus one.
472 //'r' is thus valued from 1 to 8.
473 final int r = (8 - messageBitLength % 8) % 8 + 1;
474
475 if (log.isLoggable(Level.FINEST)) {
476 log.finest("Have calculated <r="+r+
477 "> = (8 - <messageBitLength="+messageBitLength+"> % 8) % 8 + 1.");
478 }
479
480 //Pad 'mp' on the left side (set the unused 'r-1 bits' to zero).
481 //mp[0] &= 0xff >>> ((8 - (messageBitLength % 8)) % 8);
482 mp[0] &= 0xff >>> (r - 1);
483
484 if (log.isLoggable(Level.FINEST)) {
485 log.finest("Have padded mp on the left side: <mp="+
486 ByteUtil.toHex(mp)+"> &= 0xff >>> (<r="+r+"> - 1).");
487 }
488
489 //Debug 'mp'.
490 if (log.isLoggable(Level.FINER)) {
491 log.finer("Final result of <mp=" + ByteUtil.toHex(mp) + ">.");
492 }
493
494
495
496 //////
497 //
498 // Extend Message and add Redundancy.
499 //
500 //////
501
502 //The extended message with redundancy have to create in to steps:
503 //1. Create the extended message 'me' by repeating the 'z' bytes of 'mp',
504 // as many times as necessary, in order and concatenated to the left,
505 // until forming a string of t bytes.
506 //2. Create the extende message with redundancy 'mr' by interleaving the
507 // 't' bytes of 'me' in odd positions and 't' bytes of redundancy in
508 // even positions. Altered by index 'r', the least significant
509 // nibble of the '2z-th byte' of 'mr' codes the message length by
510 // its value in its position.
511 //For performance and memory reasons we haven't an extra 'me'. So we
512 //create 'mp' with all 'me'-like operations defined in ISO9796-1:1991.
513
514 //'t' is the least integer, such that a string of '2t bytes' includes at
515 //least 'ks-1 bits'.
516 final int t = (ks + 14) / 16 ;
517
518 if (log.isLoggable(Level.FINEST)) {
519 log.finest("Have calculated <t="+t+"> = (<ks="+ks+"> + 14) / 16.");
520 }
521
522 //Create mp with a length of '2t bytes'
523 final byte[] mr = new byte[2 * t];
524
525 if (log.isLoggable(Level.FINEST)) {
526 log.finest("Have created <mr"+ByteUtil.toHex(mr)+
527 "> = new byte[2 * <t="+t+">]");
528 }
529
530 //Extend and interleave the padded message mp.
531 for(int i = 1; i <= t ; i++) {
532 //odd position in 'mr' -> (2i-1) -> 't' byte of 'me'
533 mr[2*t - (2*i-1)] = mp[z-(((i-1) % z) + 1)];
534 //even -> (2i) -> 't' byte of redundancy with the help of SHADOW.
535 mr[2*t - (2*i)] = SHADOW[mp[z-(((i-1) % z) + 1)] & 0xff];
536 }
537
538 if (log.isLoggable(Level.FINEST)) {
539 log.finest("Have extended and interleaved <mr"+ByteUtil.toHex(mr)+
540 ">.");
541 }
542
543 //The '2z-th byte' of 'mr' equals the exclusive-or of index 'r' with the
544 //shadow of the 'z-th byte' of 'me'.
545 mr[2*t - (2*z)] ^= (byte) r;
546
547 if (log.isLoggable(Level.FINEST)) {
548 log.finest("Have xored r to the 2*z-th byte of mr: "+
549 "<mr[<2*<t="+t+"> - (2*<z="+z+">)="+(2*t - (2*z))+">]="+
550 ByteUtil.toHex(mr[2*t - (2*z)])+"> ^= (byte) <r="+r+">.");
551 }
552
553 //Debug mr.
554 if (log.isLoggable(Level.FINER)) {
555 log.finer("Final result of <mr=" + ByteUtil.toHex(mr) + ">.");
556 }
557
558
559 //////
560 //
561 // Truncation and forcing.
562 //
563 //////
564
565 //'ir' is a bit string of ks bits, this means that if you want to place
566 //the bit string 'ir' in a byte array, the byte array have to at least a
567 //length of ((ks + 7) / 8) bytes.
568 final byte[] ir = new byte [(ks + 7) / 8];
569
570 if (log.isLoggable(Level.FINEST)) {
571 log.finest("Have created <ir"+ByteUtil.toHex(ir)+
572 "> = new byte[(<ks="+ks+"> + 7) / 8].");
573 }
574
575 //Copy 'mr' into 'ir'.
576 //We have to distinguish between two cases:
577 //1. The number of bytes in ir is greater than or equal to the
578 // number of bytes in mr.
579 //2. The number of bytes in ir is less than the number of bytes in mr.
580 //This differentiation is necessary, because the number of bytes in mr
581 //is a multiple of 16 and the number of bytes in ir is multiple of 8.
582 if (ir.length >= mr.length) {
583 System.arraycopy(mr, 0, ir, ir.length - mr.length, mr.length);
584 } else { //(ir.length < mr.length)
585 System.arraycopy(mr, mr.length - ir.length, ir, 0, ir.length);
586 }
587
588 if (log.isLoggable(Level.FINEST)) {
589 log.finest("Have copied <mr=" + ByteUtil.toHex(mr) +
590 "> into <ir=" + ByteUtil.toHex(ir) + "> aligned to the right.");
591 }
592
593 //Truncation of 'ir'
594 //1. set most significant bit (MSB) ks to 1
595 ir[0] |= 0x01 << ((ks + 7) % 8);
596
597 if (log.isLoggable(Level.FINEST)) {
598 log.finest("Have set the most significant bit (MSB) <ks="+ks+
599 "> to 1: <ir[0]="+ByteUtil.toHex(ir[0])+"> |= 0x01 << ((<ks="+ks+
600 "> + 7) % 8).");
601 }
602
603 //Truncation of 'ir'
604 //2. add padding zero bit(s). These are this bits that are more
605 //significant than the ks-th bit.
606 ir[0] &= 0xff >>> ir.length * 8 - ks;
607
608 if (log.isLoggable(Level.FINEST)) {
609 log.finest("Have padded the bits that are more significant than " +
610 "the <ks="+ks+">-th bit to zero: <ir[0]="+ByteUtil.toHex(ir[0])+
611 "> &= 0xff >>> <ir.length="+ir.length+"> * 8 - <ks="+ks+">.");
612 }
613
614 //Forcing of 'ir'
615 //Means that the least significant byte in import is replaced
616 //by the following procedure:
617 //If (µ2||µ1) is the least significant byte of 'mr', then the least
618 //significant byte of 'ir' shall be (µ1||6).
619 ir[ir.length - 1] = (byte) ((mr[mr.length - 1] << 4) | 0x06);
620
621 if (log.isLoggable(Level.FINEST)) {
622 log.finest("Have forced the least significant byte of ir: " +
623 "<ir[<ir.length="+ir.length+"> - 1]="+ByteUtil.toHex(ir[ir.length - 1])+
624 "> = (byte) ((<mr[<mr.length="+mr.length+"> - 1]="+
625 ByteUtil.toHex(mr[mr.length - 1])+"> << 4) | 0x06).");
626 }
627
628 //Debug 'ir'.
629 if (log.isLoggable(Level.FINER)) {
630 log.finer("Final result of <ir=" + ByteUtil.toHex(ir) + ">.");
631 }
632
633
634
635 //////
636 //
637 // Produce the Signature
638 //
639 //////
640
641 //Get 'modulus'
642 final BigInteger modulus = this.key.getModulus();
643
644 if (log.isLoggable(Level.FINEST)) {
645 log.finest("Have set <modulus="+modulus+
646 "> = <key.getModulus()="+this.key.getModulus()+">.");
647 }
648
649 //Convert 'ir' to the BigInteger representation of 'ir' -
650 //denoted as the represantive element 'irAsNumber'.
651 final BigInteger irAsNumber = new BigInteger(1, ir);
652
653 if (log.isLoggable(Level.FINEST)) {
654 log.finest("Have converted ir to irAsNumber: <irAsNumber="+
655 irAsNumber+"> = <new BigInteger(1, <ir="+ByteUtil.toHex(ir)+">).");
656 }
657
658 //The representative Element of 'ir' with respect to modulus
659 //is denoted by 'rr'.
660 BigInteger rr;
661
662 //public exponent is even
663 if (publicExponentEven) {
664 //Calculate the jacobi symbol of (ir|modulus)
665 int jacobiSymbol = jacobi(irAsNumber, modulus);
666
667 if (log.isLoggable(Level.FINEST)) {
668 log.finest("Modulus is even.");
669 log.finest("Have set <jacobiSymbol="+jacobiSymbol+">");
670 }
671
672 //jacobiSymbol of (irAsNumber|modulus) = 1
673 if( jacobiSymbol == 1) {
674 //Set the representative element 'rr' = 'ir'.
675 rr = irAsNumber;
676
677 if (log.isLoggable(Level.FINEST)) {
678 log.finest("Have set <rr="+rr+"> = <irAsNumber="+
679 irAsNumber+">.");
680 }
681
682 //jacobySymbol of (irAsNumber|modulus) = -1
683 } else if (jacobiSymbol == -1) {
684 //Set the representative element 'rr' = 'ir' / 2.
685 rr = irAsNumber.divide(TWO);
686
687 if (log.isLoggable(Level.FINEST)) {
688 log.finest("Have set <rr="+rr+"> = <irAsNumber="+
689 irAsNumber+"> / 2.");
690 }
691
692 //Should not happen.
693 } else {
694 IllegalStateException e = new IllegalStateException(
695 "The jacobi symbol (ir|modulus) isn't equal to 1 or to -1.");
696
697 if (log.isLoggable(Level.FINER)) {
698 log.finer("Throwing IllegalSateException, because " +
699 "<jacobySymbol="+jacobiSymbol+
700 "> isn't equal to 1 or to -1. Exception: " + e);
701 }
702
703 throw e;
704 }
705
706 // public exponent is odd
707 } else {
708 //Convert 'ir' to the BigInteger representation of 'rr'.
709 rr = irAsNumber;
710
711 if (log.isLoggable(Level.FINEST)) {
712 log.finest("Modulus is odd.");
713 log.finest("Have set <rr="+rr+"> = <irAsNumber="+
714 irAsNumber+">.");
715 }
716 }
717
718 //Debug 'rr'.
719 if (log.isLoggable(Level.FINER)) {
720 log.finer("Final result of <rr=" +
721 ByteUtil.toHex(BigIntegerUtil.toUnsignedByteArray(rr)) + ">.");
722 }
723
724 //Chinese remainder theorem RSA decryption according to RSA PKCS1.
725 //Here it will be used to _encrypt_ the representative element 'rr' with
726 //help of the signers private key.
727 BigInteger cipherText;
728 if (this.key instanceof RSAPrivateCrtKey) {
729 final BigInteger primeP =
730 ((RSAPrivateCrtKey) this.key).getPrimeP();
731 final BigInteger primeQ =
732 ((RSAPrivateCrtKey) this.key).getPrimeQ();
733 final BigInteger primeExponentP =
734 ((RSAPrivateCrtKey) this.key).getPrimeExponentP();
735 final BigInteger primeExponentQ =
736 ((RSAPrivateCrtKey) this.key).getPrimeExponentQ();
737 final BigInteger crtCoefficient =
738 ((RSAPrivateCrtKey) this.key).getCrtCoefficient();
739 //Calc Signature
740 final BigInteger cipherTextOne =
741 rr.modPow(primeExponentP, primeP);
742 final BigInteger cipherTextTwo =
743 rr.modPow(primeExponentQ, primeQ);
744 final BigInteger h =
745 cipherTextOne.subtract(cipherTextTwo).multiply(crtCoefficient).mod(primeP);
746 cipherText = primeQ.multiply(h).add(cipherTextTwo);
747
748 if (log.isLoggable(Level.FINEST)) {
749 log.finest("Have calulated <cipherText="+cipherText+
750 "> with RSAPrivateCrtKey <key="+this.key+">.");
751 }
752
753 //Original RSA decryption according to Rivest, Shamir and Adelmann.
754 //Here it will be used to _encrypt_ the representative element 'rr' with
755 //help of the signers private key.
756 } else if (this.key instanceof RSAPrivateKey) {
757 final BigInteger privateExponent =
758 ((RSAPrivateKey) this.key).getPrivateExponent();
759 //Calc Signature
760 cipherText = rr.modPow(privateExponent, modulus);
761
762 if (log.isLoggable(Level.FINEST)) {
763 log.finest("Have calulated <cipherText="+cipherText+
764 "> with RSAPrivateKey <key="+this.key+">.");
765 }
766
767 //We are wrong... (default case - shouldn't really happen!) If we
768 //are ditching here, there are something wrong with initialization.
769 } else {
770 IllegalStateException e = new IllegalStateException(
771 "ISO9796Part1Codec contains inappropriate Key.");
772
773 if (log.isLoggable(Level.FINER)) {
774 log.finer("Throwing IllegalSateException, Exception: " + e);
775 }
776
777 throw e;
778 }
779
780 // sigma = min(rr^s mod n, n - (rr^s mod n))
781 final BigInteger sigmaAsNumber =
782 cipherText.min(modulus.subtract(cipherText));
783
784 if (log.isLoggable(Level.FINEST)) {
785 log.finest("Have set <sigmaAsNumber="+sigmaAsNumber+
786 "> = min(cipherText, modulus-cipherText).");
787 }
788
789 //Convert sigmaAsNumber to an unsigned byte array.
790 final byte[] sigma =
791 BigIntegerUtil.toUnsignedByteArray(sigmaAsNumber);
792
793 //Debug 'sigma'.
794 if (log.isLoggable(Level.FINER)) {
795 log.finer("Final result of <sigma=" + ByteUtil.toHex(sigma) + ">.");
796 //added to detect our first bug ;-) 05/30/2002
797 log.finer("Final length of <sigma.length=" + sigma.length + ">.");
798 log.finer("Final bit length of sigma is <ks="+ks+"> bit.");
799 }
800
801 //Create 'bitStringSignature' from 'sigma' and its length in bits 'ks'
802 //as ISO9796Part1BitString.
803 ISO9796Part1BitString bitStringSignature =
804 new ISO9796Part1BitString(sigma, ks);
805
806 if (log.isLoggable(Level.FINER)) {
807 log.finer("Return from encodeMessage(...) with <bitStringSignature="+
808 bitStringSignature+">.");
809 }
810
811 //Return the bitStringSignature.
812 return bitStringSignature;
813 }
814
815 /**
816 * ISO9796-1 RSA-Signature Decoding with Message Recovery.
817 *
818 * <p> This is the inverse operation of
819 * encodeMessage(ISO97696Part1RSACodec, boolean)
820 *
821 * @param bitStringSignature the Signature as ISO9796Part1BitString with a
822 * bitLength of k-1 bits. Where k is the bitLength of the public key
823 * modulus.
824 * @return the recoverd message as ISO9796Part1Message or null if the
825 * signature is rejected.
826 * throws NullPointerException if bitStringSignature is null.
827 * @throws IllegalStateException if this Codec object isn't initialized
828 * for decoding.
829 */
830 ISO9796Part1BitString decodeSignature(
831 ISO9796Part1BitString bitStringSignature) {
832 //Debug method entry.
833 if (log.isLoggable(Level.FINER)) {
834 log.finer("Entering decodeMessage(<bitStringSignature="+
835 bitStringSignature+">.");
836 }
837
838 //Debug Member usage.
839 if (log.isLoggable(Level.FINEST)) {
840 log.finest("Will use member <key=" + this.key + ">.");
841 log.finest("We are in <state=" + this.state + ">.");
842 }
843
844
845
846 //////
847 //
848 // Pre-Conditions check
849 //
850 //////
851
852 if (this.state != State.DECODE) {
853 IllegalStateException e = new IllegalStateException(
854 "The ISO9796Part1RSACodec is not in the DECODE state.");
855
856 if (log.isLoggable(Level.FINER)) {
857 log.finer("Throwing IllegalSateException, because (<state="+
858 this.state+"> != State.DECODE). Exception: " + e);
859 }
860
861 throw e;
862 }
863 if (bitStringSignature == null) {
864 NullPointerException e = new NullPointerException(
865 "Parameter bitStringSignature is null.");
866
867 if (log.isLoggable(Level.FINER)) {
868 log.finer("Throwing NullPointerException, because " +
869 "<bitStringSignature="+bitStringSignature+">. " +
870 "Exception: " + e);
871 }
872
873 throw e;
874 }
875
876
877
878 //////
879 //
880 // RSA Verification function (A.5) and Signature opening(6.1)
881 //
882 //////
883
884 //Get 'modulus'
885 final BigInteger modulus = this.key.getModulus();
886
887 if (log.isLoggable(Level.FINEST)) {
888 log.finest("Have set <modulus="+modulus+
889 "> = <key.getModulus()="+this.key.getModulus()+">.");
890 }
891
892 //Get 'sigma'.
893 final byte[] sigma = bitStringSignature.getBitString();
894
895 //Debug 'sigma'.
896 if (log.isLoggable(Level.FINER)) {
897 log.finer("Recovered result of <sigma=" + ByteUtil.toHex(sigma) + ">.");
898 }
899
900 //Convert the signature 'sigma' to the BigInteger representation of the
901 //signature 'sigma' - denoted as 'sigmaAsNumber'.
902 final BigInteger sigmaAsNumber = new BigInteger(1, sigma);
903
904 if (log.isLoggable(Level.FINEST)) {
905 log.finest("Have converted <sigmaAsNumber="+sigmaAsNumber+
906 "> = new BigInteger(1, <sigma="+ByteUtil.toHex(sigma)+">).");
907 }
908
909 //if (sigmaAsNumber >= n/2)
910 if (sigmaAsNumber.compareTo(modulus.divide(TWO)) >= 0) {
911 log.finer(
912 "Return from decodeSignature(...). " +
913 "Reject Signature! " +
914 "Signature is not a positive integer less than modulus/2.");
915
916 //reject signature.
917 return null;
918 }
919
920 //Setup RSA public exponent.
921 final BigInteger publicExponent =
922 ((RSAPublicKey) this.key).getPublicExponent();
923
924 if (log.isLoggable(Level.FINEST)) {
925 log.finest("Have set <publicExponent="+publicExponent+
926 "> = <((RSAPublicKey) key).getPublicExponent()="+
927 ((RSAPublicKey) this.key).getPublicExponent()+">");
928 }
929
930 //Do RSA encryption operation, according to Rivest, Shamir and Adelmann.
931 //Here it will be used to _decrypt_ the the signature 'sigma' with
932 //help of the signers public key. The result will be the resulting
933 //integer 'is'
934 final BigInteger is = (sigmaAsNumber.modPow(publicExponent, modulus));
935
936 if (log.isLoggable(Level.FINEST)) {
937 log.finest("Have decrypted <is="+is+"> = <sigmaAsNumber="+
938 sigmaAsNumber+">^<publicExponent="+publicExponent+"> mod <modulus="+
939 modulus+">.");
940 }
941
942 //
943 //In the following code section, we do recover the intermediate
944 //integer ir, first as a number an then we will it convert to a
945 //byte array.
946 //
947
948 //The recovered intermediate integer 'ir'
949 BigInteger irAsNumber;
950
951 //public exponent is even
952 if (publicExponent.mod(TWO).equals(ZERO)) {
953 if (log.isLoggable(Level.FINEST)) {
954 log.finest("Public exponent is even.");
955 }
956
957 //if (is % 16 == 6)
958 if (is.mod(SIXTEEN).equals(SIX)) {
959 if (log.isLoggable(Level.FINEST)) {
960 log.finest("is mod 16 is congruent to 6.");
961 }
962
963 //ir = is
964 irAsNumber = is;
965
966 if (log.isLoggable(Level.FINEST)) {
967 log.finest("Have set <irAsNumber="+irAsNumber+
968 "> = <is="+is+">.");
969 }
970
971 //if ((modulus - is) % 16 == 6)
972 } else if (modulus.subtract(is).mod(SIXTEEN).equals(SIX)) {
973 if (log.isLoggable(Level.FINEST)) {
974 log.finest("(modulus - is) mod 16 is congruent to 6.");
975 }
976
977 //ir = modulus - is
978 irAsNumber = modulus.subtract(is);
979
980 if (log.isLoggable(Level.FINEST)) {
981 log.finest("Have calculated <irAsNumber="+irAsNumber+
982 "> = <modulus="+modulus+"> - <is="+is+">.");
983 }
984
985
986 //if (is % 8 == 3)
987 } else if (is.mod(EIGHT).equals(THREE)) {
988 if (log.isLoggable(Level.FINEST)) {
989 log.finest("is mod 8 is congruent to 3.");
990 }
991
992 //ir = 2is
993 irAsNumber = is.multiply(TWO);
994
995 if (log.isLoggable(Level.FINEST)) {
996 log.finest("Have calculated <irAsNumber="+irAsNumber+
997 "> = 2 * <is="+is+">.");
998 }
999
1000 //if ((modulus - is) % 8 == 3)
1001 } else if (modulus.subtract(is).mod(EIGHT).equals(THREE)) {
1002 if (log.isLoggable(Level.FINEST)) {
1003 log.finest("(modulus - is) mod 8 is congruent to 3.");
1004 }
1005
1006 //ir = 2(modulus - is)
1007 irAsNumber = modulus.subtract(is).multiply(TWO);
1008
1009 if (log.isLoggable(Level.FINEST)) {
1010 log.finest("Have calculated <irAsNumber="+irAsNumber+
1011 "> = 2 * (<modulus="+modulus+"> - <is="+is+">).");
1012 }
1013
1014 //is or modulus-is is not congruent to 3 mod 8
1015 } else {
1016 log.finer(
1017 "Return from decodeSignature(...). " +
1018 "Reject Signature! " +
1019 "is or (modulus - is) is not congruent to 3 mod 8 or to " +
1020 "6 mod 16.");
1021
1022 //reject signature.
1023 return null;
1024 }
1025
1026 //public exponent is odd
1027 } else {
1028 if (log.isLoggable(Level.FINEST)) {
1029 log.finest("Public exponent is odd.");
1030 }
1031
1032 //if (is % 16 == 6)
1033 if (is.mod(SIXTEEN).equals(SIX)) {
1034 if (log.isLoggable(Level.FINEST)) {
1035 log.finest("is mod 16 is congruent to 6.");
1036 }
1037
1038 //ir = is
1039 irAsNumber = is;
1040
1041 if (log.isLoggable(Level.FINEST)) {
1042 log.finest("Have set <irAsNumber="+irAsNumber+
1043 "> = <is="+is+">.");
1044 }
1045
1046 //if ((modulus - is) % 16 == 6)
1047 } else if (modulus.subtract(is).mod(SIXTEEN).equals(SIX)) {
1048 if (log.isLoggable(Level.FINEST)) {
1049 log.finest("(modulus - is) mod 16 is congruent to 6.");
1050 }
1051
1052 //ir = modulus - is
1053 irAsNumber = modulus.subtract(is);
1054
1055 if (log.isLoggable(Level.FINEST)) {
1056 log.finest("Have calculated <irAsNumber="+irAsNumber+
1057 "> = <modulus="+modulus+"> - <is="+is+">.");
1058 }
1059
1060 //is or modulus-is is not congruent to 6 mod 16
1061 } else {
1062 log.finer(
1063 "Return from decodeSignature(...). " +
1064 "Reject Signature! " +
1065 "is or (modulus - is) is not congruent to 6 mod 16.");
1066
1067 //reject signature.
1068 return null;
1069 }
1070 }
1071
1072 //'k' is the length of the 'modulus' in bits.
1073 final int k = modulus.bitLength();
1074
1075 if (log.isLoggable(Level.FINEST)) {
1076 log.finest("Have set <k="+k+"> = <modulus.bitLength()="+
1077 modulus.bitLength()+">.");
1078 }
1079
1080 //The lower bound for 'ir'
1081 final BigInteger lowerBound = TWO.pow(k - 2);
1082
1083 //The upper bound for 'ir'
1084 final BigInteger upperBound = TWO.pow(k - 1).subtract(ONE);
1085
1086 //if (ir < lowerBound)
1087 if (irAsNumber.compareTo(lowerBound) < 0) {
1088 log.finer(
1089 "Return from decodeSignature(...). " +
1090 "Reject Signature! " +
1091 "<irAsNumber="+irAsNumber+"> is less than of 2^(k-2).");
1092
1093 //reject signature.
1094 return null;
1095 }
1096
1097 //if (import > upperBound)
1098 if (irAsNumber.compareTo(upperBound) > 0) {
1099 log.finer(
1100 "Return from decodeSignature(...). " +
1101 "Reject Signature! " +
1102 "<irAsNumber="+irAsNumber+"> is greater than 2^(k-1)-1.");
1103
1104 //reject signature.
1105 return null;
1106 }
1107
1108 //Convert the BigInteger representation of 'ir', denoted as
1109 //'irAsNumber', ot the byte array representation of 'ir', denoted
1110 //as 'ir'.
1111 byte[] ir = BigIntegerUtil.toUnsignedByteArray(irAsNumber);
1112
1113 if (log.isLoggable(Level.FINEST)) {
1114 log.finest("Have converted <ir="+ByteUtil.toHex(ir)+
1115 "> = BigIntegerUtil.toUnsignedByteArray(<irAsNumber="+
1116 irAsNumber+">).");
1117 }
1118
1119 //We dont have to check if 'ir' is a bit string of 'ks' bits, because
1120 //we do this with the BigInteger bound checkeing, where we check above
1121 //if irAsNumber is in the range between 2^(k-2) to 2^(k-1)-1
1122 //inclusively.
1123
1124 //Check if the least significant nibble is valued to 6
1125 if ((ir[ir.length - 1] & 0x0f) != 0x06) {
1126 //LSN isn't 6
1127 log.finer(
1128 "Return from decodeSignature(...). " +
1129 "Reject Signature! " +
1130 "Least significant nibble of ir isn't 6: <(ir[<ir.length="+
1131 ir.length+"> - 1] & 0x0f)="+(ir[ir.length - 1] & 0x0f)+">.");
1132
1133 //reject signature.
1134 return null;
1135 }
1136
1137 //Debug 'ir'.
1138 if (log.isLoggable(Level.FINER)) {
1139 log.finer("Recovered result of <ir="+ByteUtil.toHex(ir)+">.");
1140 }
1141
1142
1143
1144 //////
1145 //
1146 // Message recovery
1147 //
1148 //////
1149
1150 //'ks' the length of the signature 'sigma' in bits.
1151 final int ks = k - 1;
1152
1153 if (log.isLoggable(Level.FINEST)) {
1154 log.finest("Have calculated <ks="+ks+"> = <k"+k+"> - 1.");
1155 }
1156
1157 //'t' is the least integer, such that a string of '2t bytes' includes at
1158 //least 'ks-1 bits'.
1159 final int t = (ks + 14) / 16 ;
1160
1161 if (log.isLoggable(Level.FINEST)) {
1162 log.finest("Have calculated <t="+t+"> = (<ks="+ks+"> + 14) / 16.");
1163 }
1164
1165 //Create 'mr' with a length of '2t bytes'
1166 final byte[] mr = new byte[2 * t];
1167
1168 if (log.isLoggable(Level.FINEST)) {
1169 log.finest("Have created <mr"+ByteUtil.toHex(mr)+
1170 "> = new byte[2 * <t="+t+">]");
1171 }
1172
1173 //Copy 'ir' into 'mr'. We have to distinguish between two cases:
1174 //1. The number of bytes in ir is greater than or equal to the
1175 // number of bytes in mr.
1176 //2. The number of bytes in ir is less than the number of bytes in mr.
1177 //This differentiation is necessary, because the number of bytes in mr
1178 //is a multiple of 16 and the number of bytes in ir is multiple of 8.
1179 if (ir.length >= mr.length) {
1180 System.arraycopy(ir, ir.length - mr.length, mr, 0, mr.length);
1181 } else { //(ir.length < mr.length)
1182 System.arraycopy(ir, 0, mr, mr.length - ir.length, ir.length);
1183 }
1184
1185 if (log.isLoggable(Level.FINEST)) {
1186 log.finest("Have copied <ir=" + ByteUtil.toHex(ir) +
1187 "> into <mr=" + ByteUtil.toHex(mr) + "> aligned to the right.");
1188 }
1189
1190 //Mask out (pad) all 16t - (ks - 1) bits to the left as padding bits.
1191 //This is the reverse operation to the truncation operation.
1192 if ((ks - 1) % 16 < 8) {
1193 if ((ks - 1) % 8 == 0) {
1194 mr[0] &= 0xff;
1195 if (log.isLoggable(Level.FINEST)) {
1196 log.finest("Have set <mr[0]="+ByteUtil.toHex(mr[0])+
1197 "> &= 0xff.");
1198 }
1199 } else {
1200 mr[0] &= 0x00;
1201 if (log.isLoggable(Level.FINEST)) {
1202 log.finest("Have set <mr[0]="+ByteUtil.toHex(mr[0])+
1203 "> &= 0x00.");
1204 }
1205 }
1206 mr[1] &= 0xff >>> ((8 - (ks - 1) % 8) % 8);
1207 if (log.isLoggable(Level.FINEST)) {
1208 log.finest("Have set <mr[1]="+ByteUtil.toHex(mr[1])+
1209 "> &= <0xff >>> ((8 - (<ks="+ks+"> - 1) % 8) % 8)="+
1210 ByteUtil.toHex((byte) (0xff >>> ((8 - (ks - 1) % 8) % 8)))+">.");
1211 }
1212 } else { //((ks - 1) % 16 >= 8)
1213 mr[0] &= 0xff >>> (8 - (ks - 1) % 8);
1214 if (log.isLoggable(Level.FINEST)) {
1215 log.finest("Have set <mr[0]="+ByteUtil.toHex(mr[0])+
1216 "> &= <0xff >>> (8 - (<ks="+ks+"> - 1) % 8)="+
1217 ByteUtil.toHex((byte) (0xff >>> (8 - (ks - 1) % 8)))+">.");
1218 }
1219 }
1220
1221
1222
1223 //This is the reverse operation to the forcing operation.
1224 mr[mr.length - 1] =
1225 (byte) ((PI_INV[(mr[mr.length - 2] >>> 4) & 0x0f] << 4) |
1226 ((mr[mr.length - 1] >>> 4) & 0x0f));
1227
1228 if (log.isLoggable(Level.FINEST)) {
1229 log.finest("Do reverse operation of forcing to <mr[<mr.length="+
1230 mr.length+"> - 1]="+ByteUtil.toHex(mr[mr.length - 1])+">.");
1231 }
1232
1233 //Debug 'mr'.
1234 if (log.isLoggable(Level.FINER)) {
1235 log.finer("Recovered result of <mr="+ByteUtil.toHex(mr)+">.");
1236 }
1237
1238 //Declare and initialize the flag tSumsAreNull, the number z and
1239 //the index r.
1240 boolean tSumsAreNull = true;
1241 int z = 0;
1242 int r = 0;
1243
1244 //Search for z and r in mr, while looking for the first non null sum.
1245 for (int i = 1; i <= t; i++) {
1246 //Debug m_2i and S(m_2i-1)
1247 byte sumA = mr[mr.length - (2 * i)];
1248 byte sumB = SHADOW[mr[mr.length - ((2 * i) - 1)] & 0xff];
1249
1250 //Compute the 't'-th 'sum'.
1251 int sum = mr[mr.length - (2 * i)] ^
1252 SHADOW[mr[mr.length - ((2 * i) - 1)] & 0xff];
1253
1254 if (log.isLoggable(Level.FINEST)) {
1255 log.finest("Look for first non null sum: index <i="+i+"> <sum="+
1256 sum+"> = <mr["+(mr.length - (2 * i))+"]="+ByteUtil.toHex(sumA)+
1257 "> ^ <mr["+(mr.length - ((2 * i) - 1))+"]="+ByteUtil.toHex(sumB)+
1258 ">.");
1259 }
1260
1261 //We found the first non null 'sum'.
1262 if (sum != 0) {
1263 if(log.isLoggable(Level.FINEST)) {
1264 log.finest("Found first non null sum!");
1265 }
1266 //Tell the flag that we have found the first non null sum.
1267 tSumsAreNull = false;
1268 //Number 'z' is recovered as the position of the first
1269 //non null 'sum'.
1270 z = i;
1271 if(log.isLoggable(Level.FINEST)) {
1272 log.finest("Have set <z="+z+"> = <i="+i+">.");
1273 }
1274 //Index 'r' is recovered as the value of the least significant
1275 //nibble of the first non null 'sum'.
1276 r = sum & 0x0f;
1277 if(log.isLoggable(Level.FINEST)) {
1278 log.finest("Have calculated <r="+r+"> = <sum="+sum+
1279 "> & 0x0f.");
1280 }
1281 break;
1282 }
1283 }
1284
1285 //The signature sigma shall be rejected if the t sums are null.
1286 if (tSumsAreNull) {
1287 //reject signature
1288 log.finer(
1289 "Return from decodeSignature(...). " +
1290 "Reject Signature! " +
1291 "All <t="+t+"> sums are null.");
1292
1293 //reject signature.
1294 return null;
1295 }
1296
1297 //The signature sigma shall be rejected if if index r is not
1298 //valued from 1 to 8.
1299 if ( r < 1 || r > 8) {
1300 log.finer(
1301 "Return from decodeSignature(...). " +
1302 "Reject Signature! " +
1303 "<r="+r+"> is out of range. r have to be (1 <= r <= 8).");
1304
1305 //reject signature.
1306 return null;
1307 }
1308
1309 //Create 'mp' with a length of 'z' bytes.
1310 final byte[] mp = new byte[z];
1311
1312 if (log.isLoggable(Level.FINEST)) {
1313 log.finest("Have created <mp"+ByteUtil.toHex(mp)+
1314 "> = new byte[<z="+z+">]");
1315 }
1316
1317 //The recovered padded message 'mp' is the string of the 'z' least
1318 //significant bytes in odd position in 'mr'
1319 for (int i = 1; i <= z; i++) {
1320 mp[mp.length - i] = mr[mr.length - ((2 * i) - 1)];
1321 }
1322 log.finest("mp: " + ByteUtil.toHex(mp));
1323
1324 //Check the padded zero bits in 'mp'.
1325 if (((mp[0] & (0xff << (9 - r))) & 0xff) != 0x00) {
1326 //The 'r' - 1 most significant bits of 'mp' are not zero.
1327 log.finer(
1328 "Return from decodeSignature(...). " +
1329 "Reject Signature! " +
1330 "(<(<mp[0]="+ByteUtil.toHex(mp[0])+"> & (0xff << (9 - <r="+r+">)))="+
1331 ByteUtil.toHex((byte) (mp[0] & (0xff << (9 - r))))+"> != 0x00).");
1332
1333 //reject signature.
1334 return null;
1335 }
1336
1337 //Debug 'ir'.
1338 if (log.isLoggable(Level.FINER)) {
1339 log.finer("Recovered result of <mp="+ByteUtil.toHex(mp)+">.");
1340 }
1341
1342
1343
1344 //////
1345 //
1346 // Redundancy checking
1347 //
1348 //////
1349
1350 //The signature 'sigma' shall only be accepted if and only if the
1351 //'ks'-1 least significant bits of 'mr' are equal to the 'ks'-1 least
1352 //significant bits of another extended message with redundancy
1353 //'anotherMr' computed from the recovered padded message 'mp'.
1354
1355 //The another extended message with redundancy have to created in to
1356 //steps:
1357 //1. Create another extended message 'anotherMe' by repeating the
1358 // 'z' bytes of 'mp', as many times as necessary, in order and
1359 // concatenated to the left, until forming a string of t bytes.
1360 //2. Create another extende message with redundancy 'anotherMr' by
1361 // interleaving the 't' bytes of 'anotherMe' in odd positions and
1362 // 't' bytes of redundancy in even positions. Altered by index 'r',
1363 // the least significant nibble of the '2z-th byte' of 'anotherMr'
1364 // codes the message length by its value in its position.
1365 //For performance and memory reasons we haven't an extra 'anotherMe'.
1366 //So we create 'anotherMp' with all 'anotherMe'-like operations defined
1367 //in ISO9796-1:1991.
1368
1369 //Create anotherMr with a length of '2t bytes'
1370 final byte[] anotherMr = new byte[2 * t];
1371
1372 if (log.isLoggable(Level.FINEST)) {
1373 log.finest("Have created <anotherMr"+ByteUtil.toHex(anotherMr)+
1374 "> = new byte[2 * <t="+t+">]");
1375 }
1376
1377 //Extend and interleave the padded message mp.
1378 for(int i = 1; i <= t ; i++) {
1379 //odd position in 'anotherMr' -> (2i-1) -> 't' byte of 'me'
1380 anotherMr[2*t - (2*i-1)] = mp[z-(((i-1) % z) + 1)];
1381 //even -> (2i) -> 't' byte of redundancy with the help of SHADOW.
1382 anotherMr[2*t - (2*i)] = SHADOW[mp[z-(((i-1) % z) + 1)] & 0xff];
1383 }
1384
1385 if (log.isLoggable(Level.FINEST)) {
1386 log.finest("Have extended and interleaved <anotherMr"+
1387 ByteUtil.toHex(anotherMr)+">.");
1388 }
1389
1390 //The '2z-th byte' of 'anotherMr' equals the exclusive-or of index 'r'
1391 //with the shadow of the 'z-th byte' of 'anotherMe'.
1392 anotherMr[2*t - (2*z)] ^= (byte) r;
1393
1394 if (log.isLoggable(Level.FINEST)) {
1395 log.finest("Have xored r to the 2*z-th byte of anothermr: "+
1396 "<anotherMr[<2*<t="+t+"> - (2*<z="+z+">)="+(2*t - (2*z))+">]="+
1397 ByteUtil.toHex(anotherMr[2*t - (2*z)])+"> ^= (byte) <r="+r+">.");
1398 }
1399
1400 //Mask out (pad) all 16t - (ks - 1) bits to the left as padding bits.
1401 //This is the reverse operation to the truncation operation.
1402 if ((ks - 1) % 16 < 8) {
1403 if ((ks - 1) % 8 == 0) {
1404 anotherMr[0] &= 0xff;
1405 if (log.isLoggable(Level.FINEST)) {
1406 log.finest("Have set <anotherMr[0]="+
1407 ByteUtil.toHex(anotherMr[0])+"> &= 0xff.");
1408 }
1409 } else {
1410 anotherMr[0] &= 0x00;
1411 if (log.isLoggable(Level.FINEST)) {
1412 log.finest("Have set <anotherMr[0]="+
1413 ByteUtil.toHex(anotherMr[0])+"> &= 0x00.");
1414 }
1415 }
1416 anotherMr[1] &= 0xff >>> ((8 - (ks - 1) % 8) % 8);
1417 if (log.isLoggable(Level.FINEST)) {
1418 log.finest("Have set <anotherMr[1]="+
1419 ByteUtil.toHex(anotherMr[1])+"> &= <0xff >>> ((8 - (<ks="+ks+
1420 "> - 1) % 8) % 8)="+
1421 ByteUtil.toHex((byte) (0xff >>> ((8 - (ks - 1) % 8) % 8)))+">.");
1422 }
1423 } else { //((ks - 1) % 16 >= 8)
1424 anotherMr[0] &= 0xff >>> (8 - (ks - 1) % 8);
1425 if (log.isLoggable(Level.FINEST)) {
1426 log.finest("Have set <anotherMr[0]="+ByteUtil.toHex(anotherMr[0])+
1427 "> &= <0xff >>> (8 - (<ks="+ks+"> - 1) % 8)="+
1428 ByteUtil.toHex((byte) (0xff >>> (8 - (ks - 1) % 8)))+">.");
1429 }
1430 }
1431
1432 //Debug anotherMr.
1433 if (log.isLoggable(Level.FINER)) {
1434 log.finer("Final result of <anotherMr=" + ByteUtil.toHex(anotherMr) +
1435 ">.");
1436 }
1437
1438 //Verify if 'mr' and 'anotherMr' are the same. On step further we
1439 //masked the 16t - (ks - 1) padding bits so we compare now only the
1440 //ks - 1 least significant bits in 'mr' with the ks - 1 least
1441 //significant bits in 'anotherMr'.
1442 if (Arrays.equals(mr, anotherMr) == false) {
1443 //ks - 1 least significant bits in 'mr' are different to the ks - 1
1444 //least significant bits in 'anotherMr'.
1445 log.finer(
1446 "Return from decodeSignature(...). " +
1447 "Reject Signature! " +
1448 "<ks="+ks+"> - 1 least significant bits in <mr="+ByteUtil.toHex(mr)+
1449 "> are different to the <ks="+ks+" - 1 least significant bits in " +
1450 "<anotherMr="+ByteUtil.toHex(anotherMr)+">.");
1451
1452 //reject signature.
1453 return null;
1454 }
1455
1456 if (log.isLoggable(Level.FINEST)) {
1457 log.finest("<mr="+ByteUtil.toHex(mr)+
1458 "> is equal to <anotherMr="+ByteUtil.toHex(anotherMr)+">.");
1459 }
1460
1461 //Calculate the 'message' bit string length 'messageBitLength'.
1462 int messageBitLength = (z * 8) - (r - 1);
1463
1464 if (log.isLoggable(Level.FINEST)) {
1465 log.finest("Have calculated <messageBitLength="+messageBitLength+
1466 "> = (<z="+z+"> * 8) - (<r"+r+"> - 1).");
1467 }
1468
1469 //Create the bitStringMessage object.
1470 ISO9796Part1BitString bitStringMessage =
1471 new ISO9796Part1BitString(mp, messageBitLength);
1472
1473 if (log.isLoggable(Level.FINER)) {
1474 log.finer("Return from decodeMessage(...) with <bitStringMessage="+
1475 bitStringMessage+">.");
1476 }
1477
1478 //We are right so we return the recovered message.
1479 return bitStringMessage;
1480 }
1481
1482 /**
1483 * This method calculates the jacobi symbol (a|n) from the two BigIntegers
1484 * a and n. The two numbers have to satisfy the following preconditions:
1485 * <pre>
1486 * 1. n is odd
1487 * 2. 3 <= n
1488 * 3. 0 <= a < n
1489 * </pre>
1490 *
1491 * <p> The pseudo code for this method was taken from the great book
1492 * "Handbook of Applied Cryptography by A.Menezes, P. van Oorschot and
1493 * S. Vanstone. See Page 73, Algorithm 2.149 for details
1494 *
1495 * <p> You can find it in the Internet at:
1496 * http://www.cacr.math.uwaterloo.ca/hac/about/chap2.pdf
1497 *
1498 * <p> Sample C code can be found at:
1499 * ftp://ftp.mindspring.com/users/pate/crypto/chap02/jacobi.c
1500 *
1501 * @param a param of the jacobi symbol
1502 * @param n param of the jacobi symbol
1503 * @return the jacobi symbol (a|n), that will be -1 or 0 or 1.
1504 * @throws NullPointerException if a or n is null.
1505 * @throws IllegalArgumentException if n is even or (n < 3), further
1506 * if a and n don't satisfies the condition (0 <= a < n)
1507 */
1508 private int jacobi(BigInteger a, BigInteger n) {
1509 if (a == null) {
1510 throw new NullPointerException("Parameter 'a' is null.");
1511 }
1512 if (n == null) {
1513 throw new NullPointerException("Parameter 'n' is null.");
1514 }
1515 //(n < 3)
1516 if (n.compareTo(THREE) < 0) {
1517 throw new IllegalArgumentException("Parameter 'n' is less than 3.");
1518 }
1519 //(a < 0)
1520 if (a.compareTo(ZERO) < 0) {
1521 throw new IllegalArgumentException(
1522 "Parameter 'a' is less than zero.");
1523 }
1524 //(n <= a)
1525 if (n.compareTo(a) <= 0) {
1526 throw new IllegalArgumentException("Parameter 'n' is less than " +
1527 "or equal to parameter 'a'.");
1528 }
1529 // n should be odd
1530 if (n.mod(TWO).equals(BigInteger.ZERO)) {
1531 throw new IllegalArgumentException("Parameter 'n' is a even " +
1532 "number but 'n' should odd.");
1533 }
1534
1535 return jacobiWorker(a, n);
1536 }
1537
1538 /**
1539 * This method calculates the jacobi symbol (a|n) from the two BigIntegers
1540 * a and n. Without prcondition check. Only the jacobi method should invoke
1541 * this method. We have this done because the recursive invokation of the
1542 * jacobiWorker. We have sepparated these two methods because, we
1543 * do in jacobi(..) the exception checking for the initial entry.
1544 *
1545 * @param a param of the jacobi symbol
1546 * @param n param of the jacobi symbol
1547 * @return the jacobi symbol (a|n), that will be -1 or 0 or 1.
1548 */
1549 private int jacobiWorker(BigInteger a, BigInteger n) {
1550
1551 //if (a == 0) {
1552 if (a.equals(ZERO)) {
1553 return 0;
1554 }
1555
1556 //if (a == 1) {
1557 if (a.equals(ONE)) {
1558 return 1;
1559 }
1560
1561 BigInteger b = a;
1562 BigInteger e = ZERO;
1563 //while ((b & 1) == 0) { // while (b is even)
1564 while (b.mod(TWO).equals(ZERO)) {
1565 //b >>>= 1;
1566 b = b.shiftRight(1);
1567 //e++;
1568 e = e.add(ONE);
1569 }
1570 BigInteger a1 = b;
1571
1572 //m = n % 8;
1573 BigInteger m = n.mod(EIGHT);
1574
1575 int s = 1;
1576 //if ((e & 1) == 0) {
1577 if (e.mod(TWO).equals(ZERO)) {
1578 s = 1;
1579 //} else if (m == 1 || m == 7) {
1580 } else if (m.equals(ONE) || m.equals(SEVEN)) {
1581 s = 1;
1582 //} else if (m == 3 || m == 5) {
1583 } else if (m.equals(THREE) || m.equals(FIVE)) {
1584 s = -1;
1585 }
1586
1587 //if (n % 4 == 3 && a1 % 4 == 3) {
1588 if (n.mod(FOUR).equals(THREE) && a1.mod(FOUR).equals(THREE)) {
1589 s = -s;
1590 }
1591
1592 BigInteger n1;
1593 //if (a1 != 1) {
1594 if (a1.equals(ONE) == false) {
1595 //n1 = n % a1;
1596 n1 = n.mod(a1);
1597 } else {
1598 //n1 = 1;
1599 n1 = ONE;
1600 }
1601
1602 return s * jacobiWorker(n1, a1);
1603 }
1604
1605 /** Type safe enum for the enclosing class object state. */
1606 private final static class State {
1607 /** Name odf the state. */
1608 private final String name;
1609
1610 /** Constructor need only to called within this class. */
1611 private State(String name) {
1612 this.name = name;
1613 }
1614
1615 /** z
1616 * Returns a string representation of the object.
1617 *
1618 * @return a string representation of the object.
1619 */
1620 public String toString() {
1621 return this.name;
1622 }
1623
1624 /** State constante if the enclosing class isn't initialized. */
1625 private static final State UNINITIALIZED =
1626 new State("UNINITIALIZED");
1627
1628 /** State constante if the enclossing class is in Sign mode. */
1629 private static final State ENCODE = new State("ENCODE");
1630
1631 /** State constante if the enclossing class is in Verify mode. */
1632 private static final State DECODE = new State("DECODE");
1633 }
1634}
1635
|
ISO9796Part1RSACodec |
|