📄 rijndael_algorithm.java
字号:
} // assemble the encryption (Ke) and decryption (Kd) round keys into // one sessionKey object Object[] sessionKey = new Object[] {Ke, Kd};if (DEBUG) trace(OUT, "makeKey()"); return sessionKey; } /** * Encrypt exactly one block of plaintext. * * @param in The plaintext. * @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. * @return The ciphertext generated from a plaintext using the session key. */ public static byte[] blockEncrypt (byte[] in, int inOffset, Object sessionKey, int blockSize) { if (blockSize == BLOCK_SIZE) return blockEncrypt(in, inOffset, sessionKey);if (DEBUG) trace(IN, "blockEncrypt("+in+", "+inOffset+", "+sessionKey+", "+blockSize+")"); Object[] sKey = (Object[]) sessionKey; // extract encryption round keys int[][] Ke = (int[][]) sKey[0]; 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[] a = new int[BC]; int[] t = new int[BC]; // temporary work array int i; byte[] result = new byte[blockSize]; // the resulting ciphertext int j = 0, tt; 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 (DEBUG && 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 (DEBUG && debuglevel > 6) {System.out.println("CT="+toString(result));System.out.println();}if (DEBUG) trace(OUT, "blockEncrypt()"); return result; } /** * Decrypt exactly one block of ciphertext. * * @param in The 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. * @return The plaintext generated from a ciphertext using the session key. */ public static byte[] blockDecrypt (byte[] in, int inOffset, Object sessionKey, int blockSize) { if (blockSize == BLOCK_SIZE) return blockDecrypt(in, inOffset, sessionKey);if (DEBUG) trace(IN, "blockDecrypt("+in+", "+inOffset+", "+sessionKey+", "+blockSize+")"); Object[] sKey = (Object[]) sessionKey; // extract decryption round keys int[][] Kd = (int[][]) sKey[1]; 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; byte[] result = new byte[blockSize]; // the resulting plaintext int j = 0, tt; 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 (DEBUG && 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 (DEBUG && debuglevel > 6) {System.out.println("PT="+toString(result));System.out.println();}if (DEBUG) trace(OUT, "blockDecrypt()"); return result; } /** A basic symmetric encryption/decryption test for a given key size. */ private static boolean self_test (int keysize) {if (DEBUG) trace(IN, "self_test("+keysize+")"); boolean ok = false; try { byte[] kb = new byte[keysize]; byte[] pt = new byte[BLOCK_SIZE]; int i; for (i = 0; i < keysize; i++) kb[i] = (byte) i; for (i = 0; i < BLOCK_SIZE; i++) pt[i] = (byte) i;if (DEBUG && 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);if (DEBUG && debuglevel > 6) {System.out.println("Intermediate Ciphertext Values (Encryption)");System.out.println();System.out.println("PT="+toString(pt));} byte[] ct = blockEncrypt(pt, 0, key, BLOCK_SIZE);if (DEBUG && debuglevel > 6) {System.out.println("Intermediate Plaintext Values (Decryption)");System.out.println();System.out.println("CT="+toString(ct));} byte[] cpt = blockDecrypt(ct, 0, key, BLOCK_SIZE); ok = areEqual(pt, cpt); if (!ok) throw new RuntimeException("Symmetric operation failed"); } catch (Exception x) {if (DEBUG && debuglevel > 0) { debug("Exception encountered during self-test: " + x.getMessage()); x.printStackTrace();} }if (DEBUG && debuglevel > 0) debug("Self-test OK? " + ok);if (DEBUG) trace(OUT, "self_test()"); return ok; } /** * 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 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; } }// utility static methods (from cryptix.util.core ArrayUtil and Hex classes)//........................................................................... /** * Compares two byte arrays for equality. * * @return true if the arrays have identical contents */ private static 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 String byteToString (int n) { char[] buf = { HEX_DIGITS[(n >>> 4) & 0x0F], HEX_DIGITS[ n & 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 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 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 hexadecimal digits from an integer array. Each * int is converted to 4 hex symbols. */ private static 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); }// main(): use to generate the Intermediate Values KAT//........................................................................... public static void main (String[] args) { self_test(16); self_test(24); self_test(32); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -