private static int F32(int k64Cnt, int x, int[] k32) { int b0 = Twofish_Algorithm.b0(x); int b1 = Twofish_Algorithm.b1(x); int b2 = Twofish_Algorithm.b2(x); int b3 = Twofish_Algorithm.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) ^ Twofish_Algorithm.b0(k0)] ^ MDS[1][(P[P_11][b1] & 0xFF) ^ Twofish_Algorithm.b1(k0)] ^ MDS[2][(P[P_21][b2] & 0xFF) ^ Twofish_Algorithm.b2(k0)] ^ MDS[3][(P[P_31][b3] & 0xFF) ^ Twofish_Algorithm.b3(k0)]; break; case 0: // same as 4 b0 = (P[P_04][b0] & 0xFF) ^ Twofish_Algorithm.b0(k3); b1 = (P[P_14][b1] & 0xFF) ^ Twofish_Algorithm.b1(k3); b2 = (P[P_24][b2] & 0xFF) ^ Twofish_Algorithm.b2(k3); b3 = (P[P_34][b3] & 0xFF) ^ Twofish_Algorithm.b3(k3); goto case 3; case 3: b0 = (P[P_03][b0] & 0xFF) ^ Twofish_Algorithm.b0(k2); b1 = (P[P_13][b1] & 0xFF) ^ Twofish_Algorithm.b1(k2); b2 = (P[P_23][b2] & 0xFF) ^ Twofish_Algorithm.b2(k2); b3 = (P[P_33][b3] & 0xFF) ^ Twofish_Algorithm.b3(k2); goto case 2; case 2: // 128-bit keys (optimize for this case) result = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ Twofish_Algorithm.b0(k1)] & 0xFF) ^ Twofish_Algorithm.b0(k0)] ^ MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ Twofish_Algorithm.b1(k1)] & 0xFF) ^ Twofish_Algorithm.b1(k0)] ^ MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ Twofish_Algorithm.b2(k1)] & 0xFF) ^ Twofish_Algorithm.b2(k0)] ^ MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ Twofish_Algorithm.b3(k1)] & 0xFF) ^ Twofish_Algorithm.b3(k0)]; break; } return(result); }
// EF // Basic API methods //........................................................................... /// <summary> Expand a user-supplied key material into a session key. /// * /// </summary> /// <param name="key"> The 64/128/192/256-bit user-key to use. /// </param> /// <returns> This cipher's round keys. /// </returns> /// <exception cref=""> ApplicationException If the key is invalid. /// /// </exception> public static System.Object makeKey(byte[] k) { lock (typeof(Twofish.Twofish_Algorithm)) { if (DEBUG) { trace(IN, "makeKey(" + k + ")"); } if (k == null) { //UPGRADE_TODO: Constructor java.security.ApplicationException.ApplicationException was not converted. 'ms-help://MS.VSCC/commoner/redir/redirect.htm?keyword="jlca1095"' throw new ApplicationException("Empty key"); } int length = k.Length; if (!(length == 8 || length == 16 || length == 24 || length == 32)) { //UPGRADE_TODO: Constructor java.security.ApplicationException.ApplicationException was not converted. 'ms-help://MS.VSCC/commoner/redir/redirect.htm?keyword="jlca1095"' throw new ApplicationException("Incorrect key length"); } if (DEBUG && debuglevel > 7) { System.Console.Out.WriteLine("Intermediate Session Key Values"); System.Console.Out.WriteLine(); System.Console.Out.WriteLine("Raw=" + toString(k)); System.Console.Out.WriteLine(); } 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 | URShift(B, 24); A += B; subKeys[2 * i] = A; // combine with a PHT A += B; subKeys[2 * i + 1] = A << SK_ROTL | URShift(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) ^ Twofish_Algorithm.b0(k0)]; sBox[2 * i + 1] = MDS[1][(P[P_11][b1] & 0xFF) ^ Twofish_Algorithm.b1(k0)]; sBox[0x200 + 2 * i] = MDS[2][(P[P_21][b2] & 0xFF) ^ Twofish_Algorithm.b2(k0)]; sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][b3] & 0xFF) ^ Twofish_Algorithm.b3(k0)]; break; case 0: // same as 4 b0 = (P[P_04][b0] & 0xFF) ^ Twofish_Algorithm.b0(k3); b1 = (P[P_14][b1] & 0xFF) ^ Twofish_Algorithm.b1(k3); b2 = (P[P_24][b2] & 0xFF) ^ Twofish_Algorithm.b2(k3); b3 = (P[P_34][b3] & 0xFF) ^ Twofish_Algorithm.b3(k3); goto case 3; case 3: b0 = (P[P_03][b0] & 0xFF) ^ Twofish_Algorithm.b0(k2); b1 = (P[P_13][b1] & 0xFF) ^ Twofish_Algorithm.b1(k2); b2 = (P[P_23][b2] & 0xFF) ^ Twofish_Algorithm.b2(k2); b3 = (P[P_33][b3] & 0xFF) ^ Twofish_Algorithm.b3(k2); goto case 2; case 2: // 128-bit keys sBox[2 * i] = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ Twofish_Algorithm.b0(k1)] & 0xFF) ^ Twofish_Algorithm.b0(k0)]; sBox[2 * i + 1] = MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ Twofish_Algorithm.b1(k1)] & 0xFF) ^ Twofish_Algorithm.b1(k0)]; sBox[0x200 + 2 * i] = MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ Twofish_Algorithm.b2(k1)] & 0xFF) ^ Twofish_Algorithm.b2(k0)]; sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ Twofish_Algorithm.b3(k1)] & 0xFF) ^ Twofish_Algorithm.b3(k0)]; break; } } System.Object sessionKey = new System.Object[] { sBox, subKeys }; if (DEBUG && debuglevel > 7) { System.Console.Out.WriteLine("S-box[]:"); for (i = 0; i < 64; i++) { for (j = 0; j < 4; j++) { System.Console.Out.Write("0x" + intToString(sBox[i * 4 + j]) + ", "); } System.Console.Out.WriteLine(); } System.Console.Out.WriteLine(); for (i = 0; i < 64; i++) { for (j = 0; j < 4; j++) { System.Console.Out.Write("0x" + intToString(sBox[256 + i * 4 + j]) + ", "); } System.Console.Out.WriteLine(); } System.Console.Out.WriteLine(); for (i = 0; i < 64; i++) { for (j = 0; j < 4; j++) { System.Console.Out.Write("0x" + intToString(sBox[512 + i * 4 + j]) + ", "); } System.Console.Out.WriteLine(); } System.Console.Out.WriteLine(); for (i = 0; i < 64; i++) { for (j = 0; j < 4; j++) { System.Console.Out.Write("0x" + intToString(sBox[768 + i * 4 + j]) + ", "); } System.Console.Out.WriteLine(); } System.Console.Out.WriteLine(); System.Console.Out.WriteLine("User (odd, even) keys --> S-Box keys:"); for (i = 0; i < k64Cnt; i++) { System.Console.Out.WriteLine("0x" + intToString(k32o[i]) + " 0x" + intToString(k32e[i]) + " --> 0x" + intToString(sBoxKey[k64Cnt - 1 - i])); } System.Console.Out.WriteLine(); System.Console.Out.WriteLine("Round keys:"); for (i = 0; i < ROUND_SUBKEYS + 2 * ROUNDS; i += 2) { System.Console.Out.WriteLine("0x" + intToString(subKeys[i]) + " 0x" + intToString(subKeys[i + 1])); } System.Console.Out.WriteLine(); } if (DEBUG) { trace(OUT, "makeKey()"); } return(sessionKey); } }