2
Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
4
This file is a part of GNU Classpath.
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or (at
9
your option) any later version.
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library. Thus, the terms and
23
conditions of the GNU General Public License cover the whole
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module. An independent module is a module which is not derived from
33
or based on this library. If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so. If you do not wish to do so, delete this
36
exception statement from your version. */
39
package gnu.javax.crypto.cipher;
41
import gnu.java.security.Registry;
42
import gnu.java.security.util.Util;
44
//import java.io.PrintWriter;
45
import java.security.InvalidKeyException;
46
import java.util.ArrayList;
47
import java.util.Collections;
48
import java.util.Iterator;
51
* <p>Anubis is a 128-bit block cipher that accepts a variable-length key. The
52
* cipher is a uniform substitution-permutation network whose inverse only
53
* differs from the forward operation in the key schedule. The design of both
54
* the round transformation and the key schedule is based upon the Wide Trail
55
* strategy and permits a wide variety of implementation trade-offs.</p>
60
* <li><a href="http://planeta.terra.com.br/informatica/paulobarreto/AnubisPage.html">The
61
* ANUBIS Block Cipher</a>.<br>
62
* <a href="mailto:paulo.barreto@terra.com.br">Paulo S.L.M. Barreto</a> and
63
* <a href="mailto:vincent.rijmen@esat.kuleuven.ac.be">Vincent Rijmen</a>.</li>
66
public final class Anubis extends BaseCipher
69
// Debugging methods and variables
70
// -------------------------------------------------------------------------
72
// private static final String NAME = "anubis";
73
private static final boolean DEBUG = false;
75
private static final int debuglevel = 9;
77
// private static final PrintWriter err = new PrintWriter(System.out, true);
78
// private static void debug(String s) {
79
// err.println(">>> "+NAME+": "+s);
82
// Constants and variables
83
// -------------------------------------------------------------------------
85
private static final int DEFAULT_BLOCK_SIZE = 16; // in bytes
87
private static final int DEFAULT_KEY_SIZE = 16; // in bytes
89
private static final String Sd = // p. 25 [ANUBIS]
90
"\uBA54\u2F74\u53D3\uD24D\u50AC\u8DBF\u7052\u9A4C"
91
+ "\uEAD5\u97D1\u3351\u5BA6\uDE48\uA899\uDB32\uB7FC"
92
+ "\uE39E\u919B\uE2BB\u416E\uA5CB\u6B95\uA1F3\uB102"
93
+ "\uCCC4\u1D14\uC363\uDA5D\u5FDC\u7DCD\u7F5A\u6C5C"
94
+ "\uF726\uFFED\uE89D\u6F8E\u19A0\uF089\u0F07\uAFFB"
95
+ "\u0815\u0D04\u0164\uDF76\u79DD\u3D16\u3F37\u6D38"
96
+ "\uB973\uE935\u5571\u7B8C\u7288\uF62A\u3E5E\u2746"
97
+ "\u0C65\u6861\u03C1\u57D6\uD958\uD866\uD73A\uC83C"
98
+ "\uFA96\uA798\uECB8\uC7AE\u694B\uABA9\u670A\u47F2"
99
+ "\uB522\uE5EE\uBE2B\u8112\u831B\u0E23\uF545\u21CE"
100
+ "\u492C\uF9E6\uB628\u1782\u1A8B\uFE8A\u09C9\u874E"
101
+ "\uE12E\uE4E0\uEB90\uA41E\u8560\u0025\uF4F1\u940B"
102
+ "\uE775\uEF34\u31D4\uD086\u7EAD\uFD29\u303B\u9FF8"
103
+ "\uC613\u0605\uC511\u777C\u7A78\u361C\u3959\u1856"
104
+ "\uB3B0\u2420\uB292\uA3C0\u4462\u10B4\u8443\u93C2"
105
+ "\u4ABD\u8F2D\uBC9C\u6A40\uCFA2\u804F\u1FCA\uAA42";
107
private static final byte[] S = new byte[256];
109
private static final int[] T0 = new int[256];
111
private static final int[] T1 = new int[256];
113
private static final int[] T2 = new int[256];
115
private static final int[] T3 = new int[256];
117
private static final int[] T4 = new int[256];
119
private static final int[] T5 = new int[256];
122
* Anubis round constants. This is the largest possible considering that we
123
* always use R values, R = 8 + N, and 4 <= N <= 10.
125
private static final int[] rc = new int[18];
128
* KAT vector (from ecb_vk):
130
* KEY=000000000000000000002000000000000000000000000000
131
* CT=2E66AB15773F3D32FB6C697509460DF4
133
private static final byte[] KAT_KEY = Util.toBytesFromString("000000000000000000002000000000000000000000000000");
135
private static final byte[] KAT_CT = Util.toBytesFromString("2E66AB15773F3D32FB6C697509460DF4");
137
/** caches the result of the correctness test, once executed. */
138
private static Boolean valid;
140
// Static code - to initialise lookup tables -------------------------------
144
long time = System.currentTimeMillis();
146
int ROOT = 0x11d; // para. 2.1 [ANUBIS]
147
int i, s, s2, s4, s6, s8, t;
149
for (i = 0; i < 256; i++)
151
c = Sd.charAt(i >>> 1);
152
s = ((i & 1) == 0 ? c >>> 8 : c) & 0xFF;
174
T0[i] = s << 24 | s2 << 16 | s4 << 8 | s6;
175
T1[i] = s2 << 24 | s << 16 | s6 << 8 | s4;
176
T2[i] = s4 << 24 | s6 << 16 | s << 8 | s2;
177
T3[i] = s6 << 24 | s4 << 16 | s2 << 8 | s;
179
T4[i] = s << 24 | s << 16 | s << 8 | s;
180
T5[s] = s << 24 | s2 << 16 | s6 << 8 | s8;
183
// compute round constant
184
for (i = 0, s = 0; i < 18;)
186
rc[i++] = S[(s++) & 0xFF] << 24 | (S[(s++) & 0xFF] & 0xFF) << 16
187
| (S[(s++) & 0xFF] & 0xFF) << 8 | (S[(s++) & 0xFF] & 0xFF);
190
time = System.currentTimeMillis() - time;
192
if (DEBUG && debuglevel > 8)
194
System.out.println("==========");
195
System.out.println();
196
System.out.println("Static data");
197
System.out.println();
199
System.out.println();
200
System.out.println("T0[]:");
201
for (i = 0; i < 64; i++)
203
for (t = 0; t < 4; t++)
205
System.out.print("0x" + Util.toString(T0[i * 4 + t]) + ", ");
207
System.out.println();
209
System.out.println();
210
System.out.println("T1[]:");
211
for (i = 0; i < 64; i++)
213
for (t = 0; t < 4; t++)
215
System.out.print("0x" + Util.toString(T1[i * 4 + t]) + ", ");
217
System.out.println();
219
System.out.println();
220
System.out.println("T2[]:");
221
for (i = 0; i < 64; i++)
223
for (t = 0; t < 4; t++)
225
System.out.print("0x" + Util.toString(T2[i * 4 + t]) + ", ");
227
System.out.println();
229
System.out.println();
230
System.out.println("T3[]:");
231
for (i = 0; i < 64; i++)
233
for (t = 0; t < 4; t++)
235
System.out.print("0x" + Util.toString(T3[i * 4 + t]) + ", ");
237
System.out.println();
239
System.out.println();
240
System.out.println("T4[]:");
241
for (i = 0; i < 64; i++)
243
for (t = 0; t < 4; t++)
245
System.out.print("0x" + Util.toString(T4[i * 4 + t]) + ", ");
247
System.out.println();
249
System.out.println();
250
System.out.println("T5[]:");
251
for (i = 0; i < 64; i++)
253
for (t = 0; t < 4; t++)
255
System.out.print("0x" + Util.toString(T5[i * 4 + t]) + ", ");
257
System.out.println();
259
System.out.println();
260
System.out.println("rc[]:");
261
for (i = 0; i < 18; i++)
263
System.out.println("0x" + Util.toString(rc[i]));
265
System.out.println();
267
System.out.println();
268
System.out.println("Total initialization time: " + time + " ms.");
269
System.out.println();
274
// -------------------------------------------------------------------------
276
/** Trivial 0-arguments constructor. */
279
super(Registry.ANUBIS_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
283
// -------------------------------------------------------------------------
285
private static void anubis(byte[] in, int i, byte[] out, int j, int[][] K)
287
// extract encryption round keys
288
int R = K.length - 1;
291
// mu function + affine key addition
292
int a0 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
294
int a1 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
296
int a2 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
298
int a3 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i] & 0xFF))
303
for (int r = 1; r < R; r++)
306
b0 = T0[a0 >>> 24] ^ T1[a1 >>> 24] ^ T2[a2 >>> 24] ^ T3[a3 >>> 24]
308
b1 = T0[(a0 >>> 16) & 0xFF] ^ T1[(a1 >>> 16) & 0xFF]
309
^ T2[(a2 >>> 16) & 0xFF] ^ T3[(a3 >>> 16) & 0xFF] ^ Ker[1];
310
b2 = T0[(a0 >>> 8) & 0xFF] ^ T1[(a1 >>> 8) & 0xFF]
311
^ T2[(a2 >>> 8) & 0xFF] ^ T3[(a3 >>> 8) & 0xFF] ^ Ker[2];
312
b3 = T0[a0 & 0xFF] ^ T1[a1 & 0xFF] ^ T2[a2 & 0xFF] ^ T3[a3 & 0xFF]
318
if (DEBUG && debuglevel > 6)
320
System.out.println("T" + r + "=" + Util.toString(a0)
321
+ Util.toString(a1) + Util.toString(a2)
322
+ Util.toString(a3));
326
// last round function
329
out[j++] = (byte) (S[a0 >>> 24] ^ (tt >>> 24));
330
out[j++] = (byte) (S[a1 >>> 24] ^ (tt >>> 16));
331
out[j++] = (byte) (S[a2 >>> 24] ^ (tt >>> 8));
332
out[j++] = (byte) (S[a3 >>> 24] ^ tt);
334
out[j++] = (byte) (S[(a0 >>> 16) & 0xFF] ^ (tt >>> 24));
335
out[j++] = (byte) (S[(a1 >>> 16) & 0xFF] ^ (tt >>> 16));
336
out[j++] = (byte) (S[(a2 >>> 16) & 0xFF] ^ (tt >>> 8));
337
out[j++] = (byte) (S[(a3 >>> 16) & 0xFF] ^ tt);
339
out[j++] = (byte) (S[(a0 >>> 8) & 0xFF] ^ (tt >>> 24));
340
out[j++] = (byte) (S[(a1 >>> 8) & 0xFF] ^ (tt >>> 16));
341
out[j++] = (byte) (S[(a2 >>> 8) & 0xFF] ^ (tt >>> 8));
342
out[j++] = (byte) (S[(a3 >>> 8) & 0xFF] ^ tt);
344
out[j++] = (byte) (S[a0 & 0xFF] ^ (tt >>> 24));
345
out[j++] = (byte) (S[a1 & 0xFF] ^ (tt >>> 16));
346
out[j++] = (byte) (S[a2 & 0xFF] ^ (tt >>> 8));
347
out[j] = (byte) (S[a3 & 0xFF] ^ tt);
349
if (DEBUG && debuglevel > 6)
351
System.out.println("T=" + Util.toString(out, j - 15, 16));
352
System.out.println();
357
// -------------------------------------------------------------------------
359
// java.lang.Cloneable interface implementation ----------------------------
361
public Object clone()
363
Anubis result = new Anubis();
364
result.currentBlockSize = this.currentBlockSize;
369
// IBlockCipherSpi interface implementation --------------------------------
371
public Iterator blockSizes()
373
ArrayList al = new ArrayList();
374
al.add(new Integer(DEFAULT_BLOCK_SIZE));
376
return Collections.unmodifiableList(al).iterator();
379
public Iterator keySizes()
381
ArrayList al = new ArrayList();
382
for (int n = 4; n < 10; n++)
384
al.add(new Integer(n * 32 / 8));
387
return Collections.unmodifiableList(al).iterator();
391
* <p>Expands a user-supplied key material into a session key for a
392
* designated <i>block size</i>.</p>
394
* @param uk the 32N-bit user-supplied key material; 4 <= N <= 10.
395
* @param bs the desired block size in bytes.
396
* @return an Object encapsulating the session key.
397
* @exception IllegalArgumentException if the block size is not 16 (128-bit).
398
* @exception InvalidKeyException if the key data is invalid.
400
public Object makeKey(byte[] uk, int bs) throws InvalidKeyException
402
if (bs != DEFAULT_BLOCK_SIZE)
404
throw new IllegalArgumentException();
408
throw new InvalidKeyException("Empty key");
410
if ((uk.length % 4) != 0)
412
throw new InvalidKeyException("Key is not multiple of 32-bit.");
414
int N = uk.length / 4;
417
throw new InvalidKeyException("Key is not 32N; 4 <= N <= 10");
420
int[][] Ke = new int[R + 1][4]; // encryption round keys
421
int[][] Kd = new int[R + 1][4]; // decryption round keys
422
int[] tk = new int[N];
423
int[] kk = new int[N];
424
int r, i, j, k, k0, k1, k2, k3, tt;
427
for (r = 0, i = 0; r < N;)
429
tk[r++] = uk[i++] << 24 | (uk[i++] & 0xFF) << 16
430
| (uk[i++] & 0xFF) << 8 | (uk[i++] & 0xFF);
432
for (r = 0; r <= R; r++)
436
// psi = key evolution function
437
kk[0] = T0[(tk[0] >>> 24)] ^ T1[(tk[N - 1] >>> 16) & 0xFF]
438
^ T2[(tk[N - 2] >>> 8) & 0xFF] ^ T3[tk[N - 3] & 0xFF];
439
kk[1] = T0[(tk[1] >>> 24)] ^ T1[(tk[0] >>> 16) & 0xFF]
440
^ T2[(tk[N - 1] >>> 8) & 0xFF] ^ T3[tk[N - 2] & 0xFF];
441
kk[2] = T0[(tk[2] >>> 24)] ^ T1[(tk[1] >>> 16) & 0xFF]
442
^ T2[(tk[0] >>> 8) & 0xFF] ^ T3[tk[N - 1] & 0xFF];
443
kk[3] = T0[(tk[3] >>> 24)] ^ T1[(tk[2] >>> 16) & 0xFF]
444
^ T2[(tk[1] >>> 8) & 0xFF] ^ T3[tk[0] & 0xFF];
446
for (i = 4; i < N; i++)
448
kk[i] = T0[tk[i] >>> 24] ^ T1[(tk[i - 1] >>> 16) & 0xFF]
449
^ T2[(tk[i - 2] >>> 8) & 0xFF] ^ T3[tk[i - 3] & 0xFF];
451
// apply sigma (affine addition) to round constant
452
tk[0] = rc[r - 1] ^ kk[0];
453
for (i = 1; i < N; i++)
459
// phi = key selection function
462
k1 = T4[(tt >>> 16) & 0xFF];
463
k2 = T4[(tt >>> 8) & 0xFF];
466
for (k = N - 2; k >= 0; k--)
469
k0 = T4[tt >>> 24] ^ (T5[(k0 >>> 24) & 0xFF] & 0xFF000000)
470
^ (T5[(k0 >>> 16) & 0xFF] & 0x00FF0000)
471
^ (T5[(k0 >>> 8) & 0xFF] & 0x0000FF00)
472
^ (T5[k0 & 0xFF] & 0x000000FF);
473
k1 = T4[(tt >>> 16) & 0xFF] ^ (T5[(k1 >>> 24) & 0xFF] & 0xFF000000)
474
^ (T5[(k1 >>> 16) & 0xFF] & 0x00FF0000)
475
^ (T5[(k1 >>> 8) & 0xFF] & 0x0000FF00)
476
^ (T5[k1 & 0xFF] & 0x000000FF);
477
k2 = T4[(tt >>> 8) & 0xFF] ^ (T5[(k2 >>> 24) & 0xFF] & 0xFF000000)
478
^ (T5[(k2 >>> 16) & 0xFF] & 0x00FF0000)
479
^ (T5[(k2 >>> 8) & 0xFF] & 0x0000FF00)
480
^ (T5[(k2) & 0xFF] & 0x000000FF);
481
k3 = T4[tt & 0xFF] ^ (T5[(k3 >>> 24) & 0xFF] & 0xFF000000)
482
^ (T5[(k3 >>> 16) & 0xFF] & 0x00FF0000)
483
^ (T5[(k3 >>> 8) & 0xFF] & 0x0000FF00)
484
^ (T5[k3 & 0xFF] & 0x000000FF);
492
if (r == 0 || r == R)
501
Kd[R - r][0] = T0[S[k0 >>> 24] & 0xFF]
502
^ T1[S[(k0 >>> 16) & 0xFF] & 0xFF]
503
^ T2[S[(k0 >>> 8) & 0xFF] & 0xFF]
504
^ T3[S[k0 & 0xFF] & 0xFF];
505
Kd[R - r][1] = T0[S[k1 >>> 24] & 0xFF]
506
^ T1[S[(k1 >>> 16) & 0xFF] & 0xFF]
507
^ T2[S[(k1 >>> 8) & 0xFF] & 0xFF]
508
^ T3[S[k1 & 0xFF] & 0xFF];
509
Kd[R - r][2] = T0[S[k2 >>> 24] & 0xFF]
510
^ T1[S[(k2 >>> 16) & 0xFF] & 0xFF]
511
^ T2[S[(k2 >>> 8) & 0xFF] & 0xFF]
512
^ T3[S[k2 & 0xFF] & 0xFF];
513
Kd[R - r][3] = T0[S[k3 >>> 24] & 0xFF]
514
^ T1[S[(k3 >>> 16) & 0xFF] & 0xFF]
515
^ T2[S[(k3 >>> 8) & 0xFF] & 0xFF]
516
^ T3[S[k3 & 0xFF] & 0xFF];
520
if (DEBUG && debuglevel > 8)
522
System.out.println();
523
System.out.println("Key schedule");
524
System.out.println();
525
System.out.println("Ke[]:");
526
for (r = 0; r < R + 1; r++)
528
System.out.print("#" + r + ": ");
529
for (j = 0; j < 4; j++)
530
System.out.print("0x" + Util.toString(Ke[r][j]) + ", ");
531
System.out.println();
533
System.out.println();
534
System.out.println("Kd[]:");
535
for (r = 0; r < R + 1; r++)
537
System.out.print("#" + r + ": ");
538
for (j = 0; j < 4; j++)
539
System.out.print("0x" + Util.toString(Kd[r][j]) + ", ");
540
System.out.println();
542
System.out.println();
545
return new Object[] { Ke, Kd };
548
public void encrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
550
if (bs != DEFAULT_BLOCK_SIZE)
552
throw new IllegalArgumentException();
555
int[][] K = (int[][]) ((Object[]) k)[0];
556
anubis(in, i, out, j, K);
559
public void decrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
561
if (bs != DEFAULT_BLOCK_SIZE)
563
throw new IllegalArgumentException();
566
int[][] K = (int[][]) ((Object[]) k)[1];
567
anubis(in, i, out, j, K);
570
public boolean selfTest()
574
boolean result = super.selfTest(); // do symmetry tests
577
result = testKat(KAT_KEY, KAT_CT);
579
valid = Boolean.valueOf(result);
581
return valid.booleanValue();
b'\\ No newline at end of file'