Java 實現(xiàn) AES256-ECB-PKCS7Padding(無需修改策略文件)

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class AES {
    public static class Cipher {
        public static final int ENCRYPT_MODE = 1;
        public static final int DECRYPT_MODE = 2;
        public static final String AES_ECB_PKCS7 = "AES/ECB/PKCS7Padding";
        private int opmode;
        private AESBlock block;

        public static Cipher getInstance(String var0) throws NoSuchAlgorithmException, NoSuchPaddingException {
            if (AES_ECB_PKCS7.equals(var0)) {
                Cipher cipher = new Cipher();
                cipher.block = new AESBlock();
                return cipher;
            }
            throw new NoSuchAlgorithmException(var0);
        }

        public void init(int var1, Key var2) throws InvalidKeyException {
            this.opmode = var1;
            this.block.init(var1 == DECRYPT_MODE, var2.getEncoded());
        }

        public byte[] doFinal(byte[] var1) throws IllegalBlockSizeException, BadPaddingException {
            int blockSize = this.block.getBlockSize();
            if (this.opmode == ENCRYPT_MODE) {
                byte[] pad = PKCS7Padding.pad(var1, blockSize);
                byte[] dst = new byte[pad.length];
                for (int i = 0; i < pad.length; i += blockSize) {
                    this.block.encryptBlock(pad, i, dst, i);
                }
                return dst;
            } else {
                byte[] dst = new byte[var1.length];
                for (int i = 0; i < var1.length; i += blockSize) {
                    this.block.decryptBlock(var1, i, dst, i);
                }
                return PKCS7Padding.unpad(dst);
            }
        }
    }

    public static class PKCS7Padding {

        public static byte[] pad(byte[] var1, int blockSize) {
            int tail = blockSize - var1.length % blockSize;
            byte[] dst = new byte[var1.length + tail];
            System.arraycopy(var1, 0, dst, 0, var1.length);
            Arrays.fill(dst, var1.length, dst.length, (byte) (tail & 255));
            return dst;
        }

        public static byte[] unpad(byte[] var1) {
            int tail = var1[var1.length - 1];
            byte[] dst = new byte[var1.length - tail];
            System.arraycopy(var1, 0, dst, 0, dst.length);
            return dst;
        }
    }

    /**
     * Base on openjdk commit 85648e14f25d4448d51db001a4629154ea82b452.
     */
    public static final class AESBlock {
        private static final int AES_BLOCK_SIZE = 16;
        private static final int[] AES_KEYSIZES = new int[]{16, 24, 32};
        private static final byte[] S = new byte[256], Si = new byte[256];
        private static final int[] T1 = new int[256], T2 = new int[256], T3 = new int[256], T4 = new int[256], T5 = new int[256], T6 = new int[256], T7 = new int[256], T8 = new int[256];
        private static final int[] U1 = new int[256], U2 = new int[256], U3 = new int[256], U4 = new int[256];
        private static final byte[] rcon = new byte[30];
        private static int[] alog = new int[256], log = new int[256];

        static {
            int ROOT = 0x11B;
            int i, j = 0;
            alog[0] = 1;
            for (i = 1; i < 256; i++) {
                j = (alog[i - 1] << 1) ^ alog[i - 1];
                if ((j & 0x100) != 0) {
                    j ^= ROOT;
                }
                alog[i] = j;
            }
            for (i = 1; i < 255; i++) {
                log[alog[i]] = i;
            }
            byte[][] A = new byte[][]
                    {
                            {1, 1, 1, 1, 1, 0, 0, 0},
                            {0, 1, 1, 1, 1, 1, 0, 0},
                            {0, 0, 1, 1, 1, 1, 1, 0},
                            {0, 0, 0, 1, 1, 1, 1, 1},
                            {1, 0, 0, 0, 1, 1, 1, 1},
                            {1, 1, 0, 0, 0, 1, 1, 1},
                            {1, 1, 1, 0, 0, 0, 1, 1},
                            {1, 1, 1, 1, 0, 0, 0, 1}
                    };
            byte[] B = new byte[]{0, 1, 1, 0, 0, 0, 1, 1};
            int t;
            byte[][] box = new byte[256][8];
            box[1][7] = 1;
            for (i = 2; i < 256; i++) {
                j = alog[255 - log[i]];
                for (t = 0; t < 8; t++) {
                    box[i][t] = (byte) ((j >>> (7 - t)) & 0x01);
                }
            }
            byte[][] cox = new byte[256][8];
            for (i = 0; i < 256; i++) {
                for (t = 0; t < 8; t++) {
                    cox[i][t] = B[t];
                    for (j = 0; j < 8; j++) {
                        cox[i][t] ^= A[t][j] * box[i][j];
                    }
                }
            }
            for (i = 0; i < 256; i++) {
                S[i] = (byte) (cox[i][0] << 7);
                for (t = 1; t < 8; t++) {
                    S[i] ^= cox[i][t] << (7 - t);
                }
                Si[S[i] & 0xFF] = (byte) i;
            }
            byte[][] G = new byte[][]{
                    {2, 1, 1, 3},
                    {3, 2, 1, 1},
                    {1, 3, 2, 1},
                    {1, 1, 3, 2}
            };
            byte[][] AA = new byte[4][8];
            for (i = 0; i < 4; i++) {
                for (j = 0; j < 4; j++) AA[i][j] = G[i][j];
                AA[i][i + 4] = 1;
            }
            byte pivot, tmp;
            byte[][] iG = new byte[4][4];
            for (i = 0; i < 4; i++) {
                pivot = AA[i][i];
                if (pivot == 0) {
                    t = i + 1;
                    while (AA[t][i] == 0) {
                        t++;
                    }
                    for (j = 0; j < 8; j++) {
                        tmp = AA[i][j];
                        AA[i][j] = AA[t][j];
                        AA[t][j] = tmp;
                    }
                    pivot = AA[i][i];
                }
                for (j = 0; j < 8; j++) {
                    if (AA[i][j] != 0) {
                        AA[i][j] = (byte)
                                alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF])
                                        % 255];
                    }
                }
                for (t = 0; t < 4; t++) {
                    if (i != t) {
                        for (j = i + 1; j < 8; j++) {
                            AA[t][j] ^= mul(AA[i][j], AA[t][i]);
                        }
                        AA[t][i] = 0;
                    }
                }
            }
            for (i = 0; i < 4; i++) {
                for (j = 0; j < 4; j++) {
                    iG[i][j] = AA[i][j + 4];
                }
            }
            int s;
            for (t = 0; t < 256; t++) {
                s = S[t];
                T1[t] = mul4(s, G[0]);
                T2[t] = mul4(s, G[1]);
                T3[t] = mul4(s, G[2]);
                T4[t] = mul4(s, G[3]);

                s = Si[t];
                T5[t] = mul4(s, iG[0]);
                T6[t] = mul4(s, iG[1]);
                T7[t] = mul4(s, iG[2]);
                T8[t] = mul4(s, iG[3]);

                U1[t] = mul4(t, iG[0]);
                U2[t] = mul4(t, iG[1]);
                U3[t] = mul4(t, iG[2]);
                U4[t] = mul4(t, iG[3]);
            }
            rcon[0] = 1;
            int r = 1;
            for (t = 1; t < 30; t++) {
                r = mul(2, r);
                rcon[t] = (byte) r;
            }
            log = null;
            alog = null;
        }

        private boolean ROUNDS_12 = false;
        private boolean ROUNDS_14 = false;
        private int[][] sessionK = null;
        private int[] K = null;
        private byte[] lastKey = null;
        private int limit = 0;

        AESBlock() {
        }

        private static int[] expandToSubKey(int[][] kr, boolean decrypting) {
            int total = kr.length;
            int[] expK = new int[total * 4];
            if (decrypting) {
                System.arraycopy(kr[total - 1], 0, expK, 0, 4);
                for (int i = 1; i < total; i++) {
                    System.arraycopy(kr[i - 1], 0, expK, i * 4, 4);
                }
            } else {
                for (int i = 0; i < total; i++) {
                    System.arraycopy(kr[i], 0, expK, i * 4, 4);
                }
            }
            return expK;
        }

        private static int mul(int a, int b) {
            return (a != 0 && b != 0) ?
                    alog[(log[a & 0xFF] + log[b & 0xFF]) % 255] :
                    0;
        }

        private static 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;
        }

        private static boolean isKeySizeValid(int len) {
            for (int aesKeysize : AES_KEYSIZES) {
                if (len == aesKeysize) {
                    return false;
                }
            }
            return true;
        }

        private static int getRounds(int keySize) {
            return (keySize >> 2) + 6;
        }

        public int getBlockSize() {
            return AES_BLOCK_SIZE;
        }

        void init(boolean decrypting, byte[] key)
                throws InvalidKeyException {
            if (isKeySizeValid(key.length)) {
                throw new InvalidKeyException("Invalid AES key length: " + key.length + " bytes");
            }
            if (!MessageDigest.isEqual(key, lastKey)) {
                makeSessionKey(key);
                lastKey = key.clone();
            }
            this.K = sessionK[(decrypting ? 1 : 0)];
        }

        public void encryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) {
            int keyOffset = 0;
            int t0 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF)) ^ K[keyOffset++];
            int t1 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF)) ^ K[keyOffset++];
            int t2 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF)) ^ K[keyOffset++];
            int t3 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF)) ^ K[keyOffset++];
            while (keyOffset < limit) {
                int a0, a1, a2;
                a0 = T1[(t0 >>> 24)] ^ T2[(t1 >>> 16) & 0xFF] ^ T3[(t2 >>> 8) & 0xFF] ^ T4[(t3) & 0xFF] ^ K[keyOffset++];
                a1 = T1[(t1 >>> 24)] ^ T2[(t2 >>> 16) & 0xFF] ^ T3[(t3 >>> 8) & 0xFF] ^ T4[(t0) & 0xFF] ^ K[keyOffset++];
                a2 = T1[(t2 >>> 24)] ^ T2[(t3 >>> 16) & 0xFF] ^ T3[(t0 >>> 8) & 0xFF] ^ T4[(t1) & 0xFF] ^ K[keyOffset++];
                t3 = T1[(t3 >>> 24)] ^ T2[(t0 >>> 16) & 0xFF] ^ T3[(t1 >>> 8) & 0xFF] ^ T4[(t2) & 0xFF] ^ K[keyOffset++];
                t0 = a0;
                t1 = a1;
                t2 = a2;
            }
            int tt = K[keyOffset++];
            out[outOffset++] = (byte) (S[(t0 >>> 24)] ^ (tt >>> 24));
            out[outOffset++] = (byte) (S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16));
            out[outOffset++] = (byte) (S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8));
            out[outOffset++] = (byte) (S[(t3) & 0xFF] ^ (tt));
            tt = K[keyOffset++];
            out[outOffset++] = (byte) (S[(t1 >>> 24)] ^ (tt >>> 24));
            out[outOffset++] = (byte) (S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16));
            out[outOffset++] = (byte) (S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8));
            out[outOffset++] = (byte) (S[(t0) & 0xFF] ^ (tt));
            tt = K[keyOffset++];
            out[outOffset++] = (byte) (S[(t2 >>> 24)] ^ (tt >>> 24));
            out[outOffset++] = (byte) (S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16));
            out[outOffset++] = (byte) (S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8));
            out[outOffset++] = (byte) (S[(t1) & 0xFF] ^ (tt));
            tt = K[keyOffset++];
            out[outOffset++] = (byte) (S[(t3 >>> 24)] ^ (tt >>> 24));
            out[outOffset++] = (byte) (S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16));
            out[outOffset++] = (byte) (S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8));
            out[outOffset] = (byte) (S[(t2) & 0xFF] ^ (tt));
        }

        public void decryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) {
            int keyOffset = 4;
            int t0 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF)) ^ K[keyOffset++];
            int t1 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF)) ^ K[keyOffset++];
            int t2 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF)) ^ K[keyOffset++];
            int t3 = ((in[inOffset++]) << 24 | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 8 | (in[inOffset] & 0xFF)) ^ K[keyOffset++];
            int a0, a1, a2;
            if (ROUNDS_12) {
                a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF] ^ K[keyOffset++];
                a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF] ^ K[keyOffset++];
                a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF] ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
                t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF] ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF] ^ K[keyOffset++];
                t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF] ^ K[keyOffset++];
                t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF] ^ K[keyOffset++];
                t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF] ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
                t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF] ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF] ^ K[keyOffset++];
                if (ROUNDS_14) {
                    a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF] ^ K[keyOffset++];
                    a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF] ^ K[keyOffset++];
                    a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF] ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
                    t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF] ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF] ^ K[keyOffset++];
                    t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF] ^ K[keyOffset++];
                    t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF] ^ K[keyOffset++];
                    t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF] ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
                    t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF] ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF] ^ K[keyOffset++];
                }
            }
            a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF] ^ K[keyOffset++];
            a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF] ^ K[keyOffset++];
            a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF] ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
            t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF] ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF] ^ K[keyOffset++];
            t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF] ^ K[keyOffset++];
            t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF] ^ K[keyOffset++];
            t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF] ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
            t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF] ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF] ^ K[keyOffset++];
            a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF] ^ K[keyOffset++];
            a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF] ^ K[keyOffset++];
            a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF] ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
            t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF] ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF] ^ K[keyOffset++];
            t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF] ^ K[keyOffset++];
            t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF] ^ K[keyOffset++];
            t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF] ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
            t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF] ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF] ^ K[keyOffset++];
            a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF] ^ K[keyOffset++];
            a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF] ^ K[keyOffset++];
            a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF] ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
            t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF] ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF] ^ K[keyOffset++];
            t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF] ^ K[keyOffset++];
            t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF] ^ K[keyOffset++];
            t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF] ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
            t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF] ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF] ^ K[keyOffset++];
            a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF] ^ K[keyOffset++];
            a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF] ^ K[keyOffset++];
            a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF] ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
            t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF] ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF] ^ K[keyOffset++];
            t0 = T5[(a0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(a2 >>> 8) & 0xFF] ^ T8[(a1) & 0xFF] ^ K[keyOffset++];
            t1 = T5[(a1 >>> 24)] ^ T6[(a0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(a2) & 0xFF] ^ K[keyOffset++];
            t2 = T5[(a2 >>> 24)] ^ T6[(a1 >>> 16) & 0xFF] ^ T7[(a0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
            t3 = T5[(t3 >>> 24)] ^ T6[(a2 >>> 16) & 0xFF] ^ T7[(a1 >>> 8) & 0xFF] ^ T8[(a0) & 0xFF] ^ K[keyOffset++];
            a0 = T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(t2 >>> 8) & 0xFF] ^ T8[(t1) & 0xFF] ^ K[keyOffset++];
            a1 = T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[(t2) & 0xFF] ^ K[keyOffset++];
            a2 = T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF] ^ T7[(t0 >>> 8) & 0xFF] ^ T8[(t3) & 0xFF] ^ K[keyOffset++];
            t3 = T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF] ^ T7[(t1 >>> 8) & 0xFF] ^ T8[(t0) & 0xFF] ^ K[keyOffset++];
            t1 = K[0];
            out[outOffset++] = (byte) (Si[(a0 >>> 24)] ^ (t1 >>> 24));
            out[outOffset++] = (byte) (Si[(t3 >>> 16) & 0xFF] ^ (t1 >>> 16));
            out[outOffset++] = (byte) (Si[(a2 >>> 8) & 0xFF] ^ (t1 >>> 8));
            out[outOffset++] = (byte) (Si[(a1) & 0xFF] ^ (t1));
            t1 = K[1];
            out[outOffset++] = (byte) (Si[(a1 >>> 24)] ^ (t1 >>> 24));
            out[outOffset++] = (byte) (Si[(a0 >>> 16) & 0xFF] ^ (t1 >>> 16));
            out[outOffset++] = (byte) (Si[(t3 >>> 8) & 0xFF] ^ (t1 >>> 8));
            out[outOffset++] = (byte) (Si[(a2) & 0xFF] ^ (t1));
            t1 = K[2];
            out[outOffset++] = (byte) (Si[(a2 >>> 24)] ^ (t1 >>> 24));
            out[outOffset++] = (byte) (Si[(a1 >>> 16) & 0xFF] ^ (t1 >>> 16));
            out[outOffset++] = (byte) (Si[(a0 >>> 8) & 0xFF] ^ (t1 >>> 8));
            out[outOffset++] = (byte) (Si[(t3) & 0xFF] ^ (t1));
            t1 = K[3];
            out[outOffset++] = (byte) (Si[(t3 >>> 24)] ^ (t1 >>> 24));
            out[outOffset++] = (byte) (Si[(a2 >>> 16) & 0xFF] ^ (t1 >>> 16));
            out[outOffset++] = (byte) (Si[(a1 >>> 8) & 0xFF] ^ (t1 >>> 8));
            out[outOffset] = (byte) (Si[(a0) & 0xFF] ^ (t1));
        }

        private void makeSessionKey(byte[] k) throws InvalidKeyException {
            if (k == null) {
                throw new InvalidKeyException("Empty key");
            }
            if (isKeySizeValid(k.length)) {
                throw new InvalidKeyException("Invalid AES key length: " + k.length + " bytes");
            }
            int ROUNDS = getRounds(k.length);
            int ROUND_KEY_COUNT = (ROUNDS + 1) * 4;
            int BC = 4;
            int[][] Ke = new int[ROUNDS + 1][4];
            int[][] Kd = new int[ROUNDS + 1][4];
            int KC = k.length / 4;
            int[] tk = new int[KC];
            int i, j;
            for (i = 0, j = 0; i < KC; i++, j += 4) {
                tk[i] = (k[j]) << 24 | (k[j + 1] & 0xFF) << 16 | (k[j + 2] & 0xFF) << 8 | (k[j + 3] & 0xFF);
            }
            int t = 0;
            for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++) {
                Ke[t / 4][t % 4] = tk[j];
                Kd[ROUNDS - (t / 4)][t % 4] = tk[j];
            }
            int tt, rconpointer = 0;
            while (t < ROUND_KEY_COUNT) {
                tt = tk[KC - 1];
                tk[0] ^= (S[(tt >>> 16) & 0xFF]) << 24 ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 16 ^ (S[(tt) & 0xFF] & 0xFF) << 8 ^ (S[(tt >>> 24)] & 0xFF) ^ (rcon[rconpointer++]) << 24;
                if (KC != 8)
                    for (i = 1, j = 0; i < KC; i++, j++) tk[i] ^= tk[j];
                else {
                    for (i = 1, j = 0; i < KC / 2; i++, j++) 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)]) << 24;
                    for (j = KC / 2, i = j + 1; i < KC; i++, j++) tk[i] ^= tk[j];
                }
                for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++) {
                    Ke[t / 4][t % 4] = tk[j];
                    Kd[ROUNDS - (t / 4)][t % 4] = tk[j];
                }
            }
            for (int r = 1; r < ROUNDS; r++) {
                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];
                }
            }
            int[] expandedKe = expandToSubKey(Ke, false);
            int[] expandedKd = expandToSubKey(Kd, true);
            ROUNDS_12 = (ROUNDS >= 12);
            ROUNDS_14 = (ROUNDS == 14);
            limit = ROUNDS * 4;
            sessionK = new int[][]{expandedKe, expandedKd};
        }
    }
}

測試用例

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;

/**
 * Created by Demon on 2020/7/23
 */
public class Main {
    public static void main(String[] args) throws Exception {
        int[] keySize = {16, 24, 32};
        for (int size : keySize) {
            for (int i = 0; i < 1000; i++) {
                Key key = genKey(size);
                OriCipher oriCipher = new OriCipher(key);
                NewCipher newCipher = new NewCipher(key);
                for (int j = 0; j < 1000; j++) {
                    byte[] bytes = genData();
                    around(oriCipher, newCipher, bytes);
                }
            }
        }
    }

    private static Key genKey(int kLen) throws NoSuchAlgorithmException {
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        byte[] bytes = new byte[kLen];
        secureRandom.nextBytes(bytes);
        return new SecretKeySpec(bytes, "AES");
    }

    private static byte[] genData() throws NoSuchAlgorithmException {
        int length = ThreadLocalRandom.current().nextInt(2048);
        byte[] bytes = new byte[length];
        ThreadLocalRandom.current().nextBytes(bytes);
        return bytes;
    }

    private static void around(OriCipher ori, NewCipher newc, byte[] src) throws BadPaddingException, IllegalBlockSizeException {
        byte[] encrypt = ori.encrypt(src);
        byte[] decrypt = newc.decrypt(encrypt);
        byte[] encrypt1 = newc.encrypt(decrypt);
        byte[] decrypt1 = ori.decrypt(encrypt1);
        assertEquals(src, decrypt1);
    }

