JAVA实现AES加密,课程实验,AES128

AES结构流程图如下 

既然是来查代码的,各个步骤的具体步骤大家应该都知道,我就不细说了,放图在下面

明文/密文放入顺序: 

 S盒:

轮密钥生成:

字节旋转:每个字中的字节循环左移一个字节

字节代替:S盒代替

废话少说,直接上代码: 

package AES;

import java.util.Arrays;
import java.util.Random;

public class AES {
    private final static int[] rC = new int[]{0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000};//轮常数
    private final static byte[] cx = new byte[]{0x02, 0x01, 0x01, 0x03};
    private final static byte[] c_x = new byte[]{0x0e, 0x09, 0x0d, 0x0b};//列混合的c(x)与逆
    private final static int irreduciblePolynomial = 0b100011011;//28域上的不可约多项式
    private final static byte[][] sBox = new byte[][]{
            {(byte) 0x63, (byte) 0x7c, (byte) 0x77, (byte) 0x7b, (byte) 0xf2, (byte) 0x6b, (byte) 0x6f, (byte) 0xc5, (byte) 0x30, (byte) 0x01, (byte) 0x67, (byte) 0x2b, (byte) 0xfe, (byte) 0xd7, (byte) 0xab, (byte) 0x76},
            {(byte) 0xca, (byte) 0x82, (byte) 0xc9, (byte) 0x7d, (byte) 0xfa, (byte) 0x59, (byte) 0x47, (byte) 0xf0, (byte) 0xad, (byte) 0xd4, (byte) 0xa2, (byte) 0xaf, (byte) 0x9c, (byte) 0xa4, (byte) 0x72, (byte) 0xc0},
            {(byte) 0xb7, (byte) 0xfd, (byte) 0x93, (byte) 0x26, (byte) 0x36, (byte) 0x3f, (byte) 0xf7, (byte) 0xcc, (byte) 0x34, (byte) 0xa5, (byte) 0xe5, (byte) 0xf1, (byte) 0x71, (byte) 0xd8, (byte) 0x31, (byte) 0x15},
            {(byte) 0x04, (byte) 0xc7, (byte) 0x23, (byte) 0xc3, (byte) 0x18, (byte) 0x96, (byte) 0x05, (byte) 0x9a, (byte) 0x07, (byte) 0x12, (byte) 0x80, (byte) 0xe2, (byte) 0xeb, (byte) 0x27, (byte) 0xb2, (byte) 0x75},
            {(byte) 0x09, (byte) 0x83, (byte) 0x2c, (byte) 0x1a, (byte) 0x1b, (byte) 0x6e, (byte) 0x5a, (byte) 0xa0, (byte) 0x52, (byte) 0x3b, (byte) 0xd6, (byte) 0xb3, (byte) 0x29, (byte) 0xe3, (byte) 0x2f, (byte) 0x84},
            {(byte) 0x53, (byte) 0xd1, (byte) 0x00, (byte) 0xed, (byte) 0x20, (byte) 0xfc, (byte) 0xb1, (byte) 0x5b, (byte) 0x6a, (byte) 0xcb, (byte) 0xbe, (byte) 0x39, (byte) 0x4a, (byte) 0x4c, (byte) 0x58, (byte) 0xcf},
            {(byte) 0xd0, (byte) 0xef, (byte) 0xaa, (byte) 0xfb, (byte) 0x43, (byte) 0x4d, (byte) 0x33, (byte) 0x85, (byte) 0x45, (byte) 0xf9, (byte) 0x02, (byte) 0x7f, (byte) 0x50, (byte) 0x3c, (byte) 0x9f, (byte) 0xa8},
            {(byte) 0x51, (byte) 0xa3, (byte) 0x40, (byte) 0x8f, (byte) 0x92, (byte) 0x9d, (byte) 0x38, (byte) 0xf5, (byte) 0xbc, (byte) 0xb6, (byte) 0xda, (byte) 0x21, (byte) 0x10, (byte) 0xff, (byte) 0xf3, (byte) 0xd2},
            {(byte) 0xcd, (byte) 0x0c, (byte) 0x13, (byte) 0xec, (byte) 0x5f, (byte) 0x97, (byte) 0x44, (byte) 0x17, (byte) 0xc4, (byte) 0xa7, (byte) 0x7e, (byte) 0x3d, (byte) 0x64, (byte) 0x5d, (byte) 0x19, (byte) 0x73},
            {(byte) 0x60, (byte) 0x81, (byte) 0x4f, (byte) 0xdc, (byte) 0x22, (byte) 0x2a, (byte) 0x90, (byte) 0x88, (byte) 0x46, (byte) 0xee, (byte) 0xb8, (byte) 0x14, (byte) 0xde, (byte) 0x5e, (byte) 0x0b, (byte) 0xdb},
            {(byte) 0xe0, (byte) 0x32, (byte) 0x3a, (byte) 0x0a, (byte) 0x49, (byte) 0x06, (byte) 0x24, (byte) 0x5c, (byte) 0xc2, (byte) 0xd3, (byte) 0xac, (byte) 0x62, (byte) 0x91, (byte) 0x95, (byte) 0xe4, (byte) 0x79},
            {(byte) 0xe7, (byte) 0xc8, (byte) 0x37, (byte) 0x6d, (byte) 0x8d, (byte) 0xd5, (byte) 0x4e, (byte) 0xa9, (byte) 0x6c, (byte) 0x56, (byte) 0xf4, (byte) 0xea, (byte) 0x65, (byte) 0x7a, (byte) 0xae, (byte) 0x08},
            {(byte) 0xba, (byte) 0x78, (byte) 0x25, (byte) 0x2e, (byte) 0x1c, (byte) 0xa6, (byte) 0xb4, (byte) 0xc6, (byte) 0xe8, (byte) 0xdd, (byte) 0x74, (byte) 0x1f, (byte) 0x4b, (byte) 0xbd, (byte) 0x8b, (byte) 0x8a},
            {(byte) 0x70, (byte) 0x3e, (byte) 0xb5, (byte) 0x66, (byte) 0x48, (byte) 0x03, (byte) 0xf6, (byte) 0x0e, (byte) 0x61, (byte) 0x35, (byte) 0x57, (byte) 0xb9, (byte) 0x86, (byte) 0xc1, (byte) 0x1d, (byte) 0x9e},
            {(byte) 0xe1, (byte) 0xf8, (byte) 0x98, (byte) 0x11, (byte) 0x69, (byte) 0xd9, (byte) 0x8e, (byte) 0x94, (byte) 0x9b, (byte) 0x1e, (byte) 0x87, (byte) 0xe9, (byte) 0xce, (byte) 0x55, (byte) 0x28, (byte) 0xdf},
            {(byte) 0x8c, (byte) 0xa1, (byte) 0x89, (byte) 0x0d, (byte) 0xbf, (byte) 0xe6, (byte) 0x42, (byte) 0x68, (byte) 0x41, (byte) 0x99, (byte) 0x2d, (byte) 0x0f, (byte) 0xb0, (byte) 0x54, (byte) 0xbb, (byte) 0x16}
    };//S盒
    private final static byte[][] s_Box = new byte[16][16];//逆S盒的声明

    static {
        int k;//由于Java不支持无符号数,所以自行转换,k用于存储数组对应的无符号数
        for (int i = 0; i < 16; i++) {
            for (int j = 0; j < 16; j++) {
                k = sBox[i][j] & 0xff;//将有符号数转化成无符号数
                s_Box[k / 16][k % 16] = (byte) (i * 16 + j);
            }
        }
    }//根据S盒生成逆S盒

    private final byte[][] mMatrix = new byte[4][4];//明文状态矩阵
    private final byte[][] keys = new byte[11][16];//轮密钥,由密钥生成

    public AES(byte[] key) {
        if (key.length != 16) {
            throw new IllegalArgumentException("密钥长度应为128比特");
        }//合法检验

        {
            int[] w = new int[44];//存储字为单位的轮密钥
            int[] t = new int[10];//以字为单位的每轮的t
            byte[] x = new byte[4];//转换用到的数组

            for (int i = 0; i < 4; i++) {
                w[i] = (key[i * 4] << 24) | (key[i * 4 + 1] << 16 & 0xffffff) | (key[i * 4 + 2] << 8 & 0xffff) | (key[i * 4 + 3] & 0xff);
            }//将密钥字节转换为字存储在w中

            for (int i = 1; i <= 10; i++) {

                t[i - 1] = w[4 * i - 1] << 8 | (w[4 * i - 1] >> 24 & 0xff);//将w4n-1进行字节旋转,暂时存储在t[i-1]中
                x[0] = (byte) (t[i - 1] >> 24 & 0xff);
                x[1] = (byte) (t[i - 1] >> 16 & 0xff);
                x[2] = (byte) (t[i - 1] >> 8 & 0xff);
                x[3] = (byte) (t[i - 1] & 0xff);//将旋转后的w4n-1存储到byte数组中
                for (int k = 0; k < 4; k++) {
                    x[k] = sBox[(x[k] & 0xff) / 16][(x[k] & 0xff) % 16];
                }//进行字节代替
                t[i - 1] = (x[0] << 24) | (x[1] << 16 & 0xffffff) | (x[2] << 8 & 0xffff) | (x[3] & 0xff);//转换到字,暂时存储在t[i-1]中
                t[i - 1] = t[i - 1] ^ rC[i - 1];//与轮常数亦或,得到结果
                //计算每轮的t

                w[4 * i] = w[4 * i - 4] ^ t[i - 1];
                w[4 * i + 1] = w[4 * i - 3] ^ w[4 * i];
                w[4 * i + 2] = w[4 * i - 2] ^ w[4 * i + 1];
                w[4 * i + 3] = w[4 * i - 1] ^ w[4 * i + 2];
                //得到t后计算w4~w43

                for (int q = 0; q < 11; q++) {
                    for (int r = 0; r < 4; r++) {
                        keys[q][r * 4] = (byte) (w[q * 4 + r] >> 24 & 0xff);
                        keys[q][r * 4 + 1] = (byte) (w[q * 4 + r] >> 16 & 0xff);
                        keys[q][r * 4 + 2] = (byte) (w[q * 4 + r] >> 8 & 0xff);
                        keys[q][r * 4 + 3] = (byte) (w[q * 4 + r] & 0xff);
                    }
                }
                //将w中以字为单位存储的轮密钥转换到以字节为单位存储的轮密钥数组keys中
            }//计算10轮密钥
        }//生成轮密钥

    }//构造函数,生成指定密钥的AES对象,并根据密钥生成轮密钥

