Home | History | Annotate | Download | only in spec
      1 /*
      2  * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 package javax.crypto.spec;
     27 
     28 import java.security.InvalidKeyException;
     29 
     30 /**
     31  * This class specifies a DES key.
     32  *
     33  * @author Jan Luehe
     34  *
     35  * @since 1.4
     36  */
     37 public class DESKeySpec implements java.security.spec.KeySpec {
     38 
     39     /**
     40      * The constant which defines the length of a DES key in bytes.
     41      */
     42     public static final int DES_KEY_LEN = 8;
     43 
     44     private byte[] key;
     45 
     46     /*
     47      * Weak/semi-weak keys copied from FIPS 74.
     48      *
     49      * "...The first 6 keys have duals different than themselves, hence
     50      * each is both a key and a dual giving 12 keys with duals. The last
     51      * four keys equal their duals, and are called self-dual keys..."
     52      *
     53      * 1.   E001E001F101F101    01E001E001F101F1
     54      * 2.   FE1FFE1FFEOEFEOE    1FFE1FFEOEFEOEFE
     55      * 3.   E01FE01FF10EF10E    1FE01FEOOEF10EF1
     56      * 4.   01FE01FE01FE01FE    FE01FE01FE01FE01
     57      * 5.   011F011F010E010E    1F011F010E010E01
     58      * 6.   E0FEE0FEF1FEF1FE    FEE0FEE0FEF1FEF1
     59      * 7.   0101010101010101    0101010101010101
     60      * 8.   FEFEFEFEFEFEFEFE    FEFEFEFEFEFEFEFE
     61      * 9.   E0E0E0E0F1F1F1F1    E0E0E0E0F1F1F1F1
     62      * 10.  1F1F1F1F0E0E0E0E    1F1F1F1F0E0E0E0E
     63      */
     64     private static final byte[][] WEAK_KEYS = {
     65 
     66         { (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,
     67           (byte)0x01, (byte)0x01, (byte)0x01 },
     68 
     69         { (byte)0xFE, (byte)0xFE, (byte)0xFE, (byte)0xFE, (byte)0xFE,
     70           (byte)0xFE, (byte)0xFE, (byte)0xFE },
     71 
     72         { (byte)0x1F, (byte)0x1F, (byte)0x1F, (byte)0x1F, (byte)0x0E,
     73           (byte)0x0E, (byte)0x0E, (byte)0x0E },
     74 
     75         { (byte)0xE0, (byte)0xE0, (byte)0xE0, (byte)0xE0, (byte)0xF1,
     76           (byte)0xF1, (byte)0xF1, (byte)0xF1 },
     77 
     78         { (byte)0x01, (byte)0xFE, (byte)0x01, (byte)0xFE, (byte)0x01,
     79           (byte)0xFE, (byte)0x01, (byte)0xFE },
     80 
     81         { (byte)0x1F, (byte)0xE0, (byte)0x1F, (byte)0xE0, (byte)0x0E,
     82           (byte)0xF1, (byte)0x0E, (byte)0xF1 },
     83 
     84         { (byte)0x01, (byte)0xE0, (byte)0x01, (byte)0xE0, (byte)0x01,
     85           (byte)0xF1, (byte)0x01, (byte)0xF1 },
     86 
     87         { (byte)0x1F, (byte)0xFE, (byte)0x1F, (byte)0xFE, (byte)0x0E,
     88           (byte)0xFE, (byte)0x0E, (byte)0xFE },
     89 
     90         { (byte)0x01, (byte)0x1F, (byte)0x01, (byte)0x1F, (byte)0x01,
     91           (byte)0x0E, (byte)0x01, (byte)0x0E },
     92 
     93         { (byte)0xE0, (byte)0xFE, (byte)0xE0, (byte)0xFE, (byte)0xF1,
     94           (byte)0xFE, (byte)0xF1, (byte)0xFE },
     95 
     96         { (byte)0xFE, (byte)0x01, (byte)0xFE, (byte)0x01, (byte)0xFE,
     97           (byte)0x01, (byte)0xFE, (byte)0x01 },
     98 
     99         { (byte)0xE0, (byte)0x1F, (byte)0xE0, (byte)0x1F, (byte)0xF1,
    100           (byte)0x0E, (byte)0xF1, (byte)0x0E },
    101 
    102         { (byte)0xE0, (byte)0x01, (byte)0xE0, (byte)0x01, (byte)0xF1,
    103           (byte)0x01, (byte)0xF1, (byte)0x01 },
    104 
    105         { (byte)0xFE, (byte)0x1F, (byte)0xFE, (byte)0x1F, (byte)0xFE,
    106           (byte)0x0E, (byte)0xFE, (byte)0x0E },
    107 
    108         { (byte)0x1F, (byte)0x01, (byte)0x1F, (byte)0x01, (byte)0x0E,
    109           (byte)0x01, (byte)0x0E, (byte)0x01 },
    110 
    111         { (byte)0xFE, (byte)0xE0, (byte)0xFE, (byte)0xE0, (byte)0xFE,
    112           (byte)0xF1, (byte)0xFE, (byte)0xF1 }
    113     };
    114 
    115     /**
    116      * Creates a DESKeySpec object using the first 8 bytes in
    117      * <code>key</code> as the key material for the DES key.
    118      *
    119      * <p> The bytes that constitute the DES key are those between
    120      * <code>key[0]</code> and <code>key[7]</code> inclusive.
    121      *
    122      * @param key the buffer with the DES key material. The first 8 bytes
    123      * of the buffer are copied to protect against subsequent modification.
    124      *
    125      * @exception NullPointerException if the given key material is
    126      * <code>null</code>
    127      * @exception InvalidKeyException if the given key material is shorter
    128      * than 8 bytes.
    129      */
    130     public DESKeySpec(byte[] key) throws InvalidKeyException {
    131         this(key, 0);
    132     }
    133 
    134     /**
    135      * Creates a DESKeySpec object using the first 8 bytes in
    136      * <code>key</code>, beginning at <code>offset</code> inclusive,
    137      * as the key material for the DES key.
    138      *
    139      * <p> The bytes that constitute the DES key are those between
    140      * <code>key[offset]</code> and <code>key[offset+7]</code> inclusive.
    141      *
    142      * @param key the buffer with the DES key material. The first 8 bytes
    143      * of the buffer beginning at <code>offset</code> inclusive are copied
    144      * to protect against subsequent modification.
    145      * @param offset the offset in <code>key</code>, where the DES key
    146      * material starts.
    147      *
    148      * @exception NullPointerException if the given key material is
    149      * <code>null</code>
    150      * @exception InvalidKeyException if the given key material, starting at
    151      * <code>offset</code> inclusive, is shorter than 8 bytes.
    152      */
    153     public DESKeySpec(byte[] key, int offset) throws InvalidKeyException {
    154         if (key.length - offset < DES_KEY_LEN) {
    155             throw new InvalidKeyException("Wrong key size");
    156         }
    157         this.key = new byte[DES_KEY_LEN];
    158         System.arraycopy(key, offset, this.key, 0, DES_KEY_LEN);
    159     }
    160 
    161     /**
    162      * Returns the DES key material.
    163      *
    164      * @return the DES key material. Returns a new array
    165      * each time this method is called.
    166      */
    167     public byte[] getKey() {
    168         return (byte[])this.key.clone();
    169     }
    170 
    171     /**
    172      * Checks if the given DES key material, starting at <code>offset</code>
    173      * inclusive, is parity-adjusted.
    174      *
    175      * @param key the buffer with the DES key material.
    176      * @param offset the offset in <code>key</code>, where the DES key
    177      * material starts.
    178      *
    179      * @return true if the given DES key material is parity-adjusted, false
    180      * otherwise.
    181      *
    182      * @exception InvalidKeyException if the given key material is
    183      * <code>null</code>, or starting at <code>offset</code> inclusive, is
    184      * shorter than 8 bytes.
    185      */
    186     public static boolean isParityAdjusted(byte[] key, int offset)
    187         throws InvalidKeyException {
    188             if (key == null) {
    189                 throw new InvalidKeyException("null key");
    190             }
    191             if (key.length - offset < DES_KEY_LEN) {
    192                 throw new InvalidKeyException("Wrong key size");
    193             }
    194 
    195             for (int i = 0; i < DES_KEY_LEN; i++) {
    196                 int k = Integer.bitCount(key[offset++] & 0xff);
    197                 if ((k & 1) == 0) {
    198                     return false;
    199                 }
    200             }
    201 
    202             return true;
    203     }
    204 
    205     /**
    206      * Checks if the given DES key material is weak or semi-weak.
    207      *
    208      * @param key the buffer with the DES key material.
    209      * @param offset the offset in <code>key</code>, where the DES key
    210      * material starts.
    211      *
    212      * @return true if the given DES key material is weak or semi-weak, false
    213      * otherwise.
    214      *
    215      * @exception InvalidKeyException if the given key material is
    216      * <code>null</code>, or starting at <code>offset</code> inclusive, is
    217      * shorter than 8 bytes.
    218      */
    219     public static boolean isWeak(byte[] key, int offset)
    220         throws InvalidKeyException {
    221         if (key == null) {
    222             throw new InvalidKeyException("null key");
    223         }
    224         if (key.length - offset < DES_KEY_LEN) {
    225             throw new InvalidKeyException("Wrong key size");
    226         }
    227         for (int i = 0; i < WEAK_KEYS.length; i++) {
    228             boolean found = true;
    229             for (int j = 0; j < DES_KEY_LEN && found == true; j++) {
    230                 if (WEAK_KEYS[i][j] != key[j+offset]) {
    231                     found = false;
    232                 }
    233             }
    234             if (found == true) {
    235                 return found;
    236             }
    237         }
    238         return false;
    239     }
    240 }
    241