Author: nextgens Date: 2007-03-17 13:15:06 +0000 (Sat, 17 Mar 2007) New Revision: 12177
Modified: trunk/freenet/src/freenet/crypt/ciphers/Rijndael.java trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Algorithm.java trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Properties.java Log: indent Modified: trunk/freenet/src/freenet/crypt/ciphers/Rijndael.java =================================================================== --- trunk/freenet/src/freenet/crypt/ciphers/Rijndael.java 2007-03-17 13:11:29 UTC (rev 12176) +++ trunk/freenet/src/freenet/crypt/ciphers/Rijndael.java 2007-03-17 13:15:06 UTC (rev 12177) @@ -11,167 +11,167 @@ This code is part of the Java Adaptive Network Client by Ian Clarke. It is distributed under the GNU Public Licence (GPL) version 2. See http://www.gnu.org/ for further details of the GPL. -*/ + */ /** * Interfaces with the Rijndael AES candidate to implement the Rijndael * algorithm */ public class Rijndael implements BlockCipher { - private Object sessionKey; - private final int keysize, blocksize; - // FIXME remove. This is used to simulate an old security threatening bug in order - // to have backwards compatibility with old keys. - private final int cryptBlockSize; + private Object sessionKey; + private final int keysize, blocksize; + // FIXME remove. This is used to simulate an old security threatening bug in order + // to have backwards compatibility with old keys. + private final int cryptBlockSize; - // for Util.getCipherByName.. and yes, screw you too, java - public Rijndael(Integer keysize) throws UnsupportedCipherException { - this(keysize.intValue()); - } + // for Util.getCipherByName.. and yes, screw you too, java + public Rijndael(Integer keysize) throws UnsupportedCipherException { + this(keysize.intValue()); + } - public Rijndael(int keysize) throws UnsupportedCipherException { - this(keysize, 128, false); - } + public Rijndael(int keysize) throws UnsupportedCipherException { + this(keysize, 128, false); + } - /** - * Create a Rijndael instance. - * @param keysize The key size. - * @param blocksize The block size. - * @param fakeInsecure If true, only encrypt the first 128 bits of any block. This - * is insecure! It is used for backwards compatibility with old data encrypted with - * the old code. - * @throws UnsupportedCipherException - */ - public Rijndael(int keysize, int blocksize, boolean fakeInsecure) throws UnsupportedCipherException { - if (! ((keysize == 128) || - (keysize == 192) || - (keysize == 256))) - throw new UnsupportedCipherException("Invalid keysize"); - if (! ((blocksize == 128) || - (blocksize == 192) || - (blocksize == 256))) - throw new UnsupportedCipherException("Invalid blocksize"); - this.keysize=keysize; - this.blocksize=blocksize; - // FIXME This is deliberate insecurity! It is used for backwards compatibility *ONLY*! - // FIXME IT MUST BE REMOVED SOON! - if(fakeInsecure) + /** + * Create a Rijndael instance. + * @param keysize The key size. + * @param blocksize The block size. + * @param fakeInsecure If true, only encrypt the first 128 bits of any block. This + * is insecure! It is used for backwards compatibility with old data encrypted with + * the old code. + * @throws UnsupportedCipherException + */ + public Rijndael(int keysize, int blocksize, boolean fakeInsecure) throws UnsupportedCipherException { + if (! ((keysize == 128) || + (keysize == 192) || + (keysize == 256))) + throw new UnsupportedCipherException("Invalid keysize"); + if (! ((blocksize == 128) || + (blocksize == 192) || + (blocksize == 256))) + throw new UnsupportedCipherException("Invalid blocksize"); + this.keysize=keysize; + this.blocksize=blocksize; + // FIXME This is deliberate insecurity! It is used for backwards compatibility *ONLY*! + // FIXME IT MUST BE REMOVED SOON! + if(fakeInsecure) + this.cryptBlockSize = 128; + else + this.cryptBlockSize = blocksize; + } + + public Rijndael() { + this.keysize = 128; + this.blocksize = 128; this.cryptBlockSize = 128; - else - this.cryptBlockSize = blocksize; - } + } - public Rijndael() { - this.keysize = 128; - this.blocksize = 128; - this.cryptBlockSize = 128; - } + public final int getBlockSize() { + return blocksize; + } - public final int getBlockSize() { - return blocksize; - } + public final int getKeySize() { + return keysize; + } - public final int getKeySize() { - return keysize; - } + public final void initialize(byte[] key) { + try { + byte[] nkey=new byte[keysize>>3]; + System.arraycopy(key, 0, nkey, 0, nkey.length); + sessionKey=Rijndael_Algorithm.makeKey(nkey, cryptBlockSize/8); + } catch (InvalidKeyException e) { + e.printStackTrace(); + Logger.error(this,"Invalid key"); + } + } - public final void initialize(byte[] key) { - try { - byte[] nkey=new byte[keysize>>3]; - System.arraycopy(key, 0, nkey, 0, nkey.length); - sessionKey=Rijndael_Algorithm.makeKey(nkey, cryptBlockSize/8); - } catch (InvalidKeyException e) { - e.printStackTrace(); - Logger.error(this,"Invalid key"); + public synchronized final void encipher(byte[] block, byte[] result) { + if(block.length != blocksize/8) + throw new IllegalArgumentException(); + Rijndael_Algorithm.blockEncrypt(block, result, 0, sessionKey, cryptBlockSize/8); } - } - public synchronized final void encipher(byte[] block, byte[] result) { - if(block.length != blocksize/8) - throw new IllegalArgumentException(); - Rijndael_Algorithm.blockEncrypt(block, result, 0, sessionKey, cryptBlockSize/8); - } + /** + * @return Size of temporary int[] a, t. If these are passed in, this can speed + * things up by avoiding unnecessary allocations between rounds. + */ + public synchronized final int getTempArraySize() { + return cryptBlockSize/(8*4); + } - /** - * @return Size of temporary int[] a, t. If these are passed in, this can speed - * things up by avoiding unnecessary allocations between rounds. - */ - public synchronized final int getTempArraySize() { - return cryptBlockSize/(8*4); - } - - public synchronized final void encipher(byte[] block, byte[] result, int[] a, int[] t) { - if(block.length != blocksize/8) - throw new IllegalArgumentException(); - if(a.length != t.length || t.length != cryptBlockSize/(8*4)) - throw new IllegalArgumentException(); - Rijndael_Algorithm.blockEncrypt(block, result, 0, sessionKey, cryptBlockSize/8, a, t); - } - - public synchronized final void decipher(byte[] block, byte[] result) { - if(block.length != blocksize/8) - throw new IllegalArgumentException(); - Rijndael_Algorithm.blockDecrypt(block, result, 0, sessionKey, cryptBlockSize/8); - } + public synchronized final void encipher(byte[] block, byte[] result, int[] a, int[] t) { + if(block.length != blocksize/8) + throw new IllegalArgumentException(); + if(a.length != t.length || t.length != cryptBlockSize/(8*4)) + throw new IllegalArgumentException(); + Rijndael_Algorithm.blockEncrypt(block, result, 0, sessionKey, cryptBlockSize/8, a, t); + } - public static void main(String[] args) throws UnsupportedCipherException { - // Perform the Monte Carlo test + public synchronized final void decipher(byte[] block, byte[] result) { + if(block.length != blocksize/8) + throw new IllegalArgumentException(); + Rijndael_Algorithm.blockDecrypt(block, result, 0, sessionKey, cryptBlockSize/8); + } - System.out.println("KEYSIZE=128\n"); - monteCarlo(128); - System.out.println("=========================\n"); - System.out.println("KEYSIZE=192\n"); - monteCarlo(192); - System.out.println("=========================\n"); - System.out.println("KEYSIZE=256\n"); - monteCarlo(256); - } + public static void main(String[] args) throws UnsupportedCipherException { + // Perform the Monte Carlo test - static void monteCarlo(int keySize) throws UnsupportedCipherException { - Rijndael ctx=new Rijndael(keySize); - int kb=keySize/8; - byte[] P=new byte[16], C=new byte[16], - CL=new byte[16], KEY=new byte[kb]; + System.out.println("KEYSIZE=128\n"); + monteCarlo(128); + System.out.println("=========================\n"); + System.out.println("KEYSIZE=192\n"); + monteCarlo(192); + System.out.println("=========================\n"); + System.out.println("KEYSIZE=256\n"); + monteCarlo(256); + } - for (int i=0; i<400; i++) { - System.out.println("I="+i); - System.out.println("KEY="+HexUtil.bytesToHex(KEY,0,kb)); + static void monteCarlo(int keySize) throws UnsupportedCipherException { + Rijndael ctx=new Rijndael(keySize); + int kb=keySize/8; + byte[] P=new byte[16], C=new byte[16], + CL=new byte[16], KEY=new byte[kb]; - System.out.println("PT="+HexUtil.bytesToHex(P,0,16)); + for (int i=0; i<400; i++) { + System.out.println("I="+i); + System.out.println("KEY="+HexUtil.bytesToHex(KEY,0,kb)); - ctx.initialize(KEY); - for (int j=0; j<10000; j++) { - System.arraycopy(C, 0, CL, 0, C.length); - ctx.encipher(P, C); - System.arraycopy(C, 0, P, 0, P.length); - } - System.out.println("CT="+HexUtil.bytesToHex(C,0,16)); + System.out.println("PT="+HexUtil.bytesToHex(P,0,16)); - - for (int x=0; x<kb; x++) { - if (keySize==192) - if (x<8) - KEY[x]^=CL[8+x]; - else - KEY[x]^=C[x-8]; - else if (keySize==256) - if (x<16) - KEY[x]^=CL[x]; - else - KEY[x]^=C[x-16]; - else KEY[x]^=C[x]; - } + ctx.initialize(KEY); + for (int j=0; j<10000; j++) { + System.arraycopy(C, 0, CL, 0, C.length); + ctx.encipher(P, C); + System.arraycopy(C, 0, P, 0, P.length); + } + System.out.println("CT="+HexUtil.bytesToHex(C,0,16)); - if (keySize==192) - for (int x=0; x<8; x++) - KEY[x+16]^=CL[x+8]; - else if (keySize==256) - for (int x=0; x<16; x++) - KEY[x+16]^=CL[x]; - System.out.println(); + for (int x=0; x<kb; x++) { + if (keySize==192) + if (x<8) + KEY[x]^=CL[8+x]; + else + KEY[x]^=C[x-8]; + else if (keySize==256) + if (x<16) + KEY[x]^=CL[x]; + else + KEY[x]^=C[x-16]; + else KEY[x]^=C[x]; + } + + if (keySize==192) + for (int x=0; x<8; x++) + KEY[x+16]^=CL[x+8]; + else if (keySize==256) + for (int x=0; x<16; x++) + KEY[x+16]^=CL[x]; + + System.out.println(); + } } - } } Modified: trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Algorithm.java =================================================================== --- trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Algorithm.java 2007-03-17 13:11:29 UTC (rev 12176) +++ trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Algorithm.java 2007-03-17 13:15:06 UTC (rev 12177) @@ -27,874 +27,874 @@ */ public final class Rijndael_Algorithm // implicit no-argument constructor { -// Debugging methods and variables -//........................................................................... +// Debugging methods and variables +// ........................................................................... - static final String NAME = "Rijndael_Algorithm"; - static final boolean IN = true, OUT = false; + static final String NAME = "Rijndael_Algorithm"; + static final boolean IN = true, OUT = false; - static final boolean RDEBUG = Rijndael_Properties.GLOBAL_DEBUG; - static final int debuglevel = RDEBUG ? Rijndael_Properties.getLevel(NAME) : 0; - static final PrintWriter err = RDEBUG ? Rijndael_Properties.getOutput() : null; + static final boolean RDEBUG = Rijndael_Properties.GLOBAL_DEBUG; + static final int debuglevel = RDEBUG ? Rijndael_Properties.getLevel(NAME) : 0; + static final PrintWriter err = RDEBUG ? Rijndael_Properties.getOutput() : null; - static final boolean TRACE = Rijndael_Properties.isTraceable(NAME); + static final boolean TRACE = Rijndael_Properties.isTraceable(NAME); - static void debug (String s) { err.println(">>> "+NAME+": "+s); } - static void trace (boolean in, String s) { - if (TRACE) err.println((in?"==> ":"<== ")+NAME+ '.' +s); - } - static void trace (String s) { if (TRACE) err.println("<=> "+NAME+ '.' +s); } + static void debug (String s) { err.println(">>> "+NAME+": "+s); } + static void trace (boolean in, String s) { + if (TRACE) err.println((in?"==> ":"<== ")+NAME+ '.' +s); + } + static void trace (String s) { if (TRACE) err.println("<=> "+NAME+ '.' +s); } -// Constants and variables -//........................................................................... +// Constants and variables +// ........................................................................... - static final int BLOCK_SIZE = 16; // default block size in bytes + static final int BLOCK_SIZE = 16; // default block size in bytes - static final int[] alog = new int[256]; - static final int[] log = new int[256]; + static final int[] alog = new int[256]; + static final int[] log = new int[256]; - static final byte[] S = new byte[256]; - static final byte[] Si = new byte[256]; - static final int[] T1 = new int[256]; - static final int[] T2 = new int[256]; - static final int[] T3 = new int[256]; - static final int[] T4 = new int[256]; - static final int[] T5 = new int[256]; - static final int[] T6 = new int[256]; - static final int[] T7 = new int[256]; - static final int[] T8 = new int[256]; - static final int[] U1 = new int[256]; - static final int[] U2 = new int[256]; - static final int[] U3 = new int[256]; - static final int[] U4 = new int[256]; - static final byte[] rcon = new byte[30]; + static final byte[] S = new byte[256]; + static final byte[] Si = new byte[256]; + static final int[] T1 = new int[256]; + static final int[] T2 = new int[256]; + static final int[] T3 = new int[256]; + static final int[] T4 = new int[256]; + static final int[] T5 = new int[256]; + static final int[] T6 = new int[256]; + static final int[] T7 = new int[256]; + static final int[] T8 = new int[256]; + static final int[] U1 = new int[256]; + static final int[] U2 = new int[256]; + static final int[] U3 = new int[256]; + static final int[] U4 = new int[256]; + static final byte[] rcon = new byte[30]; - static final int[][][] shifts = new int[][][] { - { {0, 0}, {1, 3}, {2, 2}, {3, 1} }, - { {0, 0}, {1, 5}, {2, 4}, {3, 3} }, - { {0, 0}, {1, 7}, {3, 5}, {4, 4} } - }; + static final int[][][] shifts = new int[][][] { + { {0, 0}, {1, 3}, {2, 2}, {3, 1} }, + { {0, 0}, {1, 5}, {2, 4}, {3, 3} }, + { {0, 0}, {1, 7}, {3, 5}, {4, 4} } + }; - private static final char[] HEX_DIGITS = { - '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' - }; + private static final char[] HEX_DIGITS = { + '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' + }; -// Static code - to intialise S-boxes and T-boxes -//........................................................................... +// Static code - to intialise S-boxes and T-boxes +// ........................................................................... - static { - long time = System.currentTimeMillis(); + static { + long time = System.currentTimeMillis(); -if (RDEBUG && (debuglevel > 6)) { -System.out.println("Algorithm Name: "+Rijndael_Properties.FULL_NAME); -System.out.println("Electronic Codebook (ECB) Mode"); -System.out.println(); -} - int ROOT = 0x11B; - int i, j = 0; + if (RDEBUG && (debuglevel > 6)) { + System.out.println("Algorithm Name: "+Rijndael_Properties.FULL_NAME); + System.out.println("Electronic Codebook (ECB) Mode"); + System.out.println(); + } + int ROOT = 0x11B; + int i, j = 0; - // - // produce log and alog tables, needed for multiplying in the - // field GF(2^m) (generator = 3) - // - alog[0] = 1; - for (i = 1; i < 256; i++) { - j = (alog[i-1] << 1) ^ alog[i-1]; - if ((j & 0x100) != 0) j ^= ROOT; - alog[i] = j; - } - for (i = 1; i < 255; i++) log[alog[i]] = i; - byte[][] A = new byte[][] { - {1, 1, 1, 1, 1, 0, 0, 0}, - {0, 1, 1, 1, 1, 1, 0, 0}, - {0, 0, 1, 1, 1, 1, 1, 0}, - {0, 0, 0, 1, 1, 1, 1, 1}, - {1, 0, 0, 0, 1, 1, 1, 1}, - {1, 1, 0, 0, 0, 1, 1, 1}, - {1, 1, 1, 0, 0, 0, 1, 1}, - {1, 1, 1, 1, 0, 0, 0, 1} + // + // produce log and alog tables, needed for multiplying in the + // field GF(2^m) (generator = 3) + // + alog[0] = 1; + for (i = 1; i < 256; i++) { + j = (alog[i-1] << 1) ^ alog[i-1]; + if ((j & 0x100) != 0) j ^= ROOT; + alog[i] = j; + } + for (i = 1; i < 255; i++) log[alog[i]] = i; + byte[][] A = new byte[][] { + {1, 1, 1, 1, 1, 0, 0, 0}, + {0, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 1, 1, 1, 0}, + {0, 0, 0, 1, 1, 1, 1, 1}, + {1, 0, 0, 0, 1, 1, 1, 1}, + {1, 1, 0, 0, 0, 1, 1, 1}, + {1, 1, 1, 0, 0, 0, 1, 1}, + {1, 1, 1, 1, 0, 0, 0, 1} }; - byte[] B = new byte[] { 0, 1, 1, 0, 0, 0, 1, 1}; + byte[] B = new byte[] { 0, 1, 1, 0, 0, 0, 1, 1}; - // - // substitution box based on F^{-1}(x) - // - int t; - byte[][] box = new byte[256][8]; - box[1][7] = 1; - for (i = 2; i < 256; i++) { - j = alog[255 - log[i]]; - for (t = 0; t < 8; t++) - box[i][t] = (byte)((j >>> (7 - t)) & 0x01); - } - // - // affine transform: box[i] <- B + A*box[i] - // - byte[][] cox = new byte[256][8]; - for (i = 0; i < 256; i++) - for (t = 0; t < 8; t++) { - cox[i][t] = B[t]; - for (j = 0; j < 8; j++) - cox[i][t] ^= A[t][j] * box[i][j]; - } - // - // S-boxes and inverse S-boxes - // - for (i = 0; i < 256; i++) { - S[i] = (byte)(cox[i][0] << 7); - for (t = 1; t < 8; t++) - S[i] ^= cox[i][t] << (7-t); - Si[S[i] & 0xFF] = (byte) i; - } - // - // T-boxes - // - byte[][] G = new byte[][] { - {2, 1, 1, 3}, - {3, 2, 1, 1}, - {1, 3, 2, 1}, - {1, 1, 3, 2} - }; - byte[][] AA = new byte[4][8]; - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) AA[i][j] = G[i][j]; - AA[i][i+4] = 1; - } - byte pivot, tmp; - byte[][] iG = new byte[4][4]; - for (i = 0; i < 4; i++) { - pivot = AA[i][i]; - if (pivot == 0) { - t = i + 1; - while ((AA[t][i] == 0) && (t < 4)) - t++; - if (t == 4) - throw new RuntimeException("G matrix is not invertible"); - else { - for (j = 0; j < 8; j++) { - tmp = AA[i][j]; - AA[i][j] = AA[t][j]; - AA[t][j] = tmp; - } - pivot = AA[i][i]; - } - } - for (j = 0; j < 8; j++) - if (AA[i][j] != 0) - AA[i][j] = (byte) - alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255]; - for (t = 0; t < 4; t++) - if (i != t) { - for (j = i+1; j < 8; j++) - AA[t][j] ^= mul(AA[i][j], AA[t][i]); - AA[t][i] = 0; - } - } - for (i = 0; i < 4; i++) - for (j = 0; j < 4; j++) iG[i][j] = AA[i][j + 4]; + // + // substitution box based on F^{-1}(x) + // + int t; + byte[][] box = new byte[256][8]; + box[1][7] = 1; + for (i = 2; i < 256; i++) { + j = alog[255 - log[i]]; + for (t = 0; t < 8; t++) + box[i][t] = (byte)((j >>> (7 - t)) & 0x01); + } + // + // affine transform: box[i] <- B + A*box[i] + // + byte[][] cox = new byte[256][8]; + for (i = 0; i < 256; i++) + for (t = 0; t < 8; t++) { + cox[i][t] = B[t]; + for (j = 0; j < 8; j++) + cox[i][t] ^= A[t][j] * box[i][j]; + } + // + // S-boxes and inverse S-boxes + // + for (i = 0; i < 256; i++) { + S[i] = (byte)(cox[i][0] << 7); + for (t = 1; t < 8; t++) + S[i] ^= cox[i][t] << (7-t); + Si[S[i] & 0xFF] = (byte) i; + } + // + // T-boxes + // + byte[][] G = new byte[][] { + {2, 1, 1, 3}, + {3, 2, 1, 1}, + {1, 3, 2, 1}, + {1, 1, 3, 2} + }; + byte[][] AA = new byte[4][8]; + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) AA[i][j] = G[i][j]; + AA[i][i+4] = 1; + } + byte pivot, tmp; + byte[][] iG = new byte[4][4]; + for (i = 0; i < 4; i++) { + pivot = AA[i][i]; + if (pivot == 0) { + t = i + 1; + while ((AA[t][i] == 0) && (t < 4)) + t++; + if (t == 4) + throw new RuntimeException("G matrix is not invertible"); + else { + for (j = 0; j < 8; j++) { + tmp = AA[i][j]; + AA[i][j] = AA[t][j]; + AA[t][j] = tmp; + } + pivot = AA[i][i]; + } + } + for (j = 0; j < 8; j++) + if (AA[i][j] != 0) + AA[i][j] = (byte) + alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255]; + for (t = 0; t < 4; t++) + if (i != t) { + for (j = i+1; j < 8; j++) + AA[t][j] ^= mul(AA[i][j], AA[t][i]); + AA[t][i] = 0; + } + } + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) iG[i][j] = AA[i][j + 4]; - int s; - for (t = 0; t < 256; t++) { - s = S[t]; - T1[t] = mul4(s, G[0]); - T2[t] = mul4(s, G[1]); - T3[t] = mul4(s, G[2]); - T4[t] = mul4(s, G[3]); + int s; + for (t = 0; t < 256; t++) { + s = S[t]; + T1[t] = mul4(s, G[0]); + T2[t] = mul4(s, G[1]); + T3[t] = mul4(s, G[2]); + T4[t] = mul4(s, G[3]); - s = Si[t]; - T5[t] = mul4(s, iG[0]); - T6[t] = mul4(s, iG[1]); - T7[t] = mul4(s, iG[2]); - T8[t] = mul4(s, iG[3]); + s = Si[t]; + T5[t] = mul4(s, iG[0]); + T6[t] = mul4(s, iG[1]); + T7[t] = mul4(s, iG[2]); + T8[t] = mul4(s, iG[3]); - U1[t] = mul4(t, iG[0]); - U2[t] = mul4(t, iG[1]); - U3[t] = mul4(t, iG[2]); - U4[t] = mul4(t, iG[3]); - } - // - // round constants - // - rcon[0] = 1; - int r = 1; - for (t = 1; t < 30; ) rcon[t++] = (byte)(r = mul(2, r)); + U1[t] = mul4(t, iG[0]); + U2[t] = mul4(t, iG[1]); + U3[t] = mul4(t, iG[2]); + U4[t] = mul4(t, iG[3]); + } + // + // round constants + // + rcon[0] = 1; + int r = 1; + for (t = 1; t < 30; ) rcon[t++] = (byte)(r = mul(2, r)); - time = System.currentTimeMillis() - time; + time = System.currentTimeMillis() - time; -if (RDEBUG && (debuglevel > 8)) { -System.out.println("=========="); -System.out.println(); -System.out.println("Static Data"); -System.out.println(); -System.out.println("S[]:"); for(i=0;i<16;i++) { for(j=0;j<16;j++) System.out.print("0x"+byteToString(S[i*16+j])+", "); System.out.println();} -System.out.println(); -System.out.println("Si[]:"); for(i=0;i<16;i++) { for(j=0;j<16;j++) System.out.print("0x"+byteToString(Si[i*16+j])+", "); System.out.println();} + if (RDEBUG && (debuglevel > 8)) { + System.out.println("=========="); + System.out.println(); + System.out.println("Static Data"); + System.out.println(); + System.out.println("S[]:"); for(i=0;i<16;i++) { for(j=0;j<16;j++) System.out.print("0x"+byteToString(S[i*16+j])+", "); System.out.println();} + System.out.println(); + System.out.println("Si[]:"); for(i=0;i<16;i++) { for(j=0;j<16;j++) System.out.print("0x"+byteToString(Si[i*16+j])+", "); System.out.println();} -System.out.println(); -System.out.println("iG[]:"); for(i=0;i<4;i++){for(j=0;j<4;j++) System.out.print("0x"+byteToString(iG[i][j])+", "); System.out.println();} + System.out.println(); + System.out.println("iG[]:"); for(i=0;i<4;i++){for(j=0;j<4;j++) System.out.print("0x"+byteToString(iG[i][j])+", "); System.out.println();} -System.out.println(); -System.out.println("T1[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T1[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("T2[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T2[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("T3[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T3[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("T4[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T4[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("T5[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T5[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("T6[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T6[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("T7[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T7[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("T8[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T8[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("T1[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T1[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("T2[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T2[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("T3[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T3[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("T4[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T4[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("T5[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T5[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("T6[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T6[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("T7[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T7[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("T8[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(T8[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("U1[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(U1[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("U2[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(U2[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("U3[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(U3[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("U4[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(U4[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("U1[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(U1[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("U2[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(U2[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("U3[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(U3[i*4+j])+", "); System.out.println();} + System.out.println(); + System.out.println("U4[]:"); for(i=0;i<64;i++){for(j=0;j<4;j++) System.out.print("0x"+intToString(U4[i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("rcon[]:"); for(i=0;i<5;i++){for(j=0;j<6;j++) System.out.print("0x"+byteToString(rcon[i*6+j])+", "); System.out.println();} + System.out.println(); + System.out.println("rcon[]:"); for(i=0;i<5;i++){for(j=0;j<6;j++) System.out.print("0x"+byteToString(rcon[i*6+j])+", "); System.out.println();} -System.out.println(); -System.out.println("Total initialization time: "+time+" ms."); -System.out.println(); -} - } + System.out.println(); + System.out.println("Total initialization time: "+time+" ms."); + System.out.println(); + } + } - // multiply two elements of GF(2^m) - static final int mul (int a, int b) { - return ((a != 0) && (b != 0)) ? - alog[(log[a & 0xFF] + log[b & 0xFF]) % 255] : - 0; - } + // multiply two elements of GF(2^m) + static final int mul (int a, int b) { + return ((a != 0) && (b != 0)) ? + alog[(log[a & 0xFF] + log[b & 0xFF]) % 255] : + 0; + } - // convenience method used in generating Transposition boxes - static final int mul4 (int a, byte[] b) { - if (a == 0) return 0; - a = log[a & 0xFF]; - int a0 = (b[0] != 0) ? alog[(a + log[b[0] & 0xFF]) % 255] & 0xFF : 0; - int a1 = (b[1] != 0) ? alog[(a + log[b[1] & 0xFF]) % 255] & 0xFF : 0; - int a2 = (b[2] != 0) ? alog[(a + log[b[2] & 0xFF]) % 255] & 0xFF : 0; - int a3 = (b[3] != 0) ? alog[(a + log[b[3] & 0xFF]) % 255] & 0xFF : 0; - return a0 << 24 | a1 << 16 | a2 << 8 | a3; - } + // convenience method used in generating Transposition boxes + static final int mul4 (int a, byte[] b) { + if (a == 0) return 0; + a = log[a & 0xFF]; + int a0 = (b[0] != 0) ? alog[(a + log[b[0] & 0xFF]) % 255] & 0xFF : 0; + int a1 = (b[1] != 0) ? alog[(a + log[b[1] & 0xFF]) % 255] & 0xFF : 0; + int a2 = (b[2] != 0) ? alog[(a + log[b[2] & 0xFF]) % 255] & 0xFF : 0; + int a3 = (b[3] != 0) ? alog[(a + log[b[3] & 0xFF]) % 255] & 0xFF : 0; + return a0 << 24 | a1 << 16 | a2 << 8 | a3; + } -// Basic API methods -//........................................................................... +// Basic API methods +// ........................................................................... - /** - * Convenience method to expand a user-supplied key material into a - * session key, assuming Rijndael's default block size (128-bit). - * - * @param k The 128/192/256-bit user-key to use. - * @exception InvalidKeyException If the key is invalid. - */ - private static final Object makeKey (byte[] k) throws InvalidKeyException { - return makeKey(k, BLOCK_SIZE); - } + /** + * Convenience method to expand a user-supplied key material into a + * session key, assuming Rijndael's default block size (128-bit). + * + * @param k The 128/192/256-bit user-key to use. + * @exception InvalidKeyException If the key is invalid. + */ + private static final Object makeKey (byte[] k) throws InvalidKeyException { + return makeKey(k, BLOCK_SIZE); + } - /** - * Convenience method to encrypt exactly one block of plaintext, assuming - * Rijndael's default block size (128-bit). - * - * @param in The plaintext. - * @param result The buffer into which to write the resulting ciphertext. - * @param inOffset Index of in from which to start considering data. - * @param sessionKey The session key to use for encryption. - */ - private static final void - blockEncrypt (byte[] in, byte[] result, int inOffset, Object sessionKey) { -if (RDEBUG) trace(IN, "blockEncrypt("+in+", "+inOffset+", "+sessionKey+ ')'); - int[][] Ke = (int[][]) ((Object[]) sessionKey)[0]; // extract encryption round keys - int ROUNDS = Ke.length - 1; - int[] Ker = Ke[0]; + /** + * Convenience method to encrypt exactly one block of plaintext, assuming + * Rijndael's default block size (128-bit). + * + * @param in The plaintext. + * @param result The buffer into which to write the resulting ciphertext. + * @param inOffset Index of in from which to start considering data. + * @param sessionKey The session key to use for encryption. + */ + private static final void + blockEncrypt (byte[] in, byte[] result, int inOffset, Object sessionKey) { + if (RDEBUG) trace(IN, "blockEncrypt("+in+", "+inOffset+", "+sessionKey+ ')'); + int[][] Ke = (int[][]) ((Object[]) sessionKey)[0]; // extract encryption round keys + int ROUNDS = Ke.length - 1; + int[] Ker = Ke[0]; - // plaintext to ints + key - int t0 = ((in[inOffset++] & 0xFF) << 24 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) ) ^ Ker[0]; - int t1 = ((in[inOffset++] & 0xFF) << 24 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) ) ^ Ker[1]; - int t2 = ((in[inOffset++] & 0xFF) << 24 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) ) ^ Ker[2]; - int t3 = ((in[inOffset++] & 0xFF) << 24 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) ) ^ Ker[3]; + // plaintext to ints + key + int t0 = ((in[inOffset++] & 0xFF) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ Ker[0]; + int t1 = ((in[inOffset++] & 0xFF) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ Ker[1]; + int t2 = ((in[inOffset++] & 0xFF) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ Ker[2]; + int t3 = ((in[inOffset++] & 0xFF) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ Ker[3]; - int a0, a1, a2, a3; - for (int r = 1; r < ROUNDS; r++) { // apply round transforms - Ker = Ke[r]; - a0 = (T1[(t0 >>> 24) & 0xFF] ^ - T2[(t1 >>> 16) & 0xFF] ^ - T3[(t2 >>> 8) & 0xFF] ^ - T4[ t3 & 0xFF] ) ^ Ker[0]; - a1 = (T1[(t1 >>> 24) & 0xFF] ^ - T2[(t2 >>> 16) & 0xFF] ^ - T3[(t3 >>> 8) & 0xFF] ^ - T4[ t0 & 0xFF] ) ^ Ker[1]; - a2 = (T1[(t2 >>> 24) & 0xFF] ^ - T2[(t3 >>> 16) & 0xFF] ^ - T3[(t0 >>> 8) & 0xFF] ^ - T4[ t1 & 0xFF] ) ^ Ker[2]; - a3 = (T1[(t3 >>> 24) & 0xFF] ^ - T2[(t0 >>> 16) & 0xFF] ^ - T3[(t1 >>> 8) & 0xFF] ^ - T4[ t2 & 0xFF] ) ^ Ker[3]; - t0 = a0; - t1 = a1; - t2 = a2; - t3 = a3; -if (RDEBUG && (debuglevel > 6)) System.out.println("CT"+r+ '=' +intToString(t0)+intToString(t1)+intToString(t2)+intToString(t3)); - } + int a0, a1, a2, a3; + for (int r = 1; r < ROUNDS; r++) { // apply round transforms + Ker = Ke[r]; + a0 = (T1[(t0 >>> 24) & 0xFF] ^ + T2[(t1 >>> 16) & 0xFF] ^ + T3[(t2 >>> 8) & 0xFF] ^ + T4[ t3 & 0xFF] ) ^ Ker[0]; + a1 = (T1[(t1 >>> 24) & 0xFF] ^ + T2[(t2 >>> 16) & 0xFF] ^ + T3[(t3 >>> 8) & 0xFF] ^ + T4[ t0 & 0xFF] ) ^ Ker[1]; + a2 = (T1[(t2 >>> 24) & 0xFF] ^ + T2[(t3 >>> 16) & 0xFF] ^ + T3[(t0 >>> 8) & 0xFF] ^ + T4[ t1 & 0xFF] ) ^ Ker[2]; + a3 = (T1[(t3 >>> 24) & 0xFF] ^ + T2[(t0 >>> 16) & 0xFF] ^ + T3[(t1 >>> 8) & 0xFF] ^ + T4[ t2 & 0xFF] ) ^ Ker[3]; + t0 = a0; + t1 = a1; + t2 = a2; + t3 = a3; + if (RDEBUG && (debuglevel > 6)) System.out.println("CT"+r+ '=' +intToString(t0)+intToString(t1)+intToString(t2)+intToString(t3)); + } - // last round is special - Ker = Ke[ROUNDS]; - int tt = Ker[0]; - result[ 0] = (byte)(S[(t0 >>> 24) & 0xFF] ^ (tt >>> 24)); - result[ 1] = (byte)(S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16)); - result[ 2] = (byte)(S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8)); - result[ 3] = (byte)(S[ t3 & 0xFF] ^ tt ); - tt = Ker[1]; - result[ 4] = (byte)(S[(t1 >>> 24) & 0xFF] ^ (tt >>> 24)); - result[ 5] = (byte)(S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16)); - result[ 6] = (byte)(S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8)); - result[ 7] = (byte)(S[ t0 & 0xFF] ^ tt ); - tt = Ker[2]; - result[ 8] = (byte)(S[(t2 >>> 24) & 0xFF] ^ (tt >>> 24)); - result[ 9] = (byte)(S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16)); - result[10] = (byte)(S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8)); - result[11] = (byte)(S[ t1 & 0xFF] ^ tt ); - tt = Ker[3]; - result[12] = (byte)(S[(t3 >>> 24) & 0xFF] ^ (tt >>> 24)); - result[13] = (byte)(S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16)); - result[14] = (byte)(S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8)); - result[15] = (byte)(S[ t2 & 0xFF] ^ tt ); -if (RDEBUG && (debuglevel > 6)) { -System.out.println("CT="+toString(result)); -System.out.println(); -} -if (RDEBUG) trace(OUT, "blockEncrypt()"); - } + // last round is special + Ker = Ke[ROUNDS]; + int tt = Ker[0]; + result[ 0] = (byte)(S[(t0 >>> 24) & 0xFF] ^ (tt >>> 24)); + result[ 1] = (byte)(S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16)); + result[ 2] = (byte)(S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8)); + result[ 3] = (byte)(S[ t3 & 0xFF] ^ tt ); + tt = Ker[1]; + result[ 4] = (byte)(S[(t1 >>> 24) & 0xFF] ^ (tt >>> 24)); + result[ 5] = (byte)(S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16)); + result[ 6] = (byte)(S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8)); + result[ 7] = (byte)(S[ t0 & 0xFF] ^ tt ); + tt = Ker[2]; + result[ 8] = (byte)(S[(t2 >>> 24) & 0xFF] ^ (tt >>> 24)); + result[ 9] = (byte)(S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16)); + result[10] = (byte)(S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8)); + result[11] = (byte)(S[ t1 & 0xFF] ^ tt ); + tt = Ker[3]; + result[12] = (byte)(S[(t3 >>> 24) & 0xFF] ^ (tt >>> 24)); + result[13] = (byte)(S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16)); + result[14] = (byte)(S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8)); + result[15] = (byte)(S[ t2 & 0xFF] ^ tt ); + if (RDEBUG && (debuglevel > 6)) { + System.out.println("CT="+toString(result)); + System.out.println(); + } + if (RDEBUG) trace(OUT, "blockEncrypt()"); + } - /** - * Convenience method to decrypt exactly one block of plaintext, assuming - * Rijndael's default block size (128-bit). - * - * @param in The ciphertext. - * @param result the resulting ciphertext - * @param inOffset Index of in from which to start considering data. - * @param sessionKey The session key to use for decryption. - */ - private static final void - blockDecrypt (byte[] in, byte[] result, int inOffset, Object sessionKey) { -if (RDEBUG) trace(IN, "blockDecrypt("+in+", "+inOffset+", "+sessionKey+ ')'); - int[][] Kd = (int[][]) ((Object[]) sessionKey)[1]; // extract decryption round keys - int ROUNDS = Kd.length - 1; - int[] Kdr = Kd[0]; + /** + * Convenience method to decrypt exactly one block of plaintext, assuming + * Rijndael's default block size (128-bit). + * + * @param in The ciphertext. + * @param result the resulting ciphertext + * @param inOffset Index of in from which to start considering data. + * @param sessionKey The session key to use for decryption. + */ + private static final void + blockDecrypt (byte[] in, byte[] result, int inOffset, Object sessionKey) { + if (RDEBUG) trace(IN, "blockDecrypt("+in+", "+inOffset+", "+sessionKey+ ')'); + int[][] Kd = (int[][]) ((Object[]) sessionKey)[1]; // extract decryption round keys + int ROUNDS = Kd.length - 1; + int[] Kdr = Kd[0]; - // ciphertext to ints + key - int t0 = ((in[inOffset++] & 0xFF) << 24 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) ) ^ Kdr[0]; - int t1 = ((in[inOffset++] & 0xFF) << 24 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) ) ^ Kdr[1]; - int t2 = ((in[inOffset++] & 0xFF) << 24 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) ) ^ Kdr[2]; - int t3 = ((in[inOffset++] & 0xFF) << 24 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) ) ^ Kdr[3]; + // ciphertext to ints + key + int t0 = ((in[inOffset++] & 0xFF) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ Kdr[0]; + int t1 = ((in[inOffset++] & 0xFF) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ Kdr[1]; + int t2 = ((in[inOffset++] & 0xFF) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ Kdr[2]; + int t3 = ((in[inOffset++] & 0xFF) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ Kdr[3]; - int a0, a1, a2, a3; - for (int r = 1; r < ROUNDS; r++) { // apply round transforms - Kdr = Kd[r]; - a0 = (T5[(t0 >>> 24) & 0xFF] ^ - T6[(t3 >>> 16) & 0xFF] ^ - T7[(t2 >>> 8) & 0xFF] ^ - T8[ t1 & 0xFF] ) ^ Kdr[0]; - a1 = (T5[(t1 >>> 24) & 0xFF] ^ - T6[(t0 >>> 16) & 0xFF] ^ - T7[(t3 >>> 8) & 0xFF] ^ - T8[ t2 & 0xFF] ) ^ Kdr[1]; - a2 = (T5[(t2 >>> 24) & 0xFF] ^ - T6[(t1 >>> 16) & 0xFF] ^ - T7[(t0 >>> 8) & 0xFF] ^ - T8[ t3 & 0xFF] ) ^ Kdr[2]; - a3 = (T5[(t3 >>> 24) & 0xFF] ^ - T6[(t2 >>> 16) & 0xFF] ^ - T7[(t1 >>> 8) & 0xFF] ^ - T8[ t0 & 0xFF] ) ^ Kdr[3]; - t0 = a0; - t1 = a1; - t2 = a2; - t3 = a3; -if (RDEBUG && (debuglevel > 6)) System.out.println("PT"+r+ '=' +intToString(t0)+intToString(t1)+intToString(t2)+intToString(t3)); - } + int a0, a1, a2, a3; + for (int r = 1; r < ROUNDS; r++) { // apply round transforms + Kdr = Kd[r]; + a0 = (T5[(t0 >>> 24) & 0xFF] ^ + T6[(t3 >>> 16) & 0xFF] ^ + T7[(t2 >>> 8) & 0xFF] ^ + T8[ t1 & 0xFF] ) ^ Kdr[0]; + a1 = (T5[(t1 >>> 24) & 0xFF] ^ + T6[(t0 >>> 16) & 0xFF] ^ + T7[(t3 >>> 8) & 0xFF] ^ + T8[ t2 & 0xFF] ) ^ Kdr[1]; + a2 = (T5[(t2 >>> 24) & 0xFF] ^ + T6[(t1 >>> 16) & 0xFF] ^ + T7[(t0 >>> 8) & 0xFF] ^ + T8[ t3 & 0xFF] ) ^ Kdr[2]; + a3 = (T5[(t3 >>> 24) & 0xFF] ^ + T6[(t2 >>> 16) & 0xFF] ^ + T7[(t1 >>> 8) & 0xFF] ^ + T8[ t0 & 0xFF] ) ^ Kdr[3]; + t0 = a0; + t1 = a1; + t2 = a2; + t3 = a3; + if (RDEBUG && (debuglevel > 6)) System.out.println("PT"+r+ '=' +intToString(t0)+intToString(t1)+intToString(t2)+intToString(t3)); + } - // last round is special - Kdr = Kd[ROUNDS]; - int tt = Kdr[0]; - result[ 0] = (byte)(Si[(t0 >>> 24) & 0xFF] ^ (tt >>> 24)); - result[ 1] = (byte)(Si[(t3 >>> 16) & 0xFF] ^ (tt >>> 16)); - result[ 2] = (byte)(Si[(t2 >>> 8) & 0xFF] ^ (tt >>> 8)); - result[ 3] = (byte)(Si[ t1 & 0xFF] ^ tt ); - tt = Kdr[1]; - result[ 4] = (byte)(Si[(t1 >>> 24) & 0xFF] ^ (tt >>> 24)); - result[ 5] = (byte)(Si[(t0 >>> 16) & 0xFF] ^ (tt >>> 16)); - result[ 6] = (byte)(Si[(t3 >>> 8) & 0xFF] ^ (tt >>> 8)); - result[ 7] = (byte)(Si[ t2 & 0xFF] ^ tt ); - tt = Kdr[2]; - result[ 8] = (byte)(Si[(t2 >>> 24) & 0xFF] ^ (tt >>> 24)); - result[ 9] = (byte)(Si[(t1 >>> 16) & 0xFF] ^ (tt >>> 16)); - result[10] = (byte)(Si[(t0 >>> 8) & 0xFF] ^ (tt >>> 8)); - result[11] = (byte)(Si[ t3 & 0xFF] ^ tt ); - tt = Kdr[3]; - result[12] = (byte)(Si[(t3 >>> 24) & 0xFF] ^ (tt >>> 24)); - result[13] = (byte)(Si[(t2 >>> 16) & 0xFF] ^ (tt >>> 16)); - result[14] = (byte)(Si[(t1 >>> 8) & 0xFF] ^ (tt >>> 8)); - result[15] = (byte)(Si[ t0 & 0xFF] ^ tt ); -if (RDEBUG && (debuglevel > 6)) { -System.out.println("PT="+toString(result)); -System.out.println(); -} -if (RDEBUG) trace(OUT, "blockDecrypt()"); - } + // last round is special + Kdr = Kd[ROUNDS]; + int tt = Kdr[0]; + result[ 0] = (byte)(Si[(t0 >>> 24) & 0xFF] ^ (tt >>> 24)); + result[ 1] = (byte)(Si[(t3 >>> 16) & 0xFF] ^ (tt >>> 16)); + result[ 2] = (byte)(Si[(t2 >>> 8) & 0xFF] ^ (tt >>> 8)); + result[ 3] = (byte)(Si[ t1 & 0xFF] ^ tt ); + tt = Kdr[1]; + result[ 4] = (byte)(Si[(t1 >>> 24) & 0xFF] ^ (tt >>> 24)); + result[ 5] = (byte)(Si[(t0 >>> 16) & 0xFF] ^ (tt >>> 16)); + result[ 6] = (byte)(Si[(t3 >>> 8) & 0xFF] ^ (tt >>> 8)); + result[ 7] = (byte)(Si[ t2 & 0xFF] ^ tt ); + tt = Kdr[2]; + result[ 8] = (byte)(Si[(t2 >>> 24) & 0xFF] ^ (tt >>> 24)); + result[ 9] = (byte)(Si[(t1 >>> 16) & 0xFF] ^ (tt >>> 16)); + result[10] = (byte)(Si[(t0 >>> 8) & 0xFF] ^ (tt >>> 8)); + result[11] = (byte)(Si[ t3 & 0xFF] ^ tt ); + tt = Kdr[3]; + result[12] = (byte)(Si[(t3 >>> 24) & 0xFF] ^ (tt >>> 24)); + result[13] = (byte)(Si[(t2 >>> 16) & 0xFF] ^ (tt >>> 16)); + result[14] = (byte)(Si[(t1 >>> 8) & 0xFF] ^ (tt >>> 8)); + result[15] = (byte)(Si[ t0 & 0xFF] ^ tt ); + if (RDEBUG && (debuglevel > 6)) { + System.out.println("PT="+toString(result)); + System.out.println(); + } + if (RDEBUG) trace(OUT, "blockDecrypt()"); + } - /** A basic symmetric encryption/decryption test. */ - public static boolean self_test() { return self_test(BLOCK_SIZE); } + /** A basic symmetric encryption/decryption test. */ + public static boolean self_test() { return self_test(BLOCK_SIZE); } -// Rijndael own methods -//........................................................................... +// Rijndael own methods +// ........................................................................... - /** @return The default length in bytes of the Algorithm input block. */ - public static final int blockSize() { return BLOCK_SIZE; } + /** @return The default length in bytes of the Algorithm input block. */ + public static final int blockSize() { return BLOCK_SIZE; } - /** - * Expand a user-supplied key material into a session key. - * - * @param k The 128/192/256-bit user-key to use. - * @param blockSize The block size in bytes of this Rijndael. - * @exception InvalidKeyException If the key is invalid. - */ - //TODO: This method doesn't really need synchronization. The only reason - //I can see for it to be synchronized is that it will consume 100% CPU (due to - //heavy calculations) when called. Probably should be unsynchronized if we - //want better support for dual+ CPU machines. /Iakin 2003-10-12 - //Concur: the class has no fields which are not final, and does - //not reference fields of any other classes. Control over how - //many simultaneous makeKey invocations should be allowed is - //a problem the callers should resolve among themselves. - //It is a fact that allowing no more than one makeKey on any given - //CPU will result in fewer cache misses. -- ejhuff 2003-10-12 - public final static synchronized Object makeKey (byte[] k, int blockSize) - throws InvalidKeyException { -if (RDEBUG) trace(IN, "makeKey("+k+", "+blockSize+ ')'); - if (k == null) - throw new InvalidKeyException("Empty key"); - if (!((k.length == 16) || (k.length == 24) || (k.length == 32))) - throw new InvalidKeyException("Incorrect key length"); - int ROUNDS = getRounds(k.length, blockSize); - int BC = blockSize / 4; - int[][] Ke = new int[ROUNDS + 1][BC]; // encryption round keys - int[][] Kd = new int[ROUNDS + 1][BC]; // decryption round keys - int ROUND_KEY_COUNT = (ROUNDS + 1) * BC; - int KC = k.length / 4; - int[] tk = new int[KC]; - int i, j; + /** + * Expand a user-supplied key material into a session key. + * + * @param k The 128/192/256-bit user-key to use. + * @param blockSize The block size in bytes of this Rijndael. + * @exception InvalidKeyException If the key is invalid. + */ + //TODO: This method doesn't really need synchronization. The only reason + //I can see for it to be synchronized is that it will consume 100% CPU (due to + //heavy calculations) when called. Probably should be unsynchronized if we + //want better support for dual+ CPU machines. /Iakin 2003-10-12 + //Concur: the class has no fields which are not final, and does + //not reference fields of any other classes. Control over how + //many simultaneous makeKey invocations should be allowed is + //a problem the callers should resolve among themselves. + //It is a fact that allowing no more than one makeKey on any given + //CPU will result in fewer cache misses. -- ejhuff 2003-10-12 + public final static synchronized Object makeKey (byte[] k, int blockSize) + throws InvalidKeyException { + if (RDEBUG) trace(IN, "makeKey("+k+", "+blockSize+ ')'); + if (k == null) + throw new InvalidKeyException("Empty key"); + if (!((k.length == 16) || (k.length == 24) || (k.length == 32))) + throw new InvalidKeyException("Incorrect key length"); + int ROUNDS = getRounds(k.length, blockSize); + int BC = blockSize / 4; + int[][] Ke = new int[ROUNDS + 1][BC]; // encryption round keys + int[][] Kd = new int[ROUNDS + 1][BC]; // decryption round keys + int ROUND_KEY_COUNT = (ROUNDS + 1) * BC; + int KC = k.length / 4; + int[] tk = new int[KC]; + int i, j; - // copy user material bytes into temporary ints - for (i = 0, j = 0; i < KC; ) - tk[i++] = (k[j++] & 0xFF) << 24 | - (k[j++] & 0xFF) << 16 | - (k[j++] & 0xFF) << 8 | - (k[j++] & 0xFF); - // copy values into round key arrays - int t = 0; - for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++) { - Ke[t / BC][t % BC] = tk[j]; - Kd[ROUNDS - (t / BC)][t % BC] = tk[j]; - } - int tt, rconpointer = 0; - while (t < ROUND_KEY_COUNT) { - // extrapolate using phi (the round key evolution function) - tt = tk[KC - 1]; - tk[0] ^= (S[(tt >>> 16) & 0xFF] & 0xFF) << 24 ^ - (S[(tt >>> 8) & 0xFF] & 0xFF) << 16 ^ - (S[ tt & 0xFF] & 0xFF) << 8 ^ - (S[(tt >>> 24) & 0xFF] & 0xFF) ^ - (rcon[rconpointer++] & 0xFF) << 24; - if (KC != 8) - for (i = 1, j = 0; i < KC; ) { - //tk[i++] ^= tk[j++]; - // The above line replaced with the code below in order to work around - // a bug in the kjc-1.4F java compiler (which has been reported). - tk[i] ^= tk[j++]; - i++; - } - else { - for (i = 1, j = 0; i < KC / 2; ) { - //tk[i++] ^= tk[j++]; - // The above line replaced with the code below in order to work around - // a bug in the kjc-1.4F java compiler (which has been reported). - tk[i] ^= tk[j++]; - i++; - } - tt = tk[KC / 2 - 1]; - tk[KC / 2] ^= (S[ tt & 0xFF] & 0xFF) ^ - (S[(tt >>> 8) & 0xFF] & 0xFF) << 8 ^ - (S[(tt >>> 16) & 0xFF] & 0xFF) << 16 ^ - (S[(tt >>> 24) & 0xFF] & 0xFF) << 24; - for (j = KC / 2, i = j + 1; i < KC; ) { - //tk[i++] ^= tk[j++]; - // The above line replaced with the code below in order to work around - // a bug in the kjc-1.4F java compiler (which has been reported). - tk[i] ^= tk[j++]; - i++; - } - } - // copy values into round key arrays - for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++) { - Ke[t / BC][t % BC] = tk[j]; - Kd[ROUNDS - (t / BC)][t % BC] = tk[j]; - } - } - for (int r = 1; r < ROUNDS; r++) // inverse MixColumn where needed - for (j = 0; j < BC; j++) { - tt = Kd[r][j]; - Kd[r][j] = U1[(tt >>> 24) & 0xFF] ^ - U2[(tt >>> 16) & 0xFF] ^ - U3[(tt >>> 8) & 0xFF] ^ - U4[ tt & 0xFF]; - } - // assemble the encryption (Ke) and decryption (Kd) round keys into - // one sessionKey object - Object[] sessionKey = new Object[] {Ke, Kd}; -if (RDEBUG) trace(OUT, "makeKey()"); - return sessionKey; - } + // copy user material bytes into temporary ints + for (i = 0, j = 0; i < KC; ) + tk[i++] = (k[j++] & 0xFF) << 24 | + (k[j++] & 0xFF) << 16 | + (k[j++] & 0xFF) << 8 | + (k[j++] & 0xFF); + // copy values into round key arrays + int t = 0; + for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++) { + Ke[t / BC][t % BC] = tk[j]; + Kd[ROUNDS - (t / BC)][t % BC] = tk[j]; + } + int tt, rconpointer = 0; + while (t < ROUND_KEY_COUNT) { + // extrapolate using phi (the round key evolution function) + tt = tk[KC - 1]; + tk[0] ^= (S[(tt >>> 16) & 0xFF] & 0xFF) << 24 ^ + (S[(tt >>> 8) & 0xFF] & 0xFF) << 16 ^ + (S[ tt & 0xFF] & 0xFF) << 8 ^ + (S[(tt >>> 24) & 0xFF] & 0xFF) ^ + (rcon[rconpointer++] & 0xFF) << 24; + if (KC != 8) + for (i = 1, j = 0; i < KC; ) { + //tk[i++] ^= tk[j++]; + // The above line replaced with the code below in order to work around + // a bug in the kjc-1.4F java compiler (which has been reported). + tk[i] ^= tk[j++]; + i++; + } + else { + for (i = 1, j = 0; i < KC / 2; ) { + //tk[i++] ^= tk[j++]; + // The above line replaced with the code below in order to work around + // a bug in the kjc-1.4F java compiler (which has been reported). + tk[i] ^= tk[j++]; + i++; + } + tt = tk[KC / 2 - 1]; + tk[KC / 2] ^= (S[ tt & 0xFF] & 0xFF) ^ + (S[(tt >>> 8) & 0xFF] & 0xFF) << 8 ^ + (S[(tt >>> 16) & 0xFF] & 0xFF) << 16 ^ + (S[(tt >>> 24) & 0xFF] & 0xFF) << 24; + for (j = KC / 2, i = j + 1; i < KC; ) { + //tk[i++] ^= tk[j++]; + // The above line replaced with the code below in order to work around + // a bug in the kjc-1.4F java compiler (which has been reported). + tk[i] ^= tk[j++]; + i++; + } + } + // copy values into round key arrays + for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++) { + Ke[t / BC][t % BC] = tk[j]; + Kd[ROUNDS - (t / BC)][t % BC] = tk[j]; + } + } + for (int r = 1; r < ROUNDS; r++) // inverse MixColumn where needed + for (j = 0; j < BC; j++) { + tt = Kd[r][j]; + Kd[r][j] = U1[(tt >>> 24) & 0xFF] ^ + U2[(tt >>> 16) & 0xFF] ^ + U3[(tt >>> 8) & 0xFF] ^ + U4[ tt & 0xFF]; + } + // assemble the encryption (Ke) and decryption (Kd) round keys into + // one sessionKey object + Object[] sessionKey = new Object[] {Ke, Kd}; + if (RDEBUG) trace(OUT, "makeKey()"); + return sessionKey; + } - /** - * Encrypt exactly one block of plaintext. - * - * @param in The plaintext. - * @param result The buffer into which to write the resulting ciphertext. - * @param inOffset Index of in from which to start considering data. - * @param sessionKey The session key to use for encryption. - * @param blockSize The block size in bytes of this Rijndael. - */ - public static final void - blockEncrypt (byte[] in, byte[] result, int inOffset, Object sessionKey, int blockSize) { - if (blockSize == BLOCK_SIZE) { - blockEncrypt(in, result, inOffset, sessionKey); - return; - } + /** + * Encrypt exactly one block of plaintext. + * + * @param in The plaintext. + * @param result The buffer into which to write the resulting ciphertext. + * @param inOffset Index of in from which to start considering data. + * @param sessionKey The session key to use for encryption. + * @param blockSize The block size in bytes of this Rijndael. + */ + public static final void + blockEncrypt (byte[] in, byte[] result, int inOffset, Object sessionKey, int blockSize) { + if (blockSize == BLOCK_SIZE) { + blockEncrypt(in, result, inOffset, sessionKey); + return; + } - int BC = blockSize / 4; - - int[] a = new int[BC]; - int[] t = new int[BC]; // temporary work array + int BC = blockSize / 4; - blockEncrypt(in, result, inOffset, sessionKey, blockSize, a, t); - } - - /** - * Encrypt exactly one block of plaintext. - * - * @param in The plaintext. - * @param result The buffer into which to write the resulting ciphertext. - * @param inOffset Index of in from which to start considering data. - * @param sessionKey The session key to use for encryption. - * @param blockSize The block size in bytes of this Rijndael. - */ - public static final void - blockEncrypt (byte[] in, byte[] result, int inOffset, Object sessionKey, int blockSize, int[] a, int[] t) { - if (blockSize == BLOCK_SIZE) { - blockEncrypt(in, result, inOffset, sessionKey); - return; - } -if (RDEBUG) trace(IN, "blockEncrypt("+in+", "+inOffset+", "+sessionKey+", "+blockSize+ ')'); - Object[] sKey = (Object[]) sessionKey; // extract encryption round keys - int[][] Ke = (int[][]) sKey[0]; + int[] a = new int[BC]; + int[] t = new int[BC]; // temporary work array - int BC = blockSize / 4; - int ROUNDS = Ke.length - 1; - int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2); - int s1 = shifts[SC][1][0]; - int s2 = shifts[SC][2][0]; - int s3 = shifts[SC][3][0]; - int i; - int j = 0, tt; + blockEncrypt(in, result, inOffset, sessionKey, blockSize, a, t); + } - for (i = 0; i < BC; i++) // plaintext to ints + key - t[i] = ((in[inOffset++] & 0xFF) << 24 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) ) ^ Ke[0][i]; - for (int r = 1; r < ROUNDS; r++) { // apply round transforms - for (i = 0; i < BC; i++) - a[i] = (T1[(t[ i ] >>> 24) & 0xFF] ^ - T2[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ - T3[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ - T4[ t[(i + s3) % BC] & 0xFF] ) ^ Ke[r][i]; - System.arraycopy(a, 0, t, 0, BC); -if (RDEBUG && (debuglevel > 6)) System.out.println("CT"+r+ '=' +toString(t)); - } - for (i = 0; i < BC; i++) { // last round is special - tt = Ke[ROUNDS][i]; - result[j++] = (byte)(S[(t[ i ] >>> 24) & 0xFF] ^ (tt >>> 24)); - result[j++] = (byte)(S[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16)); - result[j++] = (byte)(S[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8)); - result[j++] = (byte)(S[ t[(i + s3) % BC] & 0xFF] ^ tt); - } -if (RDEBUG && (debuglevel > 6)) { -System.out.println("CT="+toString(result)); -System.out.println(); -} -if (RDEBUG) trace(OUT, "blockEncrypt()"); - } + /** + * Encrypt exactly one block of plaintext. + * + * @param in The plaintext. + * @param result The buffer into which to write the resulting ciphertext. + * @param inOffset Index of in from which to start considering data. + * @param sessionKey The session key to use for encryption. + * @param blockSize The block size in bytes of this Rijndael. + */ + public static final void + blockEncrypt (byte[] in, byte[] result, int inOffset, Object sessionKey, int blockSize, int[] a, int[] t) { + if (blockSize == BLOCK_SIZE) { + blockEncrypt(in, result, inOffset, sessionKey); + return; + } + if (RDEBUG) trace(IN, "blockEncrypt("+in+", "+inOffset+", "+sessionKey+", "+blockSize+ ')'); + Object[] sKey = (Object[]) sessionKey; // extract encryption round keys + int[][] Ke = (int[][]) sKey[0]; - /** - * Decrypt exactly one block of ciphertext. - * - * @param in The ciphertext. - * @param result The resulting ciphertext. - * @param inOffset Index of in from which to start considering data. - * @param sessionKey The session key to use for decryption. - * @param blockSize The block size in bytes of this Rijndael. - */ - public static final void - blockDecrypt (byte[] in, byte[] result, int inOffset, Object sessionKey, int blockSize) { - if (blockSize == BLOCK_SIZE) { - blockDecrypt(in, result, inOffset, sessionKey); - return; - } + int BC = blockSize / 4; + int ROUNDS = Ke.length - 1; + int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2); + int s1 = shifts[SC][1][0]; + int s2 = shifts[SC][2][0]; + int s3 = shifts[SC][3][0]; + int i; + int j = 0, tt; -if (RDEBUG) trace(IN, "blockDecrypt("+in+", "+inOffset+", "+sessionKey+", "+blockSize+ ')'); - Object[] sKey = (Object[]) sessionKey; // extract decryption round keys - int[][] Kd = (int[][]) sKey[1]; + for (i = 0; i < BC; i++) // plaintext to ints + key + t[i] = ((in[inOffset++] & 0xFF) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ Ke[0][i]; + for (int r = 1; r < ROUNDS; r++) { // apply round transforms + for (i = 0; i < BC; i++) + a[i] = (T1[(t[ i ] >>> 24) & 0xFF] ^ + T2[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ + T3[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ + T4[ t[(i + s3) % BC] & 0xFF] ) ^ Ke[r][i]; + System.arraycopy(a, 0, t, 0, BC); + if (RDEBUG && (debuglevel > 6)) System.out.println("CT"+r+ '=' +toString(t)); + } + for (i = 0; i < BC; i++) { // last round is special + tt = Ke[ROUNDS][i]; + result[j++] = (byte)(S[(t[ i ] >>> 24) & 0xFF] ^ (tt >>> 24)); + result[j++] = (byte)(S[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16)); + result[j++] = (byte)(S[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8)); + result[j++] = (byte)(S[ t[(i + s3) % BC] & 0xFF] ^ tt); + } + if (RDEBUG && (debuglevel > 6)) { + System.out.println("CT="+toString(result)); + System.out.println(); + } + if (RDEBUG) trace(OUT, "blockEncrypt()"); + } - int BC = blockSize / 4; - int ROUNDS = Kd.length - 1; - int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2); - int s1 = shifts[SC][1][1]; - int s2 = shifts[SC][2][1]; - int s3 = shifts[SC][3][1]; - int[] a = new int[BC]; - int[] t = new int[BC]; // temporary work array - int i; - int j = 0, tt; + /** + * Decrypt exactly one block of ciphertext. + * + * @param in The ciphertext. + * @param result The resulting ciphertext. + * @param inOffset Index of in from which to start considering data. + * @param sessionKey The session key to use for decryption. + * @param blockSize The block size in bytes of this Rijndael. + */ + public static final void + blockDecrypt (byte[] in, byte[] result, int inOffset, Object sessionKey, int blockSize) { + if (blockSize == BLOCK_SIZE) { + blockDecrypt(in, result, inOffset, sessionKey); + return; + } - for (i = 0; i < BC; i++) // ciphertext to ints + key - t[i] = ((in[inOffset++] & 0xFF) << 24 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) ) ^ Kd[0][i]; - for (int r = 1; r < ROUNDS; r++) { // apply round transforms - for (i = 0; i < BC; i++) - a[i] = (T5[(t[ i ] >>> 24) & 0xFF] ^ - T6[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ - T7[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ - T8[ t[(i + s3) % BC] & 0xFF] ) ^ Kd[r][i]; - System.arraycopy(a, 0, t, 0, BC); -if (RDEBUG && (debuglevel > 6)) System.out.println("PT"+r+ '=' +toString(t)); - } - for (i = 0; i < BC; i++) { // last round is special - tt = Kd[ROUNDS][i]; - result[j++] = (byte)(Si[(t[ i ] >>> 24) & 0xFF] ^ (tt >>> 24)); - result[j++] = (byte)(Si[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16)); - result[j++] = (byte)(Si[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8)); - result[j++] = (byte)(Si[ t[(i + s3) % BC] & 0xFF] ^ tt); - } -if (RDEBUG && (debuglevel > 6)) { -System.out.println("PT="+toString(result)); -System.out.println(); -} -if (RDEBUG) trace(OUT, "blockDecrypt()"); - } + if (RDEBUG) trace(IN, "blockDecrypt("+in+", "+inOffset+", "+sessionKey+", "+blockSize+ ')'); + Object[] sKey = (Object[]) sessionKey; // extract decryption round keys + int[][] Kd = (int[][]) sKey[1]; - /** A basic symmetric encryption/decryption test for a given key size. */ - private static boolean self_test (int keysize) { -if (RDEBUG) trace(IN, "self_test("+keysize+ ')'); - boolean ok = false; - try { - byte[] kb = new byte[keysize]; - byte[] pt = new byte[BLOCK_SIZE]; - int i; + int BC = blockSize / 4; + int ROUNDS = Kd.length - 1; + int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2); + int s1 = shifts[SC][1][1]; + int s2 = shifts[SC][2][1]; + int s3 = shifts[SC][3][1]; + int[] a = new int[BC]; + int[] t = new int[BC]; // temporary work array + int i; + int j = 0, tt; - for (i = 0; i < keysize; i++) - kb[i] = (byte) i; - for (i = 0; i < BLOCK_SIZE; i++) - pt[i] = (byte) i; + for (i = 0; i < BC; i++) // ciphertext to ints + key + t[i] = ((in[inOffset++] & 0xFF) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ Kd[0][i]; + for (int r = 1; r < ROUNDS; r++) { // apply round transforms + for (i = 0; i < BC; i++) + a[i] = (T5[(t[ i ] >>> 24) & 0xFF] ^ + T6[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ + T7[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ + T8[ t[(i + s3) % BC] & 0xFF] ) ^ Kd[r][i]; + System.arraycopy(a, 0, t, 0, BC); + if (RDEBUG && (debuglevel > 6)) System.out.println("PT"+r+ '=' +toString(t)); + } + for (i = 0; i < BC; i++) { // last round is special + tt = Kd[ROUNDS][i]; + result[j++] = (byte)(Si[(t[ i ] >>> 24) & 0xFF] ^ (tt >>> 24)); + result[j++] = (byte)(Si[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16)); + result[j++] = (byte)(Si[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8)); + result[j++] = (byte)(Si[ t[(i + s3) % BC] & 0xFF] ^ tt); + } + if (RDEBUG && (debuglevel > 6)) { + System.out.println("PT="+toString(result)); + System.out.println(); + } + if (RDEBUG) trace(OUT, "blockDecrypt()"); + } -if (RDEBUG && (debuglevel > 6)) { -System.out.println("=========="); -System.out.println(); -System.out.println("KEYSIZE="+(8*keysize)); -System.out.println("KEY="+toString(kb)); -System.out.println(); -} - Object key = makeKey(kb, BLOCK_SIZE); + /** A basic symmetric encryption/decryption test for a given key size. */ + private static boolean self_test (int keysize) { + if (RDEBUG) trace(IN, "self_test("+keysize+ ')'); + boolean ok = false; + try { + byte[] kb = new byte[keysize]; + byte[] pt = new byte[BLOCK_SIZE]; + int i; -if (RDEBUG && (debuglevel > 6)) { -System.out.println("Intermediate Ciphertext Values (Encryption)"); -System.out.println(); -System.out.println("PT="+toString(pt)); -} - byte[] ct = new byte[BLOCK_SIZE]; - blockEncrypt(pt, ct, 0, key, BLOCK_SIZE); + for (i = 0; i < keysize; i++) + kb[i] = (byte) i; + for (i = 0; i < BLOCK_SIZE; i++) + pt[i] = (byte) i; -if (RDEBUG && (debuglevel > 6)) { -System.out.println("Intermediate Plaintext Values (Decryption)"); -System.out.println(); -System.out.println("CT="+toString(ct)); -} - byte[] cpt = new byte[BLOCK_SIZE]; - blockDecrypt(ct, cpt, 0, key, BLOCK_SIZE); + if (RDEBUG && (debuglevel > 6)) { + System.out.println("=========="); + System.out.println(); + System.out.println("KEYSIZE="+(8*keysize)); + System.out.println("KEY="+toString(kb)); + System.out.println(); + } + Object key = makeKey(kb, BLOCK_SIZE); - ok = areEqual(pt, cpt); - if (!ok) - throw new RuntimeException("Symmetric operation failed"); - } - catch (Exception x) { -if (RDEBUG && (debuglevel > 0)) { - debug("Exception encountered during self-test: " + x.getMessage()); - x.printStackTrace(); -} - } -if (RDEBUG && (debuglevel > 0)) debug("Self-test OK? " + ok); -if (RDEBUG) trace(OUT, "self_test()"); - return ok; - } + if (RDEBUG && (debuglevel > 6)) { + System.out.println("Intermediate Ciphertext Values (Encryption)"); + System.out.println(); + System.out.println("PT="+toString(pt)); + } + byte[] ct = new byte[BLOCK_SIZE]; + blockEncrypt(pt, ct, 0, key, BLOCK_SIZE); - /** - * Return The number of rounds for a given Rijndael's key and block sizes. - * - * @param keySize The size of the user key material in bytes. - * @param blockSize The desired block size in bytes. - * @return The number of rounds for a given Rijndael's key and - * block sizes. - */ - public static final int getRounds (int keySize, int blockSize) { - switch (keySize) { - case 16: - return blockSize == 16 ? 10 : (blockSize == 24 ? 12 : 14); - case 24: - return blockSize != 32 ? 12 : 14; - default: // 32 bytes = 256 bits - return 14; - } - } + if (RDEBUG && (debuglevel > 6)) { + System.out.println("Intermediate Plaintext Values (Decryption)"); + System.out.println(); + System.out.println("CT="+toString(ct)); + } + byte[] cpt = new byte[BLOCK_SIZE]; + blockDecrypt(ct, cpt, 0, key, BLOCK_SIZE); + ok = areEqual(pt, cpt); + if (!ok) + throw new RuntimeException("Symmetric operation failed"); + } + catch (Exception x) { + if (RDEBUG && (debuglevel > 0)) { + debug("Exception encountered during self-test: " + x.getMessage()); + x.printStackTrace(); + } + } + if (RDEBUG && (debuglevel > 0)) debug("Self-test OK? " + ok); + if (RDEBUG) trace(OUT, "self_test()"); + return ok; + } -// utility static methods (from cryptix.util.core ArrayUtil and Hex classes) -//........................................................................... + /** + * Return The number of rounds for a given Rijndael's key and block sizes. + * + * @param keySize The size of the user key material in bytes. + * @param blockSize The desired block size in bytes. + * @return The number of rounds for a given Rijndael's key and + * block sizes. + */ + public static final int getRounds (int keySize, int blockSize) { + switch (keySize) { + case 16: + return blockSize == 16 ? 10 : (blockSize == 24 ? 12 : 14); + case 24: + return blockSize != 32 ? 12 : 14; + default: // 32 bytes = 256 bits + return 14; + } + } - /** - * Compares two byte arrays for equality. - * - * @return true if the arrays have identical contents - */ - private static final boolean areEqual (byte[] a, byte[] b) { - int aLength = a.length; - if (aLength != b.length) - return false; - for (int i = 0; i < aLength; i++) - if (a[i] != b[i]) - return false; - return true; - } - /** - * Returns a string of 2 hexadecimal digits (most significant - * digit first) corresponding to the lowest 8 bits of <i>n</i>. - */ - private static final String byteToString (int n) { - char[] buf = { - HEX_DIGITS[(n >>> 4) & 0x0F], - HEX_DIGITS[ n & 0x0F] - }; - return new String(buf); - } +// utility static methods (from cryptix.util.core ArrayUtil and Hex classes) +// ........................................................................... - /** - * Returns a string of 8 hexadecimal digits (most significant - * digit first) corresponding to the integer <i>n</i>, which is - * treated as unsigned. - */ - private static final String intToString (int n) { - char[] buf = new char[8]; - for (int i = 7; i >= 0; i--) { - buf[i] = HEX_DIGITS[n & 0x0F]; - n >>>= 4; - } - return new String(buf); - } + /** + * Compares two byte arrays for equality. + * + * @return true if the arrays have identical contents + */ + private static final boolean areEqual (byte[] a, byte[] b) { + int aLength = a.length; + if (aLength != b.length) + return false; + for (int i = 0; i < aLength; i++) + if (a[i] != b[i]) + return false; + return true; + } - /** - * Returns a string of hexadecimal digits from a byte array. Each - * byte is converted to 2 hex symbols. - */ - private static final String toString (byte[] ba) { - int length = ba.length; - char[] buf = new char[length * 2]; - for (int i = 0, j = 0, k; i < length; ) { - k = ba[i++]; - buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; - buf[j++] = HEX_DIGITS[ k & 0x0F]; - } - return new String(buf); - } + /** + * Returns a string of 2 hexadecimal digits (most significant + * digit first) corresponding to the lowest 8 bits of <i>n</i>. + */ + private static final String byteToString (int n) { + char[] buf = { + HEX_DIGITS[(n >>> 4) & 0x0F], + HEX_DIGITS[ n & 0x0F] + }; + return new String(buf); + } - /** - * Returns a string of hexadecimal digits from an integer array. Each - * int is converted to 4 hex symbols. - */ - private static final String toString (int[] ia) { - int length = ia.length; - char[] buf = new char[length * 8]; - for (int i = 0, j = 0, k; i < length; i++) { - k = ia[i]; - buf[j++] = HEX_DIGITS[(k >>> 28) & 0x0F]; - buf[j++] = HEX_DIGITS[(k >>> 24) & 0x0F]; - buf[j++] = HEX_DIGITS[(k >>> 20) & 0x0F]; - buf[j++] = HEX_DIGITS[(k >>> 16) & 0x0F]; - buf[j++] = HEX_DIGITS[(k >>> 12) & 0x0F]; - buf[j++] = HEX_DIGITS[(k >>> 8) & 0x0F]; - buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; - buf[j++] = HEX_DIGITS[ k & 0x0F]; - } - return new String(buf); - } + /** + * Returns a string of 8 hexadecimal digits (most significant + * digit first) corresponding to the integer <i>n</i>, which is + * treated as unsigned. + */ + private static final String intToString (int n) { + char[] buf = new char[8]; + for (int i = 7; i >= 0; i--) { + buf[i] = HEX_DIGITS[n & 0x0F]; + n >>>= 4; + } + return new String(buf); + } + /** + * Returns a string of hexadecimal digits from a byte array. Each + * byte is converted to 2 hex symbols. + */ + private static final String toString (byte[] ba) { + int length = ba.length; + char[] buf = new char[length * 2]; + for (int i = 0, j = 0, k; i < length; ) { + k = ba[i++]; + buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; + buf[j++] = HEX_DIGITS[ k & 0x0F]; + } + return new String(buf); + } -// main(): use to generate the Intermediate Values KAT -//........................................................................... + /** + * Returns a string of hexadecimal digits from an integer array. Each + * int is converted to 4 hex symbols. + */ + private static final String toString (int[] ia) { + int length = ia.length; + char[] buf = new char[length * 8]; + for (int i = 0, j = 0, k; i < length; i++) { + k = ia[i]; + buf[j++] = HEX_DIGITS[(k >>> 28) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 24) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 20) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 16) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 12) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 8) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; + buf[j++] = HEX_DIGITS[ k & 0x0F]; + } + return new String(buf); + } - public static void main (String[] args) { - self_test(16); - self_test(24); - self_test(32); - } + +// main(): use to generate the Intermediate Values KAT +// ........................................................................... + + public static void main (String[] args) { + self_test(16); + self_test(24); + self_test(32); + } } Modified: trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Properties.java =================================================================== --- trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Properties.java 2007-03-17 13:11:29 UTC (rev 12176) +++ trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Properties.java 2007-03-17 13:15:06 UTC (rev 12177) @@ -28,162 +28,162 @@ */ public class Rijndael_Properties // implicit no-argument constructor { -// Constants and variables with relevant static code -//........................................................................... +// Constants and variables with relevant static code +// ........................................................................... - static final boolean GLOBAL_DEBUG = false; + static final boolean GLOBAL_DEBUG = false; - static final String ALGORITHM = "Rijndael"; - static final double VERSION = 0.1; - static final String FULL_NAME = ALGORITHM + " ver. " + VERSION; - static final String NAME = "Rijndael_Properties"; + static final String ALGORITHM = "Rijndael"; + static final double VERSION = 0.1; + static final String FULL_NAME = ALGORITHM + " ver. " + VERSION; + static final String NAME = "Rijndael_Properties"; - static final Properties properties = new Properties(); + static final Properties properties = new Properties(); - /** Default properties in case .properties file was not found. */ - private static final String[][] DEFAULT_PROPERTIES = { - {"Trace.Rijndael_Algorithm", "true"}, - {"Debug.Level.*", "1"}, - {"Debug.Level.Rijndael_Algorithm", "9"}, - }; + /** Default properties in case .properties file was not found. */ + private static final String[][] DEFAULT_PROPERTIES = { + {"Trace.Rijndael_Algorithm", "true"}, + {"Debug.Level.*", "1"}, + {"Debug.Level.Rijndael_Algorithm", "9"}, + }; - static { -if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Looking for " + ALGORITHM + " properties"); - String it = ALGORITHM + ".properties"; - InputStream is = Rijndael_Properties.class.getResourceAsStream(it); - boolean ok = is != null; - if (ok) - try { - properties.load(is); - is.close(); -if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Properties file loaded OK..."); - } catch (Exception x) { - ok = false; - } - if (!ok) { -if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": WARNING: Unable to load \"" + it + "\" from CLASSPATH."); -if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Will use default values instead..."); - int n = DEFAULT_PROPERTIES.length; - for (int i = 0; i < n; i++) - properties.put( - DEFAULT_PROPERTIES[i][0], DEFAULT_PROPERTIES[i][1]); -if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Default properties now set..."); - } - } + static { + if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Looking for " + ALGORITHM + " properties"); + String it = ALGORITHM + ".properties"; + InputStream is = Rijndael_Properties.class.getResourceAsStream(it); + boolean ok = is != null; + if (ok) + try { + properties.load(is); + is.close(); + if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Properties file loaded OK..."); + } catch (Exception x) { + ok = false; + } + if (!ok) { + if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": WARNING: Unable to load \"" + it + "\" from CLASSPATH."); + if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Will use default values instead..."); + int n = DEFAULT_PROPERTIES.length; + for (int i = 0; i < n; i++) + properties.put( + DEFAULT_PROPERTIES[i][0], DEFAULT_PROPERTIES[i][1]); + if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Default properties now set..."); + } + } -// Properties methods (excluding load and save, which are deliberately not -// supported). -//........................................................................... +// Properties methods (excluding load and save, which are deliberately not +// supported). +// ........................................................................... - /** Get the value of a property for this algorithm. */ - public static String getProperty (String key) { - return properties.getProperty(key); - } + /** Get the value of a property for this algorithm. */ + public static String getProperty (String key) { + return properties.getProperty(key); + } - /** - * Get the value of a property for this algorithm, or return - * <i>value</i> if the property was not set. - */ - public static String getProperty (String key, String value) { - return properties.getProperty(key, value); - } + /** + * Get the value of a property for this algorithm, or return + * <i>value</i> if the property was not set. + */ + public static String getProperty (String key, String value) { + return properties.getProperty(key, value); + } - /** List algorithm properties to the PrintStream <i>out</i>. */ - public static void list (PrintStream out) { - list(new PrintWriter(out, true)); - } + /** List algorithm properties to the PrintStream <i>out</i>. */ + public static void list (PrintStream out) { + list(new PrintWriter(out, true)); + } - /** List algorithm properties to the PrintWriter <i>out</i>. */ - public static void list (PrintWriter out) { - out.println("#"); - out.println("# ----- Begin "+ALGORITHM+" properties -----"); - out.println("#"); - String key, value; - Enumeration enu = properties.propertyNames(); - while (enu.hasMoreElements()) { - key = (String) enu.nextElement(); - value = getProperty(key); - out.println(key + " = " + value); - } - out.println("#"); - out.println("# ----- End "+ALGORITHM+" properties -----"); - } + /** List algorithm properties to the PrintWriter <i>out</i>. */ + public static void list (PrintWriter out) { + out.println("#"); + out.println("# ----- Begin "+ALGORITHM+" properties -----"); + out.println("#"); + String key, value; + Enumeration enu = properties.propertyNames(); + while (enu.hasMoreElements()) { + key = (String) enu.nextElement(); + value = getProperty(key); + out.println(key + " = " + value); + } + out.println("#"); + out.println("# ----- End "+ALGORITHM+" properties -----"); + } -// public synchronized void load(InputStream in) throws IOException {} +// public synchronized void load(InputStream in) throws IOException {} - public static Enumeration propertyNames() { - return properties.propertyNames(); - } + public static Enumeration propertyNames() { + return properties.propertyNames(); + } -// public void save (OutputStream os, String comment) {} +// public void save (OutputStream os, String comment) {} -// Developer support: Tracing and debugging enquiry methods (package-private) -//........................................................................... - - /** - * Return true if tracing is requested for a given class.<p> - * - * User indicates this by setting the tracing <code>boolean</code> - * property for <i>label</i> in the <code>(algorithm).properties</code> - * file. The property's key is "<code>Trace.<i>label</i></code>".<p> - * - * @param label The name of a class. - * @return True iff a boolean true value is set for a property with - * the key <code>Trace.<i>label</i></code>. - */ - static boolean isTraceable (String label) { - String s = getProperty("Trace." + label); - if (s == null) - return false; - return Boolean.valueOf(s).booleanValue(); - } +// Developer support: Tracing and debugging enquiry methods (package-private) +// ........................................................................... - /** - * Return the debug level for a given class.<p> - * - * User indicates this by setting the numeric property with key - * "<code>Debug.Level.<i>label</i></code>".<p> - * - * If this property is not set, "<code>Debug.Level.*</code>" is looked up - * next. If neither property is set, or if the first property found is - * not a valid decimal integer, then this method returns 0. - * - * @param label The name of a class. - * @return The required debugging level for the designated class. - */ - static int getLevel(String label) { - String s = getProperty("Debug.Level." + label); - if (s == null) { - s = getProperty("Debug.Level.*"); - if (s == null) - return 0; - } - try { - return Integer.parseInt(s); - } catch (NumberFormatException e) { - return 0; - } - } + /** + * Return true if tracing is requested for a given class.<p> + * + * User indicates this by setting the tracing <code>boolean</code> + * property for <i>label</i> in the <code>(algorithm).properties</code> + * file. The property's key is "<code>Trace.<i>label</i></code>".<p> + * + * @param label The name of a class. + * @return True iff a boolean true value is set for a property with + * the key <code>Trace.<i>label</i></code>. + */ + static boolean isTraceable (String label) { + String s = getProperty("Trace." + label); + if (s == null) + return false; + return Boolean.valueOf(s).booleanValue(); + } - /** - * Return the PrintWriter to which tracing and debugging output is to - * be sent.<p> - * - * User indicates this by setting the property with key <code>Output</code> - * to the literal <code>out</code> or <code>err</code>.<p> - * - * By default or if the set value is not allowed, <code>System.err</code> - * will be used. - */ - static PrintWriter getOutput() { - PrintWriter pw; - String name = getProperty("Output"); - if ((name != null) && name.equals("out")) - pw = new PrintWriter(System.out, true); - else - pw = new PrintWriter(System.err, true); - return pw; - } + /** + * Return the debug level for a given class.<p> + * + * User indicates this by setting the numeric property with key + * "<code>Debug.Level.<i>label</i></code>".<p> + * + * If this property is not set, "<code>Debug.Level.*</code>" is looked up + * next. If neither property is set, or if the first property found is + * not a valid decimal integer, then this method returns 0. + * + * @param label The name of a class. + * @return The required debugging level for the designated class. + */ + static int getLevel(String label) { + String s = getProperty("Debug.Level." + label); + if (s == null) { + s = getProperty("Debug.Level.*"); + if (s == null) + return 0; + } + try { + return Integer.parseInt(s); + } catch (NumberFormatException e) { + return 0; + } + } + + /** + * Return the PrintWriter to which tracing and debugging output is to + * be sent.<p> + * + * User indicates this by setting the property with key <code>Output</code> + * to the literal <code>out</code> or <code>err</code>.<p> + * + * By default or if the set value is not allowed, <code>System.err</code> + * will be used. + */ + static PrintWriter getOutput() { + PrintWriter pw; + String name = getProperty("Output"); + if ((name != null) && name.equals("out")) + pw = new PrintWriter(System.out, true); + else + pw = new PrintWriter(System.err, true); + return pw; + } }
