?? twofish.java
字號:
+ ", "); } System.out.println(); } System.out.println(); System.out.println("MDS[3][]:"); for (i = 0; i < 64; i++) { for (j = 0; j < 4; j++) { System.out.print("0x" + Util.toString(MDS[3][i * 4 + j]) + ", "); } System.out.println(); } System.out.println(); System.out.println("Total initialization time: " + time + " ms."); System.out.println(); } } private static final int LFSR1(int x) { return (x >> 1) ^ ((x & 0x01) != 0 ? GF256_FDBK_2 : 0); } private static final int LFSR2(int x) { return (x >> 2) ^ ((x & 0x02) != 0 ? GF256_FDBK_2 : 0) ^ ((x & 0x01) != 0 ? GF256_FDBK_4 : 0); } // private static final int Mx_1(int x) { // return x; // } private static final int Mx_X(int x) { // 5B return x ^ LFSR2(x); } private static final int Mx_Y(int x) { // EF return x ^ LFSR1(x) ^ LFSR2(x); } // Constructor(s) // ------------------------------------------------------------------------- /** Trivial 0-arguments constructor. */ public Twofish() { super(Registry.TWOFISH_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE); } // Class methods // ------------------------------------------------------------------------- private static final int b0(int x) { return x & 0xFF; } private static final int b1(int x) { return (x >>> 8) & 0xFF; } private static final int b2(int x) { return (x >>> 16) & 0xFF; } private static final int b3(int x) { return (x >>> 24) & 0xFF; } /** * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box 32-bit * entity from two key material 32-bit entities. * * @param k0 1st 32-bit entity. * @param k1 2nd 32-bit entity. * @return remainder polynomial generated using RS code */ private static final int RS_MDS_Encode(int k0, int k1) { int r = k1; int i; for (i = 0; i < 4; i++) { // shift 1 byte at a time r = RS_rem(r); } r ^= k0; for (i = 0; i < 4; i++) { r = RS_rem(r); } return r; } /** * Reed-Solomon code parameters: (12, 8) reversible code:<p> * <pre> * g(x) = x**4 + (a + 1/a) x**3 + a x**2 + (a + 1/a) x + 1 * </pre> * where a = primitive root of field generator 0x14D */ private static final int RS_rem(int x) { int b = (x >>> 24) & 0xFF; int g2 = ((b << 1) ^ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xFF; int g3 = (b >>> 1) ^ ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0) ^ g2; int result = (x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b; return result; } private static final int F32(int k64Cnt, int x, int[] k32) { int b0 = b0(x); int b1 = b1(x); int b2 = b2(x); int b3 = b3(x); int k0 = k32[0]; int k1 = k32[1]; int k2 = k32[2]; int k3 = k32[3]; int result = 0; switch (k64Cnt & 3) { case 1: result = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)] ^ MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)] ^ MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)] ^ MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)]; break; case 0: // same as 4 b0 = (P[P_04][b0] & 0xFF) ^ b0(k3); b1 = (P[P_14][b1] & 0xFF) ^ b1(k3); b2 = (P[P_24][b2] & 0xFF) ^ b2(k3); b3 = (P[P_34][b3] & 0xFF) ^ b3(k3); case 3: b0 = (P[P_03][b0] & 0xFF) ^ b0(k2); b1 = (P[P_13][b1] & 0xFF) ^ b1(k2); b2 = (P[P_23][b2] & 0xFF) ^ b2(k2); b3 = (P[P_33][b3] & 0xFF) ^ b3(k2); case 2: // 128-bit keys (optimize for this case) result = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF) ^ b0(k0)] ^ MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF) ^ b1(k0)] ^ MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF) ^ b2(k0)] ^ MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF) ^ b3(k0)]; break; } return result; } private static final int Fe32(int[] sBox, int x, int R) { return sBox[2 * _b(x, R)] ^ sBox[2 * _b(x, R + 1) + 1] ^ sBox[0x200 + 2 * _b(x, R + 2)] ^ sBox[0x200 + 2 * _b(x, R + 3) + 1]; } private static final int _b(int x, int N) { // int result = 0; // switch (N%4) { // case 0: result = b0(x); break; // case 1: result = b1(x); break; // case 2: result = b2(x); break; // case 3: result = b3(x); break; // } // return result; // profiling shows that the code spends too long in this method. // following constructs seem to improve, albeit marginally, performance switch (N % 4) { case 0: return x & 0xFF; case 1: return (x >>> 8) & 0xFF; case 2: return (x >>> 16) & 0xFF; default: return x >>> 24; } } // Instance methods // ------------------------------------------------------------------------- // java.lang.Cloneable interface implementation ---------------------------- public Object clone() { Twofish result = new Twofish(); result.currentBlockSize = this.currentBlockSize; return result; } // IBlockCipherSpi interface implementation -------------------------------- public Iterator blockSizes() { ArrayList al = new ArrayList(); al.add(new Integer(DEFAULT_BLOCK_SIZE)); return Collections.unmodifiableList(al).iterator(); } public Iterator keySizes() { ArrayList al = new ArrayList(); al.add(new Integer(8)); // 64-bit al.add(new Integer(16)); // 128-bit al.add(new Integer(24)); // 192-bit al.add(new Integer(32)); // 256-bit return Collections.unmodifiableList(al).iterator(); } /** * <p>Expands a user-supplied key material into a session key for a designated * <i>block size</i>.</p> * * @param k the 64/128/192/256-bit user-key to use. * @param bs the desired block size in bytes. * @return an Object encapsulating the session key. * @exception IllegalArgumentException if the block size is not 16 (128-bit). * @exception InvalidKeyException if the key data is invalid. */ public Object makeKey(byte[] k, int bs) throws InvalidKeyException { if (bs != DEFAULT_BLOCK_SIZE) { throw new IllegalArgumentException(); } if (k == null) { throw new InvalidKeyException("Empty key"); } int length = k.length; if (!(length == 8 || length == 16 || length == 24 || length == 32)) { throw new InvalidKeyException("Incorrect key length"); } int k64Cnt = length / 8; int subkeyCnt = ROUND_SUBKEYS + 2 * ROUNDS; int[] k32e = new int[4]; // even 32-bit entities int[] k32o = new int[4]; // odd 32-bit entities int[] sBoxKey = new int[4]; // // split user key material into even and odd 32-bit entities and // compute S-box keys using (12, 8) Reed-Solomon code over GF(256) // int i, j, offset = 0; for (i = 0, j = k64Cnt - 1; i < 4 && offset < length; i++, j--) { k32e[i] = (k[offset++] & 0xFF) | (k[offset++] & 0xFF) << 8 | (k[offset++] & 0xFF) << 16 | (k[offset++] & 0xFF) << 24; k32o[i] = (k[offset++] & 0xFF) | (k[offset++] & 0xFF) << 8 | (k[offset++] & 0xFF) << 16 | (k[offset++] & 0xFF) << 24; sBoxKey[j] = RS_MDS_Encode(k32e[i], k32o[i]); // reverse order } // compute the round decryption subkeys for PHT. these same subkeys // will be used in encryption but will be applied in reverse order. int q, A, B; int[] subKeys = new int[subkeyCnt]; for (i = q = 0; i < subkeyCnt / 2; i++, q += SK_STEP) { A = F32(k64Cnt, q, k32e); // A uses even key entities B = F32(k64Cnt, q + SK_BUMP, k32o); // B uses odd key entities B = B << 8 | B >>> 24; A += B; subKeys[2 * i] = A; // combine with a PHT A += B; subKeys[2 * i + 1] = A << SK_ROTL | A >>> (32 - SK_ROTL); } // fully expand the table for speed int k0 = sBoxKey[0]; int k1 = sBoxKey[1]; int k2 = sBoxKey[2]; int k3 = sBoxKey[3]; int b0, b1, b2, b3; int[] sBox = new int[4 * 256]; for (i = 0; i < 256; i++) { b0 = b1 = b2 = b3 = i; switch (k64Cnt & 3) { case 1: sBox[2 * i] = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)];
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -