1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44:
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50:
51:
67: public final class Khazad
68: extends BaseCipher
69: {
70: private static final Logger log = Logger.getLogger(Khazad.class.getName());
71: private static final int DEFAULT_BLOCK_SIZE = 8;
72: private static final int DEFAULT_KEY_SIZE = 16;
73: private static final int R = 8;
74: private static final String Sd =
75: "\uBA54\u2F74\u53D3\uD24D\u50AC\u8DBF\u7052\u9A4C"
76: + "\uEAD5\u97D1\u3351\u5BA6\uDE48\uA899\uDB32\uB7FC"
77: + "\uE39E\u919B\uE2BB\u416E\uA5CB\u6B95\uA1F3\uB102"
78: + "\uCCC4\u1D14\uC363\uDA5D\u5FDC\u7DCD\u7F5A\u6C5C"
79: + "\uF726\uFFED\uE89D\u6F8E\u19A0\uF089\u0F07\uAFFB"
80: + "\u0815\u0D04\u0164\uDF76\u79DD\u3D16\u3F37\u6D38"
81: + "\uB973\uE935\u5571\u7B8C\u7288\uF62A\u3E5E\u2746"
82: + "\u0C65\u6861\u03C1\u57D6\uD958\uD866\uD73A\uC83C"
83: + "\uFA96\uA798\uECB8\uC7AE\u694B\uABA9\u670A\u47F2"
84: + "\uB522\uE5EE\uBE2B\u8112\u831B\u0E23\uF545\u21CE"
85: + "\u492C\uF9E6\uB628\u1782\u1A8B\uFE8A\u09C9\u874E"
86: + "\uE12E\uE4E0\uEB90\uA41E\u8560\u0025\uF4F1\u940B"
87: + "\uE775\uEF34\u31D4\uD086\u7EAD\uFD29\u303B\u9FF8"
88: + "\uC613\u0605\uC511\u777C\u7A78\u361C\u3959\u1856"
89: + "\uB3B0\u2420\uB292\uA3C0\u4462\u10B4\u8443\u93C2"
90: + "\u4ABD\u8F2D\uBC9C\u6A40\uCFA2\u804F\u1FCA\uAA42";
91: private static final byte[] S = new byte[256];
92: private static final int[] T0 = new int[256];
93: private static final int[] T1 = new int[256];
94: private static final int[] T2 = new int[256];
95: private static final int[] T3 = new int[256];
96: private static final int[] T4 = new int[256];
97: private static final int[] T5 = new int[256];
98: private static final int[] T6 = new int[256];
99: private static final int[] T7 = new int[256];
100: private static final int[][] rc = new int[R + 1][2];
101:
105: private static final byte[] KAT_KEY =
106: Util.toBytesFromString("00000000000000000000000000000100");
107: private static final byte[] KAT_CT = Util.toBytesFromString("A0C86A1BBE2CBF4C");
108:
109: private static Boolean valid;
110:
111: static
112: {
113: long time = System.currentTimeMillis();
114: long ROOT = 0x11d;
115: int i, j;
116: int s, s2, s3, s4, s5, s6, s7, s8, sb;
117: char c;
118: for (i = 0; i < 256; i++)
119: {
120: c = Sd.charAt(i >>> 1);
121: s = ((i & 1) == 0 ? c >>> 8 : c) & 0xFF;
122: S[i] = (byte) s;
123: s2 = s << 1;
124: if (s2 > 0xFF)
125: s2 ^= ROOT;
126: s3 = s2 ^ s;
127: s4 = s2 << 1;
128: if (s4 > 0xFF)
129: s4 ^= ROOT;
130: s5 = s4 ^ s;
131: s6 = s4 ^ s2;
132: s7 = s6 ^ s;
133: s8 = s4 << 1;
134: if (s8 > 0xFF)
135: s8 ^= ROOT;
136: sb = s8 ^ s2 ^ s;
137: T0[i] = s << 24 | s3 << 16 | s4 << 8 | s5;
138: T1[i] = s3 << 24 | s << 16 | s5 << 8 | s4;
139: T2[i] = s4 << 24 | s5 << 16 | s << 8 | s3;
140: T3[i] = s5 << 24 | s4 << 16 | s3 << 8 | s;
141: T4[i] = s6 << 24 | s8 << 16 | sb << 8 | s7;
142: T5[i] = s8 << 24 | s6 << 16 | s7 << 8 | sb;
143: T6[i] = sb << 24 | s7 << 16 | s6 << 8 | s8;
144: T7[i] = s7 << 24 | sb << 16 | s8 << 8 | s6;
145: }
146: for (i = 0, j = 0; i < R + 1; i++)
147: {
148: rc[i][0] = S[j++] << 24
149: | (S[j++] & 0xFF) << 16
150: | (S[j++] & 0xFF) << 8
151: | (S[j++] & 0xFF);
152: rc[i][1] = S[j++] << 24
153: | (S[j++] & 0xFF) << 16
154: | (S[j++] & 0xFF) << 8
155: | (S[j++] & 0xFF);
156: }
157: time = System.currentTimeMillis() - time;
158: if (Configuration.DEBUG)
159: {
160: log.fine("Static data");
161: log.fine("T0[]:");
162: StringBuilder b;
163: for (i = 0; i < 64; i++)
164: {
165: b = new StringBuilder();
166: for (j = 0; j < 4; j++)
167: b.append("0x").append(Util.toString(T0[i * 4 + j])).append(", ");
168: log.fine(b.toString());
169: }
170: log.fine("T1[]:");
171: for (i = 0; i < 64; i++)
172: {
173: b = new StringBuilder();
174: for (j = 0; j < 4; j++)
175: b.append("0x").append(Util.toString(T1[i * 4 + j])).append(", ");
176: log.fine(b.toString());
177: }
178: log.fine("T2[]:");
179: for (i = 0; i < 64; i++)
180: {
181: b = new StringBuilder();
182: for (j = 0; j < 4; j++)
183: b.append("0x").append(Util.toString(T2[i * 4 + j])).append(", ");
184: log.fine(b.toString());
185: }
186: log.fine("T3[]:");
187: for (i = 0; i < 64; i++)
188: {
189: b = new StringBuilder();
190: for (j = 0; j < 4; j++)
191: b.append("0x").append(Util.toString(T3[i * 4 + j])).append(", ");
192: log.fine(b.toString());
193: }
194: log.fine("T4[]:");
195: for (i = 0; i < 64; i++)
196: {
197: b = new StringBuilder();
198: for (j = 0; j < 4; j++)
199: b.append("0x").append(Util.toString(T4[i * 4 + j])).append(", ");
200: log.fine(b.toString());
201: }
202: log.fine("T5[]:");
203: for (i = 0; i < 64; i++)
204: {
205: b = new StringBuilder();
206: for (j = 0; j < 4; j++)
207: b.append("0x").append(Util.toString(T5[i * 4 + j])).append(", ");
208: log.fine(b.toString());
209: }
210: log.fine("T6[]:");
211: for (i = 0; i < 64; i++)
212: {
213: b = new StringBuilder();
214: for (j = 0; j < 4; j++)
215: b.append("0x").append(Util.toString(T6[i * 4 + j])).append(", ");
216: log.fine(b.toString());
217: }
218: log.fine("T7[]:");
219: for (i = 0; i < 64; i++)
220: {
221: b = new StringBuilder();
222: for (j = 0; j < 4; j++)
223: b.append("0x").append(Util.toString(T7[i * 4 + j])).append(", ");
224: log.fine(b.toString());
225: }
226: log.fine("rc[]:");
227: for (i = 0; i < R + 1; i++)
228: log.fine("0x" + Util.toString(rc[i][0]) + Util.toString(rc[i][1]));
229: log.fine("Total initialization time: " + time + " ms.");
230: }
231: }
232:
233:
234: public Khazad()
235: {
236: super(Registry.KHAZAD_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
237: }
238:
239: private static void khazad(byte[] in, int i, byte[] out, int j, int[][] K)
240: {
241:
242: int k0 = K[0][0];
243: int k1 = K[0][1];
244: int a0 = (in[i++] << 24
245: | (in[i++] & 0xFF) << 16
246: | (in[i++] & 0xFF) << 8
247: | (in[i++] & 0xFF) ) ^ k0;
248: int a1 = (in[i++] << 24
249: | (in[i++] & 0xFF) << 16
250: | (in[i++] & 0xFF) << 8
251: | (in[i ] & 0xFF) ) ^ k1;
252: int b0, b1;
253:
254: for (int r = 1; r < R; r++)
255: {
256: k0 = K[r][0];
257: k1 = K[r][1];
258: b0 = T0[ a0 >>> 24 ]
259: ^ T1[(a0 >>> 16) & 0xFF]
260: ^ T2[(a0 >>> 8) & 0xFF]
261: ^ T3[ a0 & 0xFF]
262: ^ T4[ a1 >>> 24 ]
263: ^ T5[(a1 >>> 16) & 0xFF]
264: ^ T6[(a1 >>> 8) & 0xFF]
265: ^ T7[ a1 & 0xFF] ^ k0;
266: b1 = T0[ a1 >>> 24 ]
267: ^ T1[(a1 >>> 16) & 0xFF]
268: ^ T2[(a1 >>> 8) & 0xFF]
269: ^ T3[ a1 & 0xFF]
270: ^ T4[ a0 >>> 24 ]
271: ^ T5[(a0 >>> 16) & 0xFF]
272: ^ T6[(a0 >>> 8) & 0xFF]
273: ^ T7[ a0 & 0xFF] ^ k1;
274: a0 = b0;
275: a1 = b1;
276: if (Configuration.DEBUG)
277: log.fine("T" + r + "=" + Util.toString(a0) + Util.toString(a1));
278: }
279:
280: k0 = K[R][0];
281: k1 = K[R][1];
282: out[j++] = (byte)(S[ a0 >>> 24 ] ^ (k0 >>> 24));
283: out[j++] = (byte)(S[(a0 >>> 16) & 0xFF] ^ (k0 >>> 16));
284: out[j++] = (byte)(S[(a0 >>> 8) & 0xFF] ^ (k0 >>> 8));
285: out[j++] = (byte)(S[ a0 & 0xFF] ^ k0 );
286: out[j++] = (byte)(S[ a1 >>> 24 ] ^ (k1 >>> 24));
287: out[j++] = (byte)(S[(a1 >>> 16) & 0xFF] ^ (k1 >>> 16));
288: out[j++] = (byte)(S[(a1 >>> 8) & 0xFF] ^ (k1 >>> 8));
289: out[j ] = (byte)(S[ a1 & 0xFF] ^ k1 );
290: if (Configuration.DEBUG)
291: log.fine("T=" + Util.toString(out, j - 7, 8) + "\n");
292: }
293:
294: public Object clone()
295: {
296: Khazad result = new Khazad();
297: result.currentBlockSize = this.currentBlockSize;
298:
299: return result;
300: }
301:
302: public Iterator blockSizes()
303: {
304: ArrayList al = new ArrayList();
305: al.add(Integer.valueOf(DEFAULT_BLOCK_SIZE));
306:
307: return Collections.unmodifiableList(al).iterator();
308: }
309:
310: public Iterator keySizes()
311: {
312: ArrayList al = new ArrayList();
313: al.add(Integer.valueOf(DEFAULT_KEY_SIZE));
314: return Collections.unmodifiableList(al).iterator();
315: }
316:
317:
327: public Object makeKey(byte[] uk, int bs) throws InvalidKeyException
328: {
329: if (bs != DEFAULT_BLOCK_SIZE)
330: throw new IllegalArgumentException();
331: if (uk == null)
332: throw new InvalidKeyException("Empty key");
333: if (uk.length != 16)
334: throw new InvalidKeyException("Key is not 128-bit.");
335: int[][] Ke = new int[R + 1][2];
336: int[][] Kd = new int[R + 1][2];
337: int r, i;
338: int k20, k21, k10, k11, rc0, rc1, kr0, kr1;
339: i = 0;
340: k20 = uk[i++] << 24
341: | (uk[i++] & 0xFF) << 16
342: | (uk[i++] & 0xFF) << 8
343: | (uk[i++] & 0xFF);
344: k21 = uk[i++] << 24
345: | (uk[i++] & 0xFF) << 16
346: | (uk[i++] & 0xFF) << 8
347: | (uk[i++] & 0xFF);
348: k10 = uk[i++] << 24
349: | (uk[i++] & 0xFF) << 16
350: | (uk[i++] & 0xFF) << 8
351: | (uk[i++] & 0xFF);
352: k11 = uk[i++] << 24
353: | (uk[i++] & 0xFF) << 16
354: | (uk[i++] & 0xFF) << 8
355: | (uk[i++] & 0xFF);
356: for (r = 0, i = 0; r <= R; r++)
357: {
358: rc0 = rc[r][0];
359: rc1 = rc[r][1];
360: kr0 = T0[ k10 >>> 24 ]
361: ^ T1[(k10 >>> 16) & 0xFF]
362: ^ T2[(k10 >>> 8) & 0xFF]
363: ^ T3[ k10 & 0xFF]
364: ^ T4[(k11 >>> 24) & 0xFF]
365: ^ T5[(k11 >>> 16) & 0xFF]
366: ^ T6[(k11 >>> 8) & 0xFF]
367: ^ T7[ k11 & 0xFF] ^ rc0 ^ k20;
368: kr1 = T0[ k11 >>> 24 ]
369: ^ T1[(k11 >>> 16) & 0xFF]
370: ^ T2[(k11 >>> 8) & 0xFF]
371: ^ T3[ k11 & 0xFF]
372: ^ T4[(k10 >>> 24) & 0xFF]
373: ^ T5[(k10 >>> 16) & 0xFF]
374: ^ T6[(k10 >>> 8) & 0xFF]
375: ^ T7[ k10 & 0xFF] ^ rc1 ^ k21;
376: Ke[r][0] = kr0;
377: Ke[r][1] = kr1;
378: k20 = k10;
379: k21 = k11;
380: k10 = kr0;
381: k11 = kr1;
382: if (r == 0 || r == R)
383: {
384: Kd[R - r][0] = kr0;
385: Kd[R - r][1] = kr1;
386: }
387: else
388: {
389: Kd[R - r][0] = T0[S[ kr0 >>> 24 ] & 0xFF]
390: ^ T1[S[(kr0 >>> 16) & 0xFF] & 0xFF]
391: ^ T2[S[(kr0 >>> 8) & 0xFF] & 0xFF]
392: ^ T3[S[ kr0 & 0xFF] & 0xFF]
393: ^ T4[S[ kr1 >>> 24 ] & 0xFF]
394: ^ T5[S[(kr1 >>> 16) & 0xFF] & 0xFF]
395: ^ T6[S[(kr1 >>> 8) & 0xFF] & 0xFF]
396: ^ T7[S[ kr1 & 0xFF] & 0xFF];
397: Kd[R - r][1] = T0[S[ kr1 >>> 24 ] & 0xFF]
398: ^ T1[S[(kr1 >>> 16) & 0xFF] & 0xFF]
399: ^ T2[S[(kr1 >>> 8) & 0xFF] & 0xFF]
400: ^ T3[S[ kr1 & 0xFF] & 0xFF]
401: ^ T4[S[ kr0 >>> 24 ] & 0xFF]
402: ^ T5[S[(kr0 >>> 16) & 0xFF] & 0xFF]
403: ^ T6[S[(kr0 >>> 8) & 0xFF] & 0xFF]
404: ^ T7[S[ kr0 & 0xFF] & 0xFF];
405: }
406: }
407: if (Configuration.DEBUG)
408: {
409: log.fine("Key schedule");
410: log.fine("Ke[]:");
411: for (r = 0; r < R + 1; r++)
412: log.fine("#" + r + ": 0x" + Util.toString(Ke[r][0])
413: + Util.toString(Ke[r][1]));
414: log.fine("Kd[]:");
415: for (r = 0; r < R + 1; r++)
416: log.fine("#" + r + ": 0x" + Util.toString(Kd[r][0])
417: + Util.toString(Kd[r][1]));
418: }
419: return new Object[] { Ke, Kd };
420: }
421:
422: public void encrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
423: {
424: if (bs != DEFAULT_BLOCK_SIZE)
425: throw new IllegalArgumentException();
426: int[][] K = (int[][])((Object[]) k)[0];
427: khazad(in, i, out, j, K);
428: }
429:
430: public void decrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
431: {
432: if (bs != DEFAULT_BLOCK_SIZE)
433: throw new IllegalArgumentException();
434: int[][] K = (int[][])((Object[]) k)[1];
435: khazad(in, i, out, j, K);
436: }
437:
438: public boolean selfTest()
439: {
440: if (valid == null)
441: {
442: boolean result = super.selfTest();
443: if (result)
444: result = testKat(KAT_KEY, KAT_CT);
445: valid = Boolean.valueOf(result);
446: }
447: return valid.booleanValue();
448: }
449: }