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&uuml;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