Home | History | Annotate | Download | only in spec
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package javax.crypto.spec;
     19 
     20 import java.security.InvalidKeyException;
     21 import java.security.spec.KeySpec;
     22 
     23 /**
     24  * The key specification for a DES key.
     25  */
     26 public class DESKeySpec implements KeySpec {
     27 
     28     /**
     29      * The length of a DES key in bytes.
     30      */
     31     public static final int DES_KEY_LEN = 8;
     32 
     33     private final byte[] key;
     34 
     35     // DES weak and semi-weak keys
     36     // Got from:
     37     // FIP PUB 74
     38     // FEDERAL INFORMATION PROCESSING STANDARDS PUBLICATION 1981
     39     // GUIDELINES FOR IMPLEMENTING AND USING THE NBS DATA ENCRYPTION STANDARD
     40     // http://www.dice.ucl.ac.be/crypto/standards/fips/fip74/fip74-1.pdf
     41     private static final byte[][] SEMIWEAKS = {
     42                 {(byte) 0xE0, (byte) 0x01, (byte) 0xE0, (byte) 0x01,
     43                  (byte) 0xF1, (byte) 0x01, (byte) 0xF1, (byte) 0x01},
     44 
     45                 {(byte) 0x01, (byte) 0xE0, (byte) 0x01, (byte) 0xE0,
     46                  (byte) 0x01, (byte) 0xF1, (byte) 0x01, (byte) 0xF1},
     47 
     48                 {(byte) 0xFE, (byte) 0x1F, (byte) 0xFE, (byte) 0x1F,
     49                  (byte) 0xFE, (byte) 0x0E, (byte) 0xFE, (byte) 0x0E},
     50 
     51                 {(byte) 0x1F, (byte) 0xFE, (byte) 0x1F, (byte) 0xFE,
     52                  (byte) 0x0E, (byte) 0xFE, (byte) 0x0E, (byte) 0xFE},
     53 
     54                 {(byte) 0xE0, (byte) 0x1F, (byte) 0xE0, (byte) 0x1F,
     55                  (byte) 0xF1, (byte) 0x0E, (byte) 0xF1, (byte) 0x0E},
     56 
     57                 {(byte) 0x1F, (byte) 0xE0, (byte) 0x1F, (byte) 0xE0,
     58                  (byte) 0x0E, (byte) 0xF1, (byte) 0x0E, (byte) 0xF1},
     59 
     60                 {(byte) 0x01, (byte) 0xFE, (byte) 0x01, (byte) 0xFE,
     61                  (byte) 0x01, (byte) 0xFE, (byte) 0x01, (byte) 0xFE},
     62 
     63                 {(byte) 0xFE, (byte) 0x01, (byte) 0xFE, (byte) 0x01,
     64                  (byte) 0xFE, (byte) 0x01, (byte) 0xFE, (byte) 0x01},
     65 
     66                 {(byte) 0x01, (byte) 0x1F, (byte) 0x01, (byte) 0x1F,
     67                  (byte) 0x01, (byte) 0x0E, (byte) 0x01, (byte) 0x0E},
     68 
     69                 {(byte) 0x1F, (byte) 0x01, (byte) 0x1F, (byte) 0x01,
     70                  (byte) 0x0E, (byte) 0x01, (byte) 0x0E, (byte) 0x01},
     71 
     72                 {(byte) 0xE0, (byte) 0xFE, (byte) 0xE0, (byte) 0xFE,
     73                  (byte) 0xF1, (byte) 0xFE, (byte) 0xF1, (byte) 0xFE},
     74 
     75                 {(byte) 0xFE, (byte) 0xE0, (byte) 0xFE, (byte) 0xE0,
     76                  (byte) 0xFE, (byte) 0xF1, (byte) 0xFE, (byte) 0xF1},
     77 
     78                 {(byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01,
     79                  (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01},
     80 
     81                 {(byte) 0xFE, (byte) 0xFE, (byte) 0xFE, (byte) 0xFE,
     82                  (byte) 0xFE, (byte) 0xFE, (byte) 0xFE, (byte) 0xFE},
     83 
     84                 {(byte) 0xE0, (byte) 0xE0, (byte) 0xE0, (byte) 0xE0,
     85                  (byte) 0xF1, (byte) 0xF1, (byte) 0xF1, (byte) 0xF1},
     86 
     87                 {(byte) 0x1F, (byte) 0x1F, (byte) 0x1F, (byte) 0x1F,
     88                  (byte) 0x0E, (byte) 0x0E, (byte) 0x0E, (byte) 0x0E},
     89 
     90                 };
     91 
     92     /**
     93      * Creates a new <code>DESKeySpec</code> from the first 8 bytes of the
     94      * specified key data.
     95      *
     96      * @param key
     97      *            the key data.
     98      * @throws InvalidKeyException
     99      *             if the length of the specified key data is less than 8.
    100      */
    101     public DESKeySpec(byte[] key) throws InvalidKeyException {
    102         this(key, 0);
    103     }
    104 
    105     /**
    106      * Creates a new <code>DESKeySpec</code> from the first 8 bytes of the
    107      * specified key data starting at <code>offset</code>.
    108      *
    109      * @param key
    110      *            the key data
    111      * @param offset
    112      *            the offset to start at.
    113      * @throws InvalidKeyException
    114      *             if the length of the specified key data starting at offset is
    115      *             less than 8.
    116      */
    117     public DESKeySpec(byte[] key, int offset) throws InvalidKeyException {
    118         if (key == null) {
    119             throw new NullPointerException("key == null");
    120         }
    121         if (key.length - offset < DES_KEY_LEN) {
    122             throw new InvalidKeyException("key too short");
    123         }
    124         this.key = new byte[DES_KEY_LEN];
    125         System.arraycopy(key, offset, this.key, 0, DES_KEY_LEN);
    126     }
    127 
    128     /**
    129      * Returns a copy of the key.
    130      *
    131      * @return a copy of the key.
    132      */
    133     public byte[] getKey() {
    134         byte[] result = new byte[DES_KEY_LEN];
    135         System.arraycopy(this.key, 0, result, 0, DES_KEY_LEN);
    136         return result;
    137     }
    138 
    139     /**
    140      * Returns whether the specified key data starting at <code>offset</code> is
    141      * <i>parity-adjusted</i>.
    142      *
    143      * @param key
    144      *            the key data.
    145      * @param offset
    146      *            the offset to start checking at.
    147      * @return {@code true} if the specified key data is parity-adjusted,
    148      *            {@code false} otherwise.
    149      * @throws InvalidKeyException
    150      *             if the length of the key data starting at offset is less than
    151      *             8, or the key is null.
    152      */
    153     public static boolean isParityAdjusted(byte[] key, int offset) throws InvalidKeyException {
    154         if (key == null) {
    155             throw new InvalidKeyException("key == null");
    156         }
    157         if (key.length - offset < DES_KEY_LEN) {
    158             throw new InvalidKeyException("key too short");
    159         }
    160 
    161         int byteKey = 0;
    162 
    163         for (int i = offset; i < DES_KEY_LEN; i++) {
    164             byteKey = key[i];
    165 
    166             byteKey ^= byteKey >> 1;
    167             byteKey ^= byteKey >> 2;
    168             byteKey ^= byteKey >> 4;
    169 
    170             if ((byteKey & 1) == 0) {
    171                 return false;
    172             }
    173         }
    174         return true;
    175     }
    176 
    177     /**
    178      * Returns whether the specified key data starting at <code>offset</code> is
    179      * weak or semi-weak.
    180      *
    181      * @param key
    182      *            the key data.
    183      * @param offset
    184      *            the offset to start checking at.
    185      * @return {@code true} if the specified key data is weak or semi-weak.
    186      * @throws InvalidKeyException
    187      *             if the length of the key data starting at offset is less than
    188      *             8, or it is null.
    189      */
    190     public static boolean isWeak(byte[] key, int offset) throws InvalidKeyException {
    191         if (key == null) {
    192             throw new InvalidKeyException("key == null");
    193         }
    194         if (key.length - offset < DES_KEY_LEN) {
    195             throw new InvalidKeyException("key too short");
    196         }
    197         I:
    198         for (int i=0; i<SEMIWEAKS.length; i++) {
    199             for (int j=0; j<DES_KEY_LEN; j++) {
    200                 if (SEMIWEAKS[i][j] != key[offset+j]) {
    201                     continue I;
    202                 }
    203             }
    204             return true;
    205         }
    206         return false;
    207     }
    208 }
    209