📄 aes.java
字号:
((Se[(temp ) & 0xff] & 0xff) << 8) |
((Se[(temp >>> 24) ] & 0xff));
temp ^= rcon[r++];
} else if (Nk == 8 && n == 4) {
temp =
((Se[(temp >>> 24) ] ) << 24) |
((Se[(temp >>> 16) & 0xff] & 0xff) << 16) |
((Se[(temp >>> 8) & 0xff] & 0xff) << 8) |
((Se[(temp ) & 0xff] & 0xff));
}
rek[i] = rek[i - Nk] ^ temp;
}
temp = 0;
}
/**
* Compute the decryption schedule from the encryption schedule .
*/
private final void invertKey() {
int d = 0, e = 4*Nr, w;
/*
* apply the inverse MixColumn transform to all round keys
* but the first and the last:
*/
rdk[d ] = rek[e ];
rdk[d + 1] = rek[e + 1];
rdk[d + 2] = rek[e + 2];
rdk[d + 3] = rek[e + 3];
d += 4;
e -= 4;
for (int r = 1; r < Nr; r++) {
w = rek[e ];
rdk[d ] =
Td0[Se[(w >>> 24) ] & 0xff] ^
Td1[Se[(w >>> 16) & 0xff] & 0xff] ^
Td2[Se[(w >>> 8) & 0xff] & 0xff] ^
Td3[Se[(w ) & 0xff] & 0xff];
w = rek[e + 1];
rdk[d + 1] =
Td0[Se[(w >>> 24) ] & 0xff] ^
Td1[Se[(w >>> 16) & 0xff] & 0xff] ^
Td2[Se[(w >>> 8) & 0xff] & 0xff] ^
Td3[Se[(w ) & 0xff] & 0xff];
w = rek[e + 2];
rdk[d + 2] =
Td0[Se[(w >>> 24) ] & 0xff] ^
Td1[Se[(w >>> 16) & 0xff] & 0xff] ^
Td2[Se[(w >>> 8) & 0xff] & 0xff] ^
Td3[Se[(w ) & 0xff] & 0xff];
w = rek[e + 3];
rdk[d + 3] =
Td0[Se[(w >>> 24) ] & 0xff] ^
Td1[Se[(w >>> 16) & 0xff] & 0xff] ^
Td2[Se[(w >>> 8) & 0xff] & 0xff] ^
Td3[Se[(w ) & 0xff] & 0xff];
d += 4;
e -= 4;
}
rdk[d ] = rek[e ];
rdk[d + 1] = rek[e + 1];
rdk[d + 2] = rek[e + 2];
rdk[d + 3] = rek[e + 3];
}
/**
* Setup the AES key schedule for encryption, decryption, or both.
*
* @param cipherKey the cipher key (128, 192, or 256 bits).
* @param keyBits size of the cipher key in bits.
* @param direction cipher direction (DIR_ENCRYPT, DIR_DECRYPT, or DIR_BOTH).
*/
public final void makeKey(byte[] cipherKey, int keySize, int direction)
throws RuntimeException {
// check key size:
switch (keySize) {
case 16:
case 24:
case 32:
keySize <<= 3; // keySize is now in bits
break;
case 128:
case 192:
case 256:
break;
default:
throw new RuntimeException("Invalid AES key size (" + keySize + ")");
}
Nk = keySize >>> 5;
Nr = Nk + 6;
Nw = 4*(Nr + 1);
rek = new int[Nw];
rdk = new int[Nw];
if ((direction & DIR_BOTH) != 0) {
expandKey(cipherKey);
/*
for (int r = 0; r <= Nr; r++) {
System.out.print("RK" + r + "=");
for (int i = 0; i < 4; i++) {
int w = rek[4*r + i];
System.out.print(" " + Integer.toHexString(w));
}
System.out.println();
}
*/
if ((direction & DIR_DECRYPT) != 0) {
invertKey();
}
}
}
/**
* Setup the AES key schedule (any cipher direction).
*
* @param cipherKey the cipher key (128, 192, or 256 bits).
* @param keyBits size of the cipher key in bits.
*/
public final void makeKey(byte[] cipherKey, int keyBits)
throws RuntimeException {
makeKey(cipherKey, keyBits, DIR_BOTH);
}
/**
* Encrypt exactly one block (BLOCK_SIZE bytes) of plaintext.
*
* @param pt plaintext block.
* @param ct ciphertext block.
*/
public final void encrypt(byte[] pt, byte[] ct) {
/*
* map byte array block to cipher state
* and add initial round key:
*/
int k = 0, v;
int t0 = ((pt[ 0] ) << 24 |
(pt[ 1] & 0xff) << 16 |
(pt[ 2] & 0xff) << 8 |
(pt[ 3] & 0xff) ) ^ rek[0];
int t1 = ((pt[ 4] ) << 24 |
(pt[ 5] & 0xff) << 16 |
(pt[ 6] & 0xff) << 8 |
(pt[ 7] & 0xff) ) ^ rek[1];
int t2 = ((pt[ 8] ) << 24 |
(pt[ 9] & 0xff) << 16 |
(pt[10] & 0xff) << 8 |
(pt[11] & 0xff) ) ^ rek[2];
int t3 = ((pt[12] ) << 24 |
(pt[13] & 0xff) << 16 |
(pt[14] & 0xff) << 8 |
(pt[15] & 0xff) ) ^ rek[3];
/*
* Nr - 1 full rounds:
*/
for (int r = 1; r < Nr; r++) {
k += 4;
int a0 =
Te0[(t0 >>> 24) ] ^
Te1[(t1 >>> 16) & 0xff] ^
Te2[(t2 >>> 8) & 0xff] ^
Te3[(t3 ) & 0xff] ^
rek[k ];
int a1 =
Te0[(t1 >>> 24) ] ^
Te1[(t2 >>> 16) & 0xff] ^
Te2[(t3 >>> 8) & 0xff] ^
Te3[(t0 ) & 0xff] ^
rek[k + 1];
int a2 =
Te0[(t2 >>> 24) ] ^
Te1[(t3 >>> 16) & 0xff] ^
Te2[(t0 >>> 8) & 0xff] ^
Te3[(t1 ) & 0xff] ^
rek[k + 2];
int a3 =
Te0[(t3 >>> 24) ] ^
Te1[(t0 >>> 16) & 0xff] ^
Te2[(t1 >>> 8) & 0xff] ^
Te3[(t2 ) & 0xff] ^
rek[k + 3];
t0 = a0; t1 = a1; t2 = a2; t3 = a3;
}
/*
* last round lacks MixColumn:
*/
k += 4;
v = rek[k ];
ct[ 0] = (byte)(Se[(t0 >>> 24) ] ^ (v >>> 24));
ct[ 1] = (byte)(Se[(t1 >>> 16) & 0xff] ^ (v >>> 16));
ct[ 2] = (byte)(Se[(t2 >>> 8) & 0xff] ^ (v >>> 8));
ct[ 3] = (byte)(Se[(t3 ) & 0xff] ^ (v ));
v = rek[k + 1];
ct[ 4] = (byte)(Se[(t1 >>> 24) ] ^ (v >>> 24));
ct[ 5] = (byte)(Se[(t2 >>> 16) & 0xff] ^ (v >>> 16));
ct[ 6] = (byte)(Se[(t3 >>> 8) & 0xff] ^ (v >>> 8));
ct[ 7] = (byte)(Se[(t0 ) & 0xff] ^ (v ));
v = rek[k + 2];
ct[ 8] = (byte)(Se[(t2 >>> 24) ] ^ (v >>> 24));
ct[ 9] = (byte)(Se[(t3 >>> 16) & 0xff] ^ (v >>> 16));
ct[10] = (byte)(Se[(t0 >>> 8) & 0xff] ^ (v >>> 8));
ct[11] = (byte)(Se[(t1 ) & 0xff] ^ (v ));
v = rek[k + 3];
ct[12] = (byte)(Se[(t3 >>> 24) ] ^ (v >>> 24));
ct[13] = (byte)(Se[(t0 >>> 16) & 0xff] ^ (v >>> 16));
ct[14] = (byte)(Se[(t1 >>> 8) & 0xff] ^ (v >>> 8));
ct[15] = (byte)(Se[(t2 ) & 0xff] ^ (v ));
}
/**
* Decrypt exactly one block (BLOCK_SIZE bytes) of ciphertext.
*
* @param ct ciphertext block.
* @param pt plaintext block.
*/
public final void decrypt(byte[] ct, byte[] pt) {
/*
* map byte array block to cipher state
* and add initial round key:
*/
int k = 0, v;
int t0 = ((ct[ 0] ) << 24 |
(ct[ 1] & 0xff) << 16 |
(ct[ 2] & 0xff) << 8 |
(ct[ 3] & 0xff) ) ^ rdk[0];
int t1 = ((ct[ 4] ) << 24 |
(ct[ 5] & 0xff) << 16 |
(ct[ 6] & 0xff) << 8 |
(ct[ 7] & 0xff) ) ^ rdk[1];
int t2 = ((ct[ 8] ) << 24 |
(ct[ 9] & 0xff) << 16 |
(ct[10] & 0xff) << 8 |
(ct[11] & 0xff) ) ^ rdk[2];
int t3 = ((ct[12] ) << 24 |
(ct[13] & 0xff) << 16 |
(ct[14] & 0xff) << 8 |
(ct[15] & 0xff) ) ^ rdk[3];
/*
* Nr - 1 full rounds:
*/
for (int r = 1; r < Nr; r++) {
k += 4;
int a0 =
Td0[(t0 >>> 24) ] ^
Td1[(t3 >>> 16) & 0xff] ^
Td2[(t2 >>> 8) & 0xff] ^
Td3[(t1 ) & 0xff] ^
rdk[k ];
int a1 =
Td0[(t1 >>> 24) ] ^
Td1[(t0 >>> 16) & 0xff] ^
Td2[(t3 >>> 8) & 0xff] ^
Td3[(t2 ) & 0xff] ^
rdk[k + 1];
int a2 =
Td0[(t2 >>> 24) ] ^
Td1[(t1 >>> 16) & 0xff] ^
Td2[(t0 >>> 8) & 0xff] ^
Td3[(t3 ) & 0xff] ^
rdk[k + 2];
int a3 =
Td0[(t3 >>> 24) ] ^
Td1[(t2 >>> 16) & 0xff] ^
Td2[(t1 >>> 8) & 0xff] ^
Td3[(t0 ) & 0xff] ^
rdk[k + 3];
t0 = a0; t1 = a1; t2 = a2; t3 = a3;
}
/*
* last round lacks MixColumn:
*/
k += 4;
v = rdk[k ];
pt[ 0] = (byte)(Sd[(t0 >>> 24) ] ^ (v >>> 24));
pt[ 1] = (byte)(Sd[(t3 >>> 16) & 0xff] ^ (v >>> 16));
pt[ 2] = (byte)(Sd[(t2 >>> 8) & 0xff] ^ (v >>> 8));
pt[ 3] = (byte)(Sd[(t1 ) & 0xff] ^ (v ));
v = rdk[k + 1];
pt[ 4] = (byte)(Sd[(t1 >>> 24) ] ^ (v >>> 24));
pt[ 5] = (byte)(Sd[(t0 >>> 16) & 0xff] ^ (v >>> 16));
pt[ 6] = (byte)(Sd[(t3 >>> 8) & 0xff] ^ (v >>> 8));
pt[ 7] = (byte)(Sd[(t2 ) & 0xff] ^ (v ));
v = rdk[k + 2];
pt[ 8] = (byte)(Sd[(t2 >>> 24) ] ^ (v >>> 24));
pt[ 9] = (byte)(Sd[(t1 >>> 16) & 0xff] ^ (v >>> 16));
pt[10] = (byte)(Sd[(t0 >>> 8) & 0xff] ^ (v >>> 8));
pt[11] = (byte)(Sd[(t3 ) & 0xff] ^ (v ));
v = rdk[k + 3];
pt[12] = (byte)(Sd[(t3 >>> 24) ] ^ (v >>> 24));
pt[13] = (byte)(Sd[(t2 >>> 16) & 0xff] ^ (v >>> 16));
pt[14] = (byte)(Sd[(t1 >>> 8) & 0xff] ^ (v >>> 8));
pt[15] = (byte)(Sd[(t0 ) & 0xff] ^ (v ));
}
/**
* Destroy all sensitive information in this object.
*/
public final void finalize() {
if (rek != null) {
for (int i = 0; i < rek.length; i++) {
rek[i] = 0;
}
rek = null;
}
if (rdk != null) {
for (int i = 0; i < rdk.length; i++) {
rdk[i] = 0;
}
rdk = null;
}
}
}
/*
@GROUP
Crypto
@SYNTAX
answer = AES ("encrypt", plain, key)
answer = AES ("e", plain, key)
answer = AES ("decrypt", cipher, key)
answer = AES ("d", cipher, key)
@DOC
does encryption and descrption using the AES (advanced encryption standard) algorithm
@EXAMPLES
<programlisting>
> k=str2num("0987098709870987")
k=[48,57,56,55,48,57,56,55,48,57,56,55,48,57,56,55]
> a=str2num("asdfasdfasdfasdf")
a=[97,115,100,102,97,115,100,102,97,115,100,102,97,115,100,102]
> b=aes("e",a,k)
b=[-103,34,84,18,-46,-58,35,89,80,17,81,118,-4,-15,-93,-31]
> c=aes("d",b,k)
c=[97,115,100,102,97,115,100,102,97,115,100,102,97,115,100,102]
> num2str(c)
ans = asdfasdfasdfasdf
</programlisting>
@NOTES
@SEE
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -