Source code: cryptix/jce/provider/cipher/SKIPJACK.java
1 /* $Id: SKIPJACK.java,v 1.5 2000/02/10 01:31:42 gelderen Exp $
2 *
3 * Copyright (C) 1995-2000 The Cryptix Foundation Limited.
4 * All rights reserved.
5 *
6 * Use, modification, copying and distribution of this software is subject
7 * the terms and conditions of the Cryptix General Licence. You should have
8 * received a copy of the Cryptix General Licence along with this library;
9 * if not, you can download a copy from http://www.cryptix.org/ .
10 */
11 package cryptix.jce.provider.cipher;
12
13
14 import java.security.InvalidKeyException;
15 import java.security.Key;
16
17
18 /**
19 * SKIPJACK
20 *
21 * @version $Revision: 1.5 $
22 * @author Jeroen C. van Gelderen (gelderen@cryptix.org)
23 */
24 public final class SKIPJACK
25 extends BlockCipher
26 {
27
28 // Constants and static variables
29 //............................................................................
30
31 private static final int
32 BLOCK_SIZE = 8,
33 KEY_LENGTH = 10;
34
35 private static final int F[] =
36 {
37 0xA3, 0xD7, 0x09, 0x83, 0xF8, 0x48, 0xF6, 0xF4,
38 0xB3, 0x21, 0x15, 0x78, 0x99, 0xB1, 0xAF, 0xF9,
39 0xE7, 0x2D, 0x4D, 0x8A, 0xCE, 0x4C, 0xCA, 0x2E,
40 0x52, 0x95, 0xD9, 0x1E, 0x4E, 0x38, 0x44, 0x28,
41 0x0A, 0xDF, 0x02, 0xA0, 0x17, 0xF1, 0x60, 0x68,
42 0x12, 0xB7, 0x7A, 0xC3, 0xE9, 0xFA, 0x3D, 0x53,
43 0x96, 0x84, 0x6B, 0xBA, 0xF2, 0x63, 0x9A, 0x19,
44 0x7C, 0xAE, 0xE5, 0xF5, 0xF7, 0x16, 0x6A, 0xA2,
45 0x39, 0xB6, 0x7B, 0x0F, 0xC1, 0x93, 0x81, 0x1B,
46 0xEE, 0xB4, 0x1A, 0xEA, 0xD0, 0x91, 0x2F, 0xB8,
47 0x55, 0xB9, 0xDA, 0x85, 0x3F, 0x41, 0xBF, 0xE0,
48 0x5A, 0x58, 0x80, 0x5F, 0x66, 0x0B, 0xD8, 0x90,
49 0x35, 0xD5, 0xC0, 0xA7, 0x33, 0x06, 0x65, 0x69,
50 0x45, 0x00, 0x94, 0x56, 0x6D, 0x98, 0x9B, 0x76,
51 0x97, 0xFC, 0xB2, 0xC2, 0xB0, 0xFE, 0xDB, 0x20,
52 0xE1, 0xEB, 0xD6, 0xE4, 0xDD, 0x47, 0x4A, 0x1D,
53 0x42, 0xED, 0x9E, 0x6E, 0x49, 0x3C, 0xCD, 0x43,
54 0x27, 0xD2, 0x07, 0xD4, 0xDE, 0xC7, 0x67, 0x18,
55 0x89, 0xCB, 0x30, 0x1F, 0x8D, 0xC6, 0x8F, 0xAA,
56 0xC8, 0x74, 0xDC, 0xC9, 0x5D, 0x5C, 0x31, 0xA4,
57 0x70, 0x88, 0x61, 0x2C, 0x9F, 0x0D, 0x2B, 0x87,
58 0x50, 0x82, 0x54, 0x64, 0x26, 0x7D, 0x03, 0x40,
59 0x34, 0x4B, 0x1C, 0x73, 0xD1, 0xC4, 0xFD, 0x3B,
60 0xCC, 0xFB, 0x7F, 0xAB, 0xE6, 0x3E, 0x5B, 0xA5,
61 0xAD, 0x04, 0x23, 0x9C, 0x14, 0x51, 0x22, 0xF0,
62 0x29, 0x79, 0x71, 0x7E, 0xFF, 0x8C, 0x0E, 0xE2,
63 0x0C, 0xEF, 0xBC, 0x72, 0x75, 0x6F, 0x37, 0xA1,
64 0xEC, 0xD3, 0x8E, 0x62, 0x8B, 0x86, 0x10, 0xE8,
65 0x08, 0x77, 0x11, 0xBE, 0x92, 0x4F, 0x24, 0xC5,
66 0x32, 0x36, 0x9D, 0xCF, 0xF3, 0xA6, 0xBB, 0xAC,
67 0x5E, 0x6C, 0xA9, 0x13, 0x57, 0x25, 0xB5, 0xE3,
68 0xBD, 0xA8, 0x3A, 0x01, 0x05, 0x59, 0x2A, 0x46
69 };
70
71
72 // Instance variables
73 //............................................................................
74
75 /**
76 * Twelf-byte array of subkeys. It's 12 to save on modulus operations.
77 * The last 2 bytes must be equal to the first two bytes.
78 */
79 private final int[] K = new int[12];
80
81 /** We are in decrypt mode */
82 private boolean decrypt;
83
84
85 // Constructor
86 //............................................................................
87
88 public SKIPJACK()
89 {
90 super(BLOCK_SIZE);
91 }
92
93
94 // Implementation of abstract methods
95 //............................................................................
96
97 protected void coreInit(Key key, boolean decrypt)
98 throws InvalidKeyException
99 {
100 byte[] userkey = key.getEncoded();
101 if( userkey == null )
102 throw new InvalidKeyException("Null user key");
103
104 if( userkey.length != KEY_LENGTH )
105 throw new InvalidKeyException("Invalid user key length");
106
107 for( int i=0; i<K.length; i++)
108 K[i] = userkey[i%KEY_LENGTH]&0xFF;
109
110 this.decrypt = decrypt;
111 }
112
113
114 protected void coreCrypt(byte[] in, int inOffset, byte[] out, int outOffset)
115 {
116 if(decrypt)
117 blockDecrypt(in, inOffset, out, outOffset);
118 else
119 blockEncrypt(in, inOffset, out, outOffset);
120 }
121
122
123 // Private parts
124 //............................................................................
125
126 /**
127 * Encrypt a single, 8-byte block. Input and output may overlap.
128 */
129 private final void blockEncrypt(byte[] in, int inOffset, byte[] out, int outOffset)
130 {
131 int w1 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
132 int w2 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
133 int w3 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
134 int w4 = (in[inOffset++]&0xFF) << 8 | (in[inOffset ]&0xFF);
135
136 // A
137 w1 = G(w1, 0); w4 ^= w1 ^ 1;
138 w4 = G(w4, 4); w3 ^= w4 ^ 2;
139 w3 = G(w3, 8); w2 ^= w3 ^ 3;
140 w2 = G(w2, 2); w1 ^= w2 ^ 4;
141 w1 = G(w1, 6); w4 ^= w1 ^ 5;
142 w4 = G(w4, 0); w3 ^= w4 ^ 6;
143 w3 = G(w3, 4); w2 ^= w3 ^ 7;
144 w2 = G(w2, 8); w1 ^= w2 ^ 8;
145 // B
146 w2 ^= w1 ^ 9; w1 = G(w1, 2);
147 w1 ^= w4 ^ 10; w4 = G(w4, 6);
148 w4 ^= w3 ^ 11; w3 = G(w3, 0);
149 w3 ^= w2 ^ 12; w2 = G(w2, 4);
150 w2 ^= w1 ^ 13; w1 = G(w1, 8);
151 w1 ^= w4 ^ 14; w4 = G(w4, 2);
152 w4 ^= w3 ^ 15; w3 = G(w3, 6);
153 w3 ^= w2 ^ 16; w2 = G(w2, 0);
154 // A
155 w1 = G(w1, 4); w4 ^= w1 ^ 17;
156 w4 = G(w4, 8); w3 ^= w4 ^ 18;
157 w3 = G(w3, 2); w2 ^= w3 ^ 19;
158 w2 = G(w2, 6); w1 ^= w2 ^ 20;
159 w1 = G(w1, 0); w4 ^= w1 ^ 21;
160 w4 = G(w4, 4); w3 ^= w4 ^ 22;
161 w3 = G(w3, 8); w2 ^= w3 ^ 23;
162 w2 = G(w2, 2); w1 ^= w2 ^ 24;
163 // B
164 w2 ^= w1 ^ 25; w1 = G(w1, 6);
165 w1 ^= w4 ^ 26; w4 = G(w4, 0);
166 w4 ^= w3 ^ 27; w3 = G(w3, 4);
167 w3 ^= w2 ^ 28; w2 = G(w2, 8);
168 w2 ^= w1 ^ 29; w1 = G(w1, 2);
169 w1 ^= w4 ^ 30; w4 = G(w4, 6);
170 w4 ^= w3 ^ 31; w3 = G(w3, 0);
171 w3 ^= w2 ^ 32; w2 = G(w2, 4);
172
173 out[outOffset++] = (byte)(w1 >>> 8);
174 out[outOffset++] = (byte)(w1 );
175 out[outOffset++] = (byte)(w2 >>> 8);
176 out[outOffset++] = (byte)(w2 );
177 out[outOffset++] = (byte)(w3 >>> 8);
178 out[outOffset++] = (byte)(w3 );
179 out[outOffset++] = (byte)(w4 >>> 8);
180 out[outOffset ] = (byte)(w4 );
181 }
182
183
184 /** G-function used by blockEncrypt */
185 private final int G(int in, int counter)
186 {
187 int low = (in & 0x000000FF);
188 int high = (in ) >>> 8;
189
190 high ^= F[low ^ K[counter ]];
191 low ^= F[high ^ K[counter+1]];
192 high ^= F[low ^ K[counter+2]];
193 low ^= F[high ^ K[counter+3]];
194
195 return (high << 8) | low;
196 }
197
198
199 /**
200 * Decrypt a single block. Input and output may overlap.
201 */
202 private final void blockDecrypt(byte[] in, int inOffset, byte[] out, int outOffset)
203 {
204 int w1 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
205 int w2 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
206 int w3 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
207 int w4 = (in[inOffset++]&0xFF) << 8 | (in[inOffset ]&0xFF);
208
209 // B-1
210 w2 = GINV(w2, 7); w3 ^= w2 ^ 32;
211 w3 = GINV(w3, 3); w4 ^= w3 ^ 31;
212 w4 = GINV(w4, 9); w1 ^= w4 ^ 30;
213 w1 = GINV(w1, 5); w2 ^= w1 ^ 29;
214 w2 = GINV(w2, 11); w3 ^= w2 ^ 28;
215 w3 = GINV(w3, 7); w4 ^= w3 ^ 27;
216 w4 = GINV(w4, 3); w1 ^= w4 ^ 26;
217 w1 = GINV(w1, 9); w2 ^= w1 ^ 25;
218 // A-1
219 w1 ^= w2 ^ 24; w2 = GINV(w2, 5);
220 w2 ^= w3 ^ 23; w3 = GINV(w3, 11);
221 w3 ^= w4 ^ 22; w4 = GINV(w4, 7);
222 w4 ^= w1 ^ 21; w1 = GINV(w1, 3);
223 w1 ^= w2 ^ 20; w2 = GINV(w2, 9);
224 w2 ^= w3 ^ 19; w3 = GINV(w3, 5);
225 w3 ^= w4 ^ 18; w4 = GINV(w4, 11);
226 w4 ^= w1 ^ 17; w1 = GINV(w1, 7);
227 // B-1
228 w2 = GINV(w2, 3); w3 ^= w2 ^ 16;
229 w3 = GINV(w3, 9); w4 ^= w3 ^ 15;
230 w4 = GINV(w4, 5); w1 ^= w4 ^ 14;
231 w1 = GINV(w1, 11); w2 ^= w1 ^ 13;
232 w2 = GINV(w2, 7); w3 ^= w2 ^ 12;
233 w3 = GINV(w3, 3); w4 ^= w3 ^ 11;
234 w4 = GINV(w4, 9); w1 ^= w4 ^ 10;
235 w1 = GINV(w1, 5); w2 ^= w1 ^ 9;
236 // A-1
237 w1 ^= w2 ^ 8; w2 = GINV(w2, 11);
238 w2 ^= w3 ^ 7; w3 = GINV(w3, 7);
239 w3 ^= w4 ^ 6; w4 = GINV(w4, 3);
240 w4 ^= w1 ^ 5; w1 = GINV(w1, 9);
241 w1 ^= w2 ^ 4; w2 = GINV(w2, 5);
242 w2 ^= w3 ^ 3; w3 = GINV(w3, 11);
243 w3 ^= w4 ^ 2; w4 = GINV(w4, 7);
244 w4 ^= w1 ^ 1; w1 = GINV(w1, 3);
245
246 out[outOffset++] = (byte)(w1 >>> 8);
247 out[outOffset++] = (byte)(w1 );
248 out[outOffset++] = (byte)(w2 >>> 8);
249 out[outOffset++] = (byte)(w2 );
250 out[outOffset++] = (byte)(w3 >>> 8);
251 out[outOffset++] = (byte)(w3 );
252 out[outOffset++] = (byte)(w4 >>> 8);
253 out[outOffset ] = (byte)(w4 );
254
255 }
256
257
258 /** G-inverse function used by blockDecrypt */
259 private final int GINV(int in, int counter)
260 {
261 int low = (in & 0x000000FF);
262 int high = (in ) >>> 8;
263
264 low ^= F[high ^ K[counter ]];
265 high ^= F[low ^ K[counter-1]];
266 low ^= F[high ^ K[counter-2]];
267 high ^= F[low ^ K[counter-3]];
268
269 return (high << 8) | low;
270 }
271 }