    public byte[] encryption(byte[] m) {
        int r = m.length % 16 == 0 ? m.length / 16 : m.length / 16 + 1;//需要将消息分r次进行加密,电码本模式
        byte[] c = new byte[r * 16];//返回的密文

        for (int p = 0; p < r; p++) {

            for (int j = 0; j < 4; j++) {
                for (int i = 0; i < 4; i++) {
                    try {
                        mMatrix[i][j] = m[p * 16 + j * 4 + i];
                    } catch (ArrayIndexOutOfBoundsException e) {
                    }
                }
            }//将明文装进明文矩阵
            encryption();//对明文矩阵进行AES加密
            for (int j = 0; j < 4; j++) {
                for (int i = 0; i < 4; i++) {
                    c[p * 16 + j * 4 + i] = mMatrix[i][j];
                }
            }//从明文矩阵取回结果放在c的对应位置中
            for (int i = 0; i < 4; i++) {
                Arrays.fill(mMatrix[i], (byte) 0);
            }//清空明文矩阵

        }//进行r次加密,并将密文存储在数组c中
        return c;
    }

    public byte[] decryption(byte[] c) {
        int r = c.length % 16 == 0 ? c.length / 16 : c.length / 16 + 1;//需要将消息分r次进行解密
        byte[] m = new byte[r * 16];//返回的明文

        for (int p = 0; p < r; p++) {

            for (int j = 0; j < 4; j++) {
                for (int i = 0; i < 4; i++) {
                    try {
                        mMatrix[i][j] = c[p * 16 + j * 4 + i];
                    } catch (ArrayIndexOutOfBoundsException e) {
                    }
                }
            }//将密文装进明文矩阵
            decryption();//对明文矩阵进行AES解密
            for (int j = 0; j < 4; j++) {
                for (int i = 0; i < 4; i++) {
                    m[p * 16 + j * 4 + i] = mMatrix[i][j];
                }
            }//从明文矩阵取回结果放在c的对应位置中
            for (int i = 0; i < 4; i++) {
                Arrays.fill(mMatrix[i], (byte) 0);
            }//清空明文矩阵

        }//进行r次解密,并将明文存储在数组m中
        return m;
    }

    private void encryption() {
        byte b;//用于行位移存放数据
        byte[] m = new byte[4];//用于列混合存放数据

        for (int j = 0; j < 4; j++) {
            for (int i = 0; i < 4; i++) {
                mMatrix[i][j] = (byte) ((mMatrix[i][j] & 0xff) ^ (keys[0][j * 4 + i] & 0xff));
            }
        }//进行一次轮密钥加

        for (int r = 1; r <= 10; r++) {

            for (int j = 0; j < 4; j++) {
                for (int i = 0; i < 4; i++) {
                    mMatrix[i][j] = sBox[(mMatrix[i][j] & 0xff) / 16][(mMatrix[i][j] & 0xff) % 16];
                }
            }//字节替换

            b = mMatrix[1][0];
            System.arraycopy(mMatrix[1], 1, mMatrix[1], 0, 3);
            mMatrix[1][3] = b;

            b = mMatrix[2][0];
            mMatrix[2][0] = mMatrix[2][2];
            mMatrix[2][2] = b;
            b = mMatrix[2][1];
            mMatrix[2][1] = mMatrix[2][3];
            mMatrix[2][3] = b;

            b = mMatrix[3][3];
            System.arraycopy(mMatrix[3], 0, mMatrix[3], 1, 3);
            mMatrix[3][0] = b;
            //行移位

            if (r != 10) {
                for (int j = 0; j < 4; j++) {
                    m[0] = (byte) ((multi(mMatrix[0][j], cx[0]) & 0xff) ^ (multi(mMatrix[1][j], cx[3]) & 0xff) ^ (multi(mMatrix[2][j], cx[2]) & 0xff) ^ (multi(mMatrix[3][j], cx[1]) & 0xff));
                    m[1] = (byte) ((multi(mMatrix[0][j], cx[1]) & 0xff) ^ (multi(mMatrix[1][j], cx[0]) & 0xff) ^ (multi(mMatrix[2][j], cx[3]) & 0xff) ^ (multi(mMatrix[3][j], cx[2]) & 0xff));
                    m[2] = (byte) ((multi(mMatrix[0][j], cx[2]) & 0xff) ^ (multi(mMatrix[1][j], cx[1]) & 0xff) ^ (multi(mMatrix[2][j], cx[0]) & 0xff) ^ (multi(mMatrix[3][j], cx[3]) & 0xff));
                    m[3] = (byte) ((multi(mMatrix[0][j], cx[3]) & 0xff) ^ (multi(mMatrix[1][j], cx[2]) & 0xff) ^ (multi(mMatrix[2][j], cx[1]) & 0xff) ^ (multi(mMatrix[3][j], cx[0]) & 0xff));
                    mMatrix[0][j] = m[0];
                    mMatrix[1][j] = m[1];
                    mMatrix[2][j] = m[2];
                    mMatrix[3][j] = m[3];
                }
            }//1~9轮进行列混合

            for (int j = 0; j < 4; j++) {
                for (int i = 0; i < 4; i++) {
                    mMatrix[i][j] = (byte) ((mMatrix[i][j] & 0xff) ^ (keys[r][j * 4 + i] & 0xff));
                }
            }//轮密钥加
        }//进行十轮加密
    }

    private void decryption() {
        byte b;//用于逆行位移存放数据
        byte[] m = new byte[4];//用于列混合存放数据

        for (int j = 0; j < 4; j++) {
            for (int i = 0; i < 4; i++) {
                mMatrix[i][j] = (byte) ((mMatrix[i][j] & 0xff) ^ (keys[10][j * 4 + i] & 0xff));
            }
        }//轮密钥加

        for (int r = 9; r >= 0; r--) {

            b = mMatrix[1][3];
            System.arraycopy(mMatrix[1], 0, mMatrix[1], 1, 3);
            mMatrix[1][0] = b;

            b = mMatrix[2][0];
            mMatrix[2][0] = mMatrix[2][2];
            mMatrix[2][2] = b;
            b = mMatrix[2][1];
            mMatrix[2][1] = mMatrix[2][3];
            mMatrix[2][3] = b;

            b = mMatrix[3][0];
            System.arraycopy(mMatrix[3], 1, mMatrix[3], 0, 3);
            mMatrix[3][3] = b;
            //逆行移位

            for (int j = 0; j < 4; j++) {
                for (int i = 0; i < 4; i++) {
                    mMatrix[i][j] = s_Box[(mMatrix[i][j] & 0xff) / 16][(mMatrix[i][j] & 0xff) % 16];
                }
            }//逆字节替换

            for (int j = 0; j < 4; j++) {
                for (int i = 0; i < 4; i++) {
                    mMatrix[i][j] = (byte) ((mMatrix[i][j] & 0xff) ^ (keys[r][j * 4 + i] & 0xff));
                }
            }//轮密钥加

            if (r != 0) {
                for (int j = 0; j < 4; j++) {
                    m[0] = (byte) ((multi(mMatrix[0][j], c_x[0]) & 0xff) ^ (multi(mMatrix[1][j], c_x[3]) & 0xff) ^ (multi(mMatrix[2][j], c_x[2]) & 0xff) ^ (multi(mMatrix[3][j], c_x[1]) & 0xff));
                    m[1] = (byte) ((multi(mMatrix[0][j], c_x[1]) & 0xff) ^ (multi(mMatrix[1][j], c_x[0]) & 0xff) ^ (multi(mMatrix[2][j], c_x[3]) & 0xff) ^ (multi(mMatrix[3][j], c_x[2]) & 0xff));
                    m[2] = (byte) ((multi(mMatrix[0][j], c_x[2]) & 0xff) ^ (multi(mMatrix[1][j], c_x[1]) & 0xff) ^ (multi(mMatrix[2][j], c_x[0]) & 0xff) ^ (multi(mMatrix[3][j], c_x[3]) & 0xff));
                    m[3] = (byte) ((multi(mMatrix[0][j], c_x[3]) & 0xff) ^ (multi(mMatrix[1][j], c_x[2]) & 0xff) ^ (multi(mMatrix[2][j], c_x[1]) & 0xff) ^ (multi(mMatrix[3][j], c_x[0]) & 0xff));
                    mMatrix[0][j] = m[0];
                    mMatrix[1][j] = m[1];
                    mMatrix[2][j] = m[2];
                    mMatrix[3][j] = m[3];
                }
            }//进行9轮逆列混合
        }//进行10轮解密
    }

    private byte multi(byte a, byte b) {
        int n = 0b11111111111111;//用于进行模运算
        int m = 0;

        for (int i = 0; i < 8; i++) {
            m = (b >> i & 0b1) == 1 ? m ^ ((a & 0xff) << i) : m;
        }//得到a与b相乘的结果存放在int m中

        for (int i = 0; i < 7; i++) {
            m = m > n >> i ? m ^ irreduciblePolynomial << 6 - i : m;
        }//将结果模掉8次不可约多项式irreduciblePolynomial

        return (byte) m;
    }//8比特多项式模乘运算

    static byte[] createKey() {
        byte[] key = new byte[16];
        new Random().nextBytes(key);
        return key;
    }//随机生成密钥
}

密码学课程实验,代码拿走不谢

package AES;

import java.nio.charset.StandardCharsets;

public class run1 {

    public static void main(String[] args) {
        byte[] key=AES.createKey();
        System.out.print("密钥:");
        for(int i=0;i<16;i++) {
            System.out.print(Integer.toHexString(key[i] & 0xff) + '\t');
        }
        System.out.println("");//获取密钥

        byte[] m="Hello,world!".getBytes(StandardCharsets.UTF_8);//明文内容
        byte[] c;//获取密文
        AES aes=new AES(key);


        System.out.print("明文字符:");
        for(int i=0;i<m.length;i++) {
            System.out.print(Integer.toHexString(m[i] & 0xff) + '\t');
        }
        System.out.println("");

        long startTime = System.nanoTime();
        c=aes.encryption(m);
        long endTime = System.nanoTime();

        System.out.print("密文字符:");
        for(int i=0;i<c.length;i++) {
            System.out.print(Integer.toHexString(c[i] & 0xff) + '\t');
        }
        System.out.println("");

        System.out.println("密文内容:"+new String(c,StandardCharsets.UTF_8));

        m=aes.decryption(c);
        System.out.println("解密内容:"+new String(m,StandardCharsets.UTF_8));
        System.out.println("加密时间:"+(endTime-startTime)+"ns");
    }

}

运行截图:

里面的编码格式可以在run1里面自己改的,只是参数问题 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值