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
= new Boolean(result
);
581 return valid
.booleanValue();