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 18package javax.crypto.spec; 19 20import java.security.InvalidKeyException; 21import java.security.spec.KeySpec; 22 23import org.apache.harmony.crypto.internal.nls.Messages; 24 25/** 26 * The key specification for a DES key. 27 */ 28public class DESKeySpec implements KeySpec { 29 30 /** 31 * The length of a DES key in bytes. 32 */ 33 public static final int DES_KEY_LEN = 8; 34 35 private final byte[] key; 36 37 // DES weak and semi-weak keys 38 // Got from: 39 // FIP PUB 74 40 // FEDERAL INFORMATION PROCESSING STANDARDS PUBLICATION 1981 41 // GUIDELINES FOR IMPLEMENTING AND USING THE NBS DATA ENCRYPTION STANDARD 42 // http://www.dice.ucl.ac.be/crypto/standards/fips/fip74/fip74-1.pdf 43 private static final byte[][] SEMIWEAKS = { 44 {(byte) 0xE0, (byte) 0x01, (byte) 0xE0, (byte) 0x01, 45 (byte) 0xF1, (byte) 0x01, (byte) 0xF1, (byte) 0x01}, 46 47 {(byte) 0x01, (byte) 0xE0, (byte) 0x01, (byte) 0xE0, 48 (byte) 0x01, (byte) 0xF1, (byte) 0x01, (byte) 0xF1}, 49 50 {(byte) 0xFE, (byte) 0x1F, (byte) 0xFE, (byte) 0x1F, 51 (byte) 0xFE, (byte) 0x0E, (byte) 0xFE, (byte) 0x0E}, 52 53 {(byte) 0x1F, (byte) 0xFE, (byte) 0x1F, (byte) 0xFE, 54 (byte) 0x0E, (byte) 0xFE, (byte) 0x0E, (byte) 0xFE}, 55 56 {(byte) 0xE0, (byte) 0x1F, (byte) 0xE0, (byte) 0x1F, 57 (byte) 0xF1, (byte) 0x0E, (byte) 0xF1, (byte) 0x0E}, 58 59 {(byte) 0x1F, (byte) 0xE0, (byte) 0x1F, (byte) 0xE0, 60 (byte) 0x0E, (byte) 0xF1, (byte) 0x0E, (byte) 0xF1}, 61 62 {(byte) 0x01, (byte) 0xFE, (byte) 0x01, (byte) 0xFE, 63 (byte) 0x01, (byte) 0xFE, (byte) 0x01, (byte) 0xFE}, 64 65 {(byte) 0xFE, (byte) 0x01, (byte) 0xFE, (byte) 0x01, 66 (byte) 0xFE, (byte) 0x01, (byte) 0xFE, (byte) 0x01}, 67 68 {(byte) 0x01, (byte) 0x1F, (byte) 0x01, (byte) 0x1F, 69 (byte) 0x01, (byte) 0x0E, (byte) 0x01, (byte) 0x0E}, 70 71 {(byte) 0x1F, (byte) 0x01, (byte) 0x1F, (byte) 0x01, 72 (byte) 0x0E, (byte) 0x01, (byte) 0x0E, (byte) 0x01}, 73 74 {(byte) 0xE0, (byte) 0xFE, (byte) 0xE0, (byte) 0xFE, 75 (byte) 0xF1, (byte) 0xFE, (byte) 0xF1, (byte) 0xFE}, 76 77 {(byte) 0xFE, (byte) 0xE0, (byte) 0xFE, (byte) 0xE0, 78 (byte) 0xFE, (byte) 0xF1, (byte) 0xFE, (byte) 0xF1}, 79 80 {(byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, 81 (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01}, 82 83 {(byte) 0xFE, (byte) 0xFE, (byte) 0xFE, (byte) 0xFE, 84 (byte) 0xFE, (byte) 0xFE, (byte) 0xFE, (byte) 0xFE}, 85 86 {(byte) 0xE0, (byte) 0xE0, (byte) 0xE0, (byte) 0xE0, 87 (byte) 0xF1, (byte) 0xF1, (byte) 0xF1, (byte) 0xF1}, 88 89 {(byte) 0x1F, (byte) 0x1F, (byte) 0x1F, (byte) 0x1F, 90 (byte) 0x0E, (byte) 0x0E, (byte) 0x0E, (byte) 0x0E}, 91 92 }; 93 94 /** 95 * Creates a new <code>DESKeySpec</code> from the first 8 bytes of the 96 * specified key data. 97 * 98 * @param key 99 * the key data. 100 * @throws InvalidKeyException 101 * if the length of the specified key data is less than 8. 102 */ 103 public DESKeySpec(byte[] key) throws InvalidKeyException { 104 this(key, 0); 105 } 106 107 /** 108 * Creates a new <code>DESKeySpec</code> from the first 8 bytes of the 109 * specified key data starting at <code>offset</code>. 110 * 111 * @param key 112 * the key data 113 * @param offset 114 * the offset to start at. 115 * @throws InvalidKeyException 116 * if the length of the specified key data starting at offset is 117 * less than 8. 118 */ 119 public DESKeySpec(byte[] key, int offset) 120 throws InvalidKeyException { 121 if (key == null) { 122 throw new NullPointerException(Messages.getString("crypto.2F")); //$NON-NLS-1$ 123 } 124 if (key.length - offset < DES_KEY_LEN) { 125 throw new InvalidKeyException( 126 Messages.getString("crypto.40")); //$NON-NLS-1$ 127 } 128 this.key = new byte[DES_KEY_LEN]; 129 System.arraycopy(key, offset, this.key, 0, DES_KEY_LEN); 130 } 131 132 /** 133 * Returns a copy of the key. 134 * 135 * @return a copy of the key. 136 */ 137 public byte[] getKey() { 138 byte[] result = new byte[DES_KEY_LEN]; 139 System.arraycopy(this.key, 0, result, 0, DES_KEY_LEN); 140 return result; 141 } 142 143 /** 144 * Returns whether the specified key data starting at <code>offset</code> is 145 * <i>parity-adjusted</i>. 146 * 147 * @param key 148 * the key data. 149 * @param offset 150 * the offset to start checking at. 151 * @return {@code true} if the specified key data is parity-adjusted, 152 * {@code false} otherwise. 153 * @throws InvalidKeyException 154 * if the length of the key data starting at offset is less than 155 * 8, or the key is null. 156 */ 157 public static boolean isParityAdjusted(byte[] key, int offset) 158 throws InvalidKeyException { 159 if (key == null) { 160 throw new InvalidKeyException(Messages.getString("crypto.2F")); //$NON-NLS-1$ 161 } 162 if (key.length - offset < DES_KEY_LEN) { 163 throw new InvalidKeyException( 164 Messages.getString("crypto.40")); //$NON-NLS-1$ 165 } 166 167 int byteKey = 0; 168 169 for (int i = offset; i < DES_KEY_LEN; i++) { 170 byteKey = key[i]; 171 172 byteKey ^= byteKey >> 1; 173 byteKey ^= byteKey >> 2; 174 byteKey ^= byteKey >> 4; 175 176 if ((byteKey & 1) == 0) { 177 return false; 178 } 179 } 180 return true; 181 } 182 183 /** 184 * Returns whether the specified key data starting at <code>offset</code> is 185 * weak or semi-weak. 186 * 187 * @param key 188 * the key data. 189 * @param offset 190 * the offset to start checking at. 191 * @return {@code true} if the specified key data is weak or semi-weak. 192 * @throws InvalidKeyException 193 * if the length of the key data starting at offset is less than 194 * 8, or it is null. 195 */ 196 public static boolean isWeak(byte[] key, int offset) 197 throws InvalidKeyException { 198 if (key == null) { 199 throw new InvalidKeyException(Messages.getString("crypto.2F")); //$NON-NLS-1$ 200 } 201 if (key.length - offset < DES_KEY_LEN) { 202 throw new InvalidKeyException( 203 Messages.getString("crypto.40")); //$NON-NLS-1$ 204 } 205 I: 206 for (int i=0; i<SEMIWEAKS.length; i++) { 207 for (int j=0; j<DES_KEY_LEN; j++) { 208 if (SEMIWEAKS[i][j] != key[offset+j]) { 209 continue I; 210 } 211 } 212 return true; 213 } 214 return false; 215 } 216} 217 218