1package org.bouncycastle.crypto.params;
2
3public class DESParameters
4    extends KeyParameter
5{
6    public DESParameters(
7        byte[]  key)
8    {
9        super(key);
10
11        if (isWeakKey(key, 0))
12        {
13            throw new IllegalArgumentException("attempt to create weak DES key");
14        }
15    }
16
17    /*
18     * DES Key length in bytes.
19     */
20    static public final int DES_KEY_LENGTH = 8;
21
22    /*
23     * Table of weak and semi-weak keys taken from Schneier pp281
24     */
25    static private final int N_DES_WEAK_KEYS = 16;
26
27    static private byte[] DES_weak_keys =
28    {
29        /* weak keys */
30        (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
31        (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
32        (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
33        (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
34
35        /* semi-weak keys */
36        (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
37        (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
38        (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
39        (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
40        (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
41        (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
42        (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
43        (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
44        (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
45        (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
46        (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
47        (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
48    };
49
50    /**
51     * DES has 16 weak keys.  This method will check
52     * if the given DES key material is weak or semi-weak.
53     * Key material that is too short is regarded as weak.
54     * <p>
55     * See <a href="http://www.counterpane.com/applied.html">"Applied
56     * Cryptography"</a> by Bruce Schneier for more information.
57     *
58     * @return true if the given DES key material is weak or semi-weak,
59     *     false otherwise.
60     */
61    public static boolean isWeakKey(
62        byte[] key,
63        int offset)
64    {
65        if (key.length - offset < DES_KEY_LENGTH)
66        {
67            throw new IllegalArgumentException("key material too short.");
68        }
69
70        nextkey: for (int i = 0; i < N_DES_WEAK_KEYS; i++)
71        {
72            for (int j = 0; j < DES_KEY_LENGTH; j++)
73            {
74                if (key[j + offset] != DES_weak_keys[i * DES_KEY_LENGTH + j])
75                {
76                    continue nextkey;
77                }
78            }
79
80            return true;
81        }
82        return false;
83    }
84
85    /**
86     * DES Keys use the LSB as the odd parity bit.  This can
87     * be used to check for corrupt keys.
88     *
89     * @param bytes the byte array to set the parity on.
90     */
91    public static void setOddParity(
92        byte[] bytes)
93    {
94        for (int i = 0; i < bytes.length; i++)
95        {
96            int b = bytes[i];
97            bytes[i] = (byte)((b & 0xfe) |
98                            ((((b >> 1) ^
99                            (b >> 2) ^
100                            (b >> 3) ^
101                            (b >> 4) ^
102                            (b >> 5) ^
103                            (b >> 6) ^
104                            (b >> 7)) ^ 0x01) & 0x01));
105        }
106    }
107}
108