    private static void assertEquals(byte[] b1, byte[] b2) {
        if (!Arrays.equals(b1, b2)) {
            throw new RuntimeException("\n" +
                    Arrays.toString(b1) +
                    "\n" +
                    Arrays.toString(b2) +
                    "\n");

        }
    }
}

class OriCipher {
    private Cipher cipher1;
    private Cipher cipher2;

    public OriCipher(Key key) {
        try {
            this.cipher1 = Cipher.getInstance("AES/ECB/PKCS5Padding");
            this.cipher1.init(Cipher.ENCRYPT_MODE, key);
            this.cipher2 = Cipher.getInstance("AES/ECB/PKCS5Padding");
            this.cipher2.init(Cipher.DECRYPT_MODE, key);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public byte[] encrypt(byte[] src) throws BadPaddingException, IllegalBlockSizeException {
        return this.cipher1.doFinal(src);
    }

    public byte[] decrypt(byte[] enc) throws BadPaddingException, IllegalBlockSizeException {
        return this.cipher2.doFinal(enc);
    }
}

class NewCipher {
    private AES.Cipher cipher1;
    private AES.Cipher cipher2;

    public NewCipher(Key key) {
        try {
            this.cipher1 = AES.Cipher.getInstance("AES/ECB/PKCS7Padding");
            this.cipher1.init(AES.Cipher.ENCRYPT_MODE, key);
            this.cipher2 = AES.Cipher.getInstance("AES/ECB/PKCS7Padding");
            this.cipher2.init(AES.Cipher.DECRYPT_MODE, key);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public byte[] encrypt(byte[] src) throws BadPaddingException, IllegalBlockSizeException {
        return this.cipher1.doFinal(src);
    }

    public byte[] decrypt(byte[] enc) throws BadPaddingException, IllegalBlockSizeException {
        return this.cipher2.doFinal(enc);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子焕窝,更是在濱河造成了極大的恐慌厌均,老刑警劉巖棒呛,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件聂示,死亡現(xiàn)場離奇詭異,居然都是意外死亡簇秒,警方通過查閱死者的電腦和手機鱼喉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來趋观,“玉大人蒲凶,你說我怎么就攤上這事〔鹉冢” “怎么了旋圆?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長麸恍。 經(jīng)常有香客問我灵巧,道長,這世上最難降的妖魔是什么抹沪? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任刻肄,我火速辦了婚禮,結(jié)果婚禮上融欧,老公的妹妹穿的比我還像新娘敏弃。我一直安慰自己,他們只是感情好噪馏,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布麦到。 她就那樣靜靜地躺著,像睡著了一般欠肾。 火紅的嫁衣襯著肌膚如雪瓶颠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天刺桃,我揣著相機與錄音粹淋,去河邊找鬼。 笑死瑟慈,一個胖子當(dāng)著我的面吹牛桃移,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播葛碧,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼借杰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吹埠?” 一聲冷哼從身側(cè)響起第步,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤疮装,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后粘都,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體廓推,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年翩隧,在試婚紗的時候發(fā)現(xiàn)自己被綠了樊展。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡堆生,死狀恐怖专缠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情淑仆,我是刑警寧澤涝婉,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站蔗怠,受9級特大地震影響墩弯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寞射,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一渔工、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桥温,春花似錦引矩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至通惫,卻和暖如春茂翔,著一層夾襖步出監(jiān)牢的瞬間混蔼,已是汗流浹背履腋。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留惭嚣,地道東北人遵湖。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像晚吞,于是被迫代替她去往敵國和親延旧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355