📄 aescipher.java
字号:
alog[( a + log[b[3] & 0xFF] ) % 255] & 0xFF : 0;
return a0 << 24 | a1 << 16 | a2 << 8 | a3;
}
/// 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;
}
}
// Constructors.
// Constructor, string key.
public AesCipher( String keyStr )
{
super( KEY_SIZE, BLOCK_SIZE );
setKey( keyStr );
}
// Constructor, byte-array key.
public AesCipher( byte[] key )
{
super( KEY_SIZE, BLOCK_SIZE );
setKey( key );
}
// Key routines.
private int ROUNDS = getRounds( KEY_SIZE, BLOCK_SIZE );
private int BC = BLOCK_SIZE / 4;
private int[][] Ke = new int[ROUNDS + 1][BC]; // encryption round keys
private int[][] Kd = new int[ROUNDS + 1][BC]; // decryption round keys
/// Set the key.
public void setKey( byte[] key )
{
if ( key.length != KEY_SIZE )
throw new RuntimeException("Incorrect key length");
int ROUND_KEY_COUNT = ( ROUNDS + 1 ) * BC;
int KC = KEY_SIZE / 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++] = ( key[j++] & 0xFF ) << 24 |
( key[j++] & 0xFF ) << 16 |
( key[j++] & 0xFF ) << 8 |
( key[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;
if ( KC != 8 )
for ( i = 1, j = 0; i < KC; )
tk[i++] ^= tk[j++];
else
{
for ( i = 1, j = 0; i < KC / 2; )
tk[i++] ^= tk[j++];
tt = tk[KC / 2 - 1];
tk[KC / 2] ^= ( S[ tt & 0xFF] & 0xFF ) ^
( S[( tt >>> 8 ) & 0xFF] & 0xFF ) << 8 ^
( S[( tt >>> 16 ) & 0xFF] & 0xFF ) << 16 ^
( S[( tt >>> 24 ) & 0xFF] & 0xFF ) << 24;
for ( j = KC / 2, i = j + 1; i < KC; )
tk[i++] ^= tk[j++];
}
// Copy values into round key arrays.
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];
}
}
for ( int r = 1; r < ROUNDS; ++r ) // inverse MixColumn where needed
for ( j = 0; j < BC; ++j )
{
tt = Kd[r][j];
Kd[r][j] = U1[( tt >>> 24 ) & 0xFF] ^
U2[( tt >>> 16 ) & 0xFF] ^
U3[( tt >>> 8 ) & 0xFF] ^
U4[ tt & 0xFF];
}
}
// Block encryption routines.
private int[] tempInts = new int[8];
/// Encrypt a block.
public void encrypt( byte[] clearText, int clearOff, byte[] cipherText, int cipherOff )
{
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;
int tt;
for ( i = 0; i < BC; ++i ) // plaintext to ints + key
t[i] = ( ( clearText[clearOff++] & 0xFF ) << 24 |
( clearText[clearOff++] & 0xFF ) << 16 |
( clearText[clearOff++] & 0xFF ) << 8 |
( clearText[clearOff++] & 0xFF ) ) ^ Ke[0][i];
// Apply round transforms.
for ( int r = 1; r < ROUNDS; ++r )
{
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 );
}
// Last round is special.
for ( i = 0; i < BC; ++i )
{
tt = Ke[ROUNDS][i];
cipherText[cipherOff++] =
(byte) ( S[( t[ i ] >>> 24 ) & 0xFF] ^
( tt >>> 24 ) );
cipherText[cipherOff++] =
(byte) ( S[( t[( i + s1 ) % BC] >>> 16 ) & 0xFF] ^
( tt >>> 16 ) );
cipherText[cipherOff++] =
(byte) ( S[( t[( i + s2 ) % BC] >>> 8 ) & 0xFF] ^
( tt >>> 8 ) );
cipherText[cipherOff++] =
(byte) ( S[ t[( i + s3 ) % BC] & 0xFF] ^
tt );
}
}
/// Decrypt a block.
public void decrypt( byte[] cipherText, int cipherOff, byte[] clearText, int clearOff )
{
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;
int tt;
for ( i = 0; i < BC; ++i ) // ciphertext to ints + key
t[i] = ( ( cipherText[cipherOff++] & 0xFF ) << 24 |
( cipherText[cipherOff++] & 0xFF ) << 16 |
( cipherText[cipherOff++] & 0xFF ) << 8 |
( cipherText[cipherOff++] & 0xFF ) ) ^ Kd[0][i];
// Apply round transforms.
for ( int r = 1; r < ROUNDS; ++r )
{
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 );
}
// Last round is special.
for ( i = 0; i < BC; ++i )
{
tt = Kd[ROUNDS][i];
clearText[clearOff++] =
(byte) ( Si[( t[ i ] >>> 24 ) & 0xFF] ^
( tt >>> 24 ) );
clearText[clearOff++] =
(byte) ( Si[( t[( i + s1 ) % BC] >>> 16 ) & 0xFF] ^
( tt >>> 16 ) );
clearText[clearOff++] =
(byte) ( Si[( t[( i + s2 ) % BC] >>> 8 ) & 0xFF] ^
( tt >>> 8 ) );
clearText[clearOff++] =
(byte) ( Si[ t[( i + s3 ) % BC] & 0xFF] ^
tt );
}
}
/// Test routine.
public static void main( String[] args )
{
byte[] cipherText = new byte[16];
byte[] decipherText = new byte[16];
BlockCipher aesa = new AesCipher( "0123456789" );
byte[] clearText1 = {
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
System.out.println( "cleartext: " + toStringBlock( clearText1 ) );
aesa.encrypt( clearText1, cipherText );
System.out.println( "encrypted: " + toStringBlock( cipherText ) );
aesa.decrypt( cipherText, decipherText );
System.out.println( "decrypted: " + toStringBlock( decipherText ) );
System.out.println();
BlockCipher aesb = new AesCipher( "abcdefghijklmnopqrstuvwxyz" );
byte[] clearText2 = {
(byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03,
(byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07,
(byte) 0x08, (byte) 0x09, (byte) 0x0a, (byte) 0x0b,
(byte) 0x0c, (byte) 0x0d, (byte) 0x0e, (byte) 0x0f };
System.out.println( "cleartext: " + toStringBlock( clearText2 ) );
aesb.encrypt( clearText2, cipherText );
System.out.println( "encrypted: " + toStringBlock( cipherText ) );
aesb.decrypt( cipherText, decipherText );
System.out.println( "decrypted: " + toStringBlock( decipherText ) );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -