|
DES1KeySpec |
|
1 /* $RCSfile: DES1KeySpec.java,v $
2 * $Revision: 1.10 $
3 * $Date: 2002/11/23 11:09:57 $
4 * $Author: uwe_guenther $
5 * $State: Exp $
6 *
7 * Created on August 11, 2001 11:18 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.spec;
33
34 import java.security.InvalidKeyException;
35 import java.util.Arrays;
36
37 import de.cscc.crypto.util.ByteUtil;
38
39 /**
40 * DES secret key specification (56 bit or 64 bit with parity) class.
41 *
42 * <p>This class is immutable.
43 *
44 * @author <a href=mailto:uwe@cscc.de>Uwe Günther</a>
45 * @version $Revision: 1.10 $
46 */
47 public class DES1KeySpec implements DESKeySpec, Cloneable {
48
49 /** Key length in bytes. */
50 private static final int DES_KEY_LEN = 8;
51
52 /** The 4 DES weak keys. */
53 private static final byte[][] WEAK_KEYS = {
54 //weak key 0
55 {
56 (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,
57 (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01
58 },
59
60 //weak key 1
61 {
62 (byte)0xfe, (byte)0xfe, (byte)0xfe, (byte)0xfe,
63 (byte)0xfe, (byte)0xfe, (byte)0xfe, (byte)0xfe
64 },
65
66 //weak key 2
67 {
68 (byte)0x1f, (byte)0x1f, (byte)0x1f, (byte)0x1f,
69 (byte)0x0e, (byte)0x0e, (byte)0x0e, (byte)0x0e
70 },
71
72 //weak key 3
73 {
74 (byte)0xe0, (byte)0xe0, (byte)0xe0, (byte)0xe0,
75 (byte)0xf1, (byte)0xf1, (byte)0xf1, (byte)0xf1
76 }
77 };
78
79 /** The 12 DES semi weak keys. */
80 private static final byte[][] SEMI_WEAK_KEYS = {
81 //semi weak key 0
82 {
83 (byte)0x01, (byte)0xfe, (byte)0x01, (byte)0xfe,
84 (byte)0x01, (byte)0xfe, (byte)0x01, (byte)0xfe
85 },
86
87 //semi weak key 1
88 {
89 (byte)0xfe, (byte)0x01, (byte)0xfe, (byte)0x01,
90 (byte)0xfe, (byte)0x01, (byte)0xfe, (byte)0x01
91 },
92
93 //semi weak key 2
94 {
95 (byte)0x1f, (byte)0xe0, (byte)0x1f, (byte)0xe0,
96 (byte)0x0e, (byte)0xf1, (byte)0x0e, (byte)0xf1
97 },
98
99 //semi weak key 3
100 {
101 (byte)0xe0, (byte)0x1f, (byte)0xe0, (byte)0x1f,
102 (byte)0xf1, (byte)0x0e, (byte)0xf1, (byte)0x0e
103 },
104
105 //semi weak key 4
106 {
107 (byte)0x01, (byte)0xe0, (byte)0x01, (byte)0xe0,
108 (byte)0x01, (byte)0xf1, (byte)0x01, (byte)0xf1
109 },
110
111 //semi weak key 5
112 {
113 (byte)0xe0, (byte)0x01, (byte)0xe0, (byte)0x01,
114 (byte)0xf1, (byte)0x01, (byte)0xf1, (byte)0x01
115 },
116
117 //semi weak key 6
118 {
119 (byte)0x1f, (byte)0xfe, (byte)0x1f, (byte)0xfe,
120 (byte)0x0e, (byte)0xfe, (byte)0x0e, (byte)0xfe
121 },
122
123 //semi weak key 7
124 {
125 (byte)0xfe, (byte)0x1f, (byte)0xfe, (byte)0x1f,
126 (byte)0xfe, (byte)0x0e, (byte)0xfe, (byte)0x0e
127 },
128
129 //semi weak key 8
130 {
131 (byte)0x01, (byte)0x1f, (byte)0x01, (byte)0x1f,
132 (byte)0x01, (byte)0x0e, (byte)0x01, (byte)0x0e
133 },
134
135 //semi weak key 9
136 {
137 (byte)0x1f, (byte)0x01, (byte)0x1f, (byte)0x01,
138 (byte)0x0e, (byte)0x01, (byte)0x0e, (byte)0x01
139 },
140
141 //semi weak key 10
142 {
143 (byte)0xe0, (byte)0xfe, (byte)0xe0, (byte)0xfe,
144 (byte)0xf1, (byte)0xfe, (byte)0xf1, (byte)0xfe
145 },
146
147 //semi weak key 11
148 {
149 (byte)0xfe, (byte)0xe0, (byte)0xfe, (byte)0xe0,
150 (byte)0xfe, (byte)0xf1, (byte)0xfe, (byte)0xf1
151 }
152
153 };
154
155 /** Internal data representation. */
156 private byte[] key = new byte[8];
157
158 /**
159 * Creates a new DES1KeySpec from a 16 bytes long byte array. We
160 * use the first 8 bytes in key as the key material for the DES key.
161 * The bytes that constitute the two DES keys are those between
162 * key[0] and key[8] inclusive.
163 *
164 * @param key the buffer with the DES keys.
165 * @throws InvalidKeyException if the given key material is shorter
166 * than 8 bytes or the key is weak or semi weak.
167 */
168 public DES1KeySpec(byte[] key) throws InvalidKeyException {
169 this(key, 0);
170 }
171
172 /**
173 * Creates a new DES1KeySpec from a 16 bytes long byte array.
174 *
175 * @param key the buffer with the DES keys.
176 * @param offset the offset in key, where the key starts.
177 * @throws InvalidKeyException if the given key material is shorter
178 * than 8 bytes or the key is weak or semi weak.
179 */
180 public DES1KeySpec(byte[] key, int offset) throws InvalidKeyException {
181 if(key.length-offset < 8){
182 throw new InvalidKeyException(
183 "Usable byte range is " + (key.length-offset) +
184 " bytes large, but it should be 8 bytes or larger.");
185 }
186
187 System.arraycopy(key, offset, this.key, 0, 8);
188
189 //We have to first adjust the parity,
190 //because isWeak() and isSemiWeak() does deliver wrong results.
191 if (isParityAdjusted() == false){
192 adjustParity();
193 }
194
195 //After parity adjusting, now we can test if the key is weak.
196 if (isWeak() == true){
197 throw new InvalidKeyException(
198 "Key " + toString() + " is on of 4 weak DES keys.");
199 }
200
201 //After parity adjusting, now we can test if the key is semi weak.
202 if (isSemiWeak() == true){
203 throw new InvalidKeyException(
204 "Key " + toString() + " is on of 12 semi weak DES keys.");
205 }
206 }
207
208 /**
209 * Creates a new DES1KeySpec from an existing one.
210 *
211 * @param key DesKeySpec object with a key.
212 */
213 public DES1KeySpec(DES1KeySpec key) {
214 System.arraycopy(key.key, 0, this.key, 0, 8);
215 }
216
217 /**
218 * Creates and returns a deep copy of this object.
219 *
220 * @return a clone of this instance.
221 * @see java.lang.Cloneable
222 * @exception CloneNotSupportedException if the object's class does not
223 * support the <code>Cloneable</code> interface. Subclasses
224 * that override the <code>clone</code> method can also
225 * throw this exception to indicate that an instance cannot
226 * be cloned.
227 */
228 public Object clone() throws CloneNotSupportedException {
229 DES1KeySpec result = (DES1KeySpec) super.clone();
230 result.key = (byte[]) this.key.clone();
231 return result;
232 }
233
234 /**
235 * Indicates whether some other object is "equal to" this one.
236 *
237 * @param obj the reference object with which to compare.
238 * @return <code>true</code> if this object is the same as the obj
239 * argument; <code>false</code> otherwise.
240 * @see #hashCode()
241 * @see java.util.Hashtable
242 */
243 public boolean equals(Object obj) {
244 //Only for performance.
245 if (this == obj) {
246 return true;
247 }
248
249 //If obj == null then instanceof returns false, see JLS 15.20.2
250 if (!(obj instanceof DES1KeySpec)) {
251 return false;
252 }
253
254 DES1KeySpec other = (DES1KeySpec)obj;
255 return Arrays.equals(this.key, other.key);
256 }
257
258 /**
259 * Returns a hash code value for the object. This method is
260 * supported for the benefit of hashtables such as those provided by
261 * <code>java.util.Hashtable</code>.
262 *
263 * @return a hash code value for this object.
264 * @see #equals(java.lang.Object)
265 * @see java.util.Hashtable
266 */
267 public int hashCode() {
268 int result = 17;
269 for(int i = 0; i < this.key.length; i++) {
270 result = 37*result + this.key[i];
271 }
272 return result;
273 }
274
275 /**
276 * Returns a string representation of the object.
277 *
278 * @return a string representation of the object.
279 */
280 public String toString() {
281 return ByteUtil.toHex(this.key);
282 }
283
284 /**
285 * Resets the internal data representation to 0 (zero).
286 *
287 * Only for security reasons.
288 */
289 private void reset() {
290 Arrays.fill(this.key, (byte) 0x00);
291 }
292
293 /**
294 * Get the DES Key as byte[8].
295 *
296 * @return the DES Key as byte[8].
297 */
298 public byte[] getKey() {
299 /*byte[] returnValue =new byte[8];
300 System.arraycopy(this.key, 0, returnValue, 0, 8);
301 return returnValue;*/
302 return (byte[]) this.key.clone();
303 }
304
305 /**
306 * Checks parity for the whole key.
307 *
308 * @return true if the whole key is parity adjusted, respectively all
309 * bytes have odd parity, or false otherwise.
310 */
311 private boolean isParityAdjusted() {
312 for (int i = 0; i < this.key.length; i++) {
313 if (isParrityOdd(this.key[i]) == false) {
314
315 //At least one byte int the key
316 //has even parity and is corrupted.
317 return false;
318 }
319 }
320
321 //All bytes in the key has odd parity
322 //We say the key is parity adjusted.
323 return true;
324 }
325
326 /**
327 * Checks parity of a byte.
328 *
329 * The right most bit used as placeholder to change the parity.
330 *
331 * 00000010 -> odd parity
332 * 00000110 -> even parity
333 * 00001110 -> odd parity
334 * .
335 * .
336 * 10001110 -> even parity
337 *
338 * @return true if the parity of byte b is odd, or false if the parity is even.
339 * @param b the byte to check.
340 */
341 private boolean isParrityOdd(byte b) {
342
343 if (((
344 (b >>> 0) ^
345 (b >>> 1) ^
346 (b >>> 2) ^
347 (b >>> 3) ^
348 (b >>> 4) ^
349 (b >>> 5) ^
350 (b >>> 6) ^
351 (b >>> 7)
352 ) & 0x00000001 ) == 0x00000001)
353 {
354 return true; //1
355 } else {
356 return false; //0
357 }
358 }
359
360 /**
361 * Adjust the parity to odd parity (means a odd sum of "1" bits).
362 *
363 * The right most bit (bit 8) in every byte in the DES key is the
364 * parity bit. Every byte in the DES key must have always odd parity!
365 * If one byte in the key has not odd parity, the key is corrupted.
366 */
367 private void adjustParity() {
368 for (int i = 0; i < 8; i++){
369 this.key[i] = oddParity(this.key[i]);
370 }
371 }
372
373 /**
374 * Sets a byte b to odd parity, if it has even parity.
375 * If the input byte b has odd parity the return value will be
376 * the same as the input value b.
377 *
378 * <pre>
379 * 00000010 -> odd parity
380 * 00000110 -> even parity
381 * 00001110 -> odd parity
382 * .
383 * .
384 * 10001110 -> even parity
385 * </pre>
386 *
387 * Even parity means that the number of all "1" bits are even.
388 * Odd parity means that the number of all "1" bits are odd.
389 *
390 * The algorithm works in the following way:
391 * The right most bit (bit 8) is the parity bit.
392 * Every byte in the DES key must have always odd parity!
393 * If one byte in the key has not odd parity, the key is corrupted.
394 *
395 * That means:
396 * Is the sum of all "1" bits from bit 1 to bit 7 odd, set bit 8 to "0".
397 * IS the sum of all "1" bits from bit 1 to bit 7 even, set bit 8 to "1".
398 *
399 * @param b the byte where will be set to odd parity.
400 * @return the parity adjusted byte.
401 */
402 private byte oddParity(byte b) {
403 return (byte)(
404 (b & 0x000000fe) | ( //set bit 8 to 0
405 (
406 (
407 //xor bit 1 to 7
408 (b >>> 1) ^
409 (b >>> 2) ^
410 (b >>> 3) ^
411 (b >>> 4) ^
412 (b >>> 5) ^
413 (b >>> 6) ^
414 (b >>> 7)
415
416 //delete bit 1 to bit 7
417 ) & 0x00000001
418
419 //if the xor result "0" means even
420 //set party bit to "1" means odd
421 //
422 //if the xor result "1" means odd
423 //set parity bit to "0" means odd
424 ) ^ 0x00000001
425 )
426 );
427 }
428
429 /**
430 * Returns true, if the internal data representation of the key is
431 * equal with one of the 4 weak keys.
432 *
433 * @return true if the key is weak, false otherwise.
434 */
435 private boolean isWeak() {
436 for (int i = 0; i < 4; i++) {
437 if (Arrays.equals(DES1KeySpec.WEAK_KEYS[i], this.key)) {
438 return true;
439 }
440 }
441
442 return false;
443 }
444
445 /**
446 * Returns true, if the internal data representation of the key is
447 * equal with one of the 12 semi weak keys.
448 *
449 * @return true if the key is semi weak, false otherwise.
450 */
451 private boolean isSemiWeak() {
452 for (int i = 0; i < 12; i++){
453 if (Arrays.equals(DES1KeySpec.SEMI_WEAK_KEYS[i], this.key)) {
454 return true;
455 }
456 }
457
458 return false;
459 }
460 }
461
|
DES1KeySpec |
|