001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.util.crypto.params;
019    
020    public class DESParameters
021        extends KeyParameter
022    {
023        public DESParameters(
024            byte[]  key)
025        {
026            super(key);
027    
028            if (isWeakKey(key, 0))
029            {
030                throw new IllegalArgumentException("attempt to create weak DES key");
031            }
032        }
033    
034        /*
035         * DES Key length in bytes.
036         */
037        static public final int DES_KEY_LENGTH = 8;
038    
039        /*
040         * Table of weak and semi-weak keys taken from Schneier pp281
041         */
042        static private final int N_DES_WEAK_KEYS = 16;
043    
044        static private byte[] DES_weak_keys =
045        {
046            /* weak keys */
047            (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
048            (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
049            (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
050            (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
051    
052            /* semi-weak keys */
053            (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
054            (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
055            (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
056            (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
057            (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
058            (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
059            (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
060            (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
061            (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
062            (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
063            (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
064            (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
065        };
066    
067        /**
068         * DES has 16 weak keys.  This method will check
069         * if the given DES key material is weak or semi-weak.
070         * Key material that is too short is regarded as weak.
071         * <p>
072         * See <a href="http://www.counterpane.com/applied.html">"Applied
073         * Cryptography"</a> by Bruce Schneier for more information.
074         *
075         * @return true if the given DES key material is weak or semi-weak,
076         *     false otherwise.
077         */
078        public static boolean isWeakKey(
079            byte[] key,
080            int offset)
081        {
082            if (key.length - offset < DES_KEY_LENGTH)
083            {
084                throw new IllegalArgumentException("key material too short.");
085            }
086    
087            nextkey: for (int i = 0; i < N_DES_WEAK_KEYS; i++)
088            {
089                for (int j = 0; j < DES_KEY_LENGTH; j++)
090                {
091                    if (key[j + offset] != DES_weak_keys[i * DES_KEY_LENGTH + j])
092                    {
093                        continue nextkey;
094                    }
095                }
096    
097                return true;
098            }
099            return false;
100        }
101    
102        /**
103         * DES Keys use the LSB as the odd parity bit.  This can
104         * be used to check for corrupt keys.
105         *
106         * @param bytes the byte array to set the parity on.
107         */
108        public static void setOddParity(
109            byte[] bytes)
110        {
111            for (int i = 0; i < bytes.length; i++)
112            {
113                int b = bytes[i];
114                bytes[i] = (byte)((b & 0xfe) |
115                                ((((b >> 1) ^
116                                (b >> 2) ^
117                                (b >> 3) ^
118                                (b >> 4) ^
119                                (b >> 5) ^
120                                (b >> 6) ^
121                                (b >> 7)) ^ 0x01) & 0x01));
122            }
123        }
124    }