📄 rijndael.java
字号:
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 void makeKey(byte[] cipherKey, int keyBits, int direction) throws RuntimeException { // check key size: if (keyBits != 128 && keyBits != 192 && keyBits != 256) { throw new RuntimeException("Invalid AES key size (" + keyBits + " bits)"); } Nk = keyBits >>> 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 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 byte[] encryptBlock(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 )); return ct; } /** * Decrypt exactly one block (BLOCK_SIZE bytes) of ciphertext. * * @param ct ciphertext block. * @param pt plaintext block. */ public byte[] decryptBlock(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 )); return pt; } public byte[] encryptArray(byte[] message, int offset) throws CryptoException { //Check for a bad offset if(offset > message.length) { throw new CryptoException("Offset is greater than length of message"); } //Length of message to process int length = message.length - offset; //Number of whole blocks int numOfBlocks = length / BLOCK_SIZE; //Length of the last part int lengthOfLastPart = length - (numOfBlocks * BLOCK_SIZE); //If message was mutliple of BLOCK_SIZE if(lengthOfLastPart == 0) { lengthOfLastPart = BLOCK_SIZE; numOfBlocks = numOfBlocks - 1; } byte[] result = new byte[0]; byte[] block = new byte[BLOCK_SIZE]; //Process whole blocks for(int i = 0; i < numOfBlocks; i++) { System.arraycopy(message, offset + (i * BLOCK_SIZE), block, 0, BLOCK_SIZE); result = Util.addByteArrays(result, encryptBlock(block, new byte[BLOCK_SIZE])); } //Now do the last part (or last block if message was multiple of BLOCK_SIZE) byte last[] = new byte[lengthOfLastPart]; System.arraycopy(message, offset + (numOfBlocks * BLOCK_SIZE), last, 0, lengthOfLastPart); //Number of padding bytes required int numOfPads = BLOCK_SIZE - last.length; //If last block is equal to the block size we need a whole new padding block if(numOfPads == 0){ numOfPads = BLOCK_SIZE; } //Set the padding bytes byte pads[] = new byte[numOfPads]; for(int i = 0; i < numOfPads; i++) { pads[i]=(byte)numOfPads; } if(numOfPads != BLOCK_SIZE) { //Add the padding bytes to the input last = Util.addByteArrays(last, pads); } else { //If last block passed was 0 bytes long, just return a 16 byte padding block if(last.length == 0) { last = pads; } //Return block plus 16 byte padding block result = Util.addByteArrays(encryptBlock(last, new byte[BLOCK_SIZE]), encryptBlock(pads, new byte[BLOCK_SIZE])); return result; } result = Util.addByteArrays(result, encryptBlock(last, new byte[BLOCK_SIZE])); return result; } public byte[] decryptArray(byte[] message, int offset) throws CryptoException { //Check for a bad offset if(offset > message.length) { throw new CryptoException("Offset is greater than length of message"); } //Length of message to process int length = message.length - offset; //Number of whole blocks int numOfBlocks = length / BLOCK_SIZE; //Length of the last part int lengthOfLastPart = length - (numOfBlocks * BLOCK_SIZE); //If message was mutliple of BLOCK_SIZE if(lengthOfLastPart == 0) { lengthOfLastPart = BLOCK_SIZE; numOfBlocks = numOfBlocks - 1; } byte[] result = new byte[0]; byte[] block = new byte[BLOCK_SIZE]; //Process whole blocks for(int i = 0; i < numOfBlocks; i++) { System.arraycopy(message, offset + (i * BLOCK_SIZE), block, 0, BLOCK_SIZE); result = Util.addByteArrays(result, decryptBlock(block, new byte[BLOCK_SIZE])); } //Now do the last part (or last block if message was multiple of BLOCK_SIZE) byte last[] = new byte[lengthOfLastPart]; System.arraycopy(message, offset + (numOfBlocks * BLOCK_SIZE), last, 0, lengthOfLastPart); //Decrypt the last block byte[] tmp = decryptBlock(last, new byte[BLOCK_SIZE]); int numOfPads = tmp[tmp.length - 1]; byte[] lastBlock = new byte[BLOCK_SIZE - numOfPads]; System.arraycopy(tmp, 0, lastBlock, 0, lastBlock.length); result = Util.addByteArrays(result, lastBlock); return result; } /** * Compares two byte arrays for equality. * * @return true if the arrays have identical contents */ public static final 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; } /** * Destroy all sensitive information in this object. */ protected 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; } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -