📄 rijndael_algorithm.java
字号:
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("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();
}
}
// 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;
}
// 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 key
* The 128/192/256-bit user-key to use.
* @exception InvalidKeyException
* If the key is invalid.
*/
public static 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 inOffset
* Index of in from which to start considering data.
* @param sessionKey
* The session key to use for encryption.
* @return The ciphertext generated from a plaintext using the session key.
*/
public static byte[] blockEncrypt(byte[] in, int inOffset, Object sessionKey) {
if (DEBUG)
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];
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 (DEBUG && debuglevel > 6)
System.out.println("CT" + r + "=" + intToString(t0)
+ intToString(t1) + intToString(t2) + intToString(t3));
}
// last round is special
byte[] result = new byte[BLOCK_SIZE]; // the resulting ciphertext
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 (DEBUG && debuglevel > 6) {
System.out.println("CT=" + toString(result));
System.out.println();
}
if (DEBUG)
trace(OUT, "blockEncrypt()");
return result;
}
/**
* Convenience method to decrypt exactly one block of plaintext, assuming
* Rijndael's default block size (128-bit).
*
* @param in
* The ciphertext.
* @param inOffset
* Index of in from which to start considering data.
* @param sessionKey
* The session key to use for decryption.
* @return The plaintext generated from a ciphertext using the session key.
*/
public static byte[] blockDecrypt(byte[] in, int inOffset, Object sessionKey) {
if (DEBUG)
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];
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 (DEBUG && debuglevel > 6)
System.out.println("PT" + r + "=" + intToString(t0)
+ intToString(t1) + intToString(t2) + intToString(t3));
}
// last round is special
byte[] result = new byte[16]; // the resulting plaintext
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 (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. */
public static boolean self_test() {
return self_test(BLOCK_SIZE);
}
// Rijndael own methods
// ...........................................................................
/** @return The default length in bytes of the Algorithm input block. */
public static int blockSize() {
return BLOCK_SIZE;
}
/**
* Expand a user-supplied key material into a session key.
*
* @param key
* 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.
*/
public static synchronized Object makeKey(byte[] k, int blockSize)
throws InvalidKeyException {
if (DEBUG)
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -