利用Java实现AES算法

1、AES算法简介

AES算法是一种对称加密算法,也是一种分组加密算法,AES根据密钥长度不同可以细分为AES128,AES192和AES256,同时和DES一样具有多种工作模式,我们只实现ECB即可,至于填充方式我们使用PKCS7。

2、AES加密步骤

2.1 消息填充

把输入的 L L L长明文 M M M填充至128比特的整数倍,即
L + k ∗ 8 = 0   m o d   128 L + k * 8 = 0\ mod\ 128 L+k8=0 mod 128
填充内容是以1字节表示的消息长度,填充 k k k个字节。

填充完后,对消息每一块进行加密时,我们是吧每一块当做一个4*4字节的二维数组矩阵表示,例如把"1234567890abcdef"放入矩阵中,对应图如下

在这里插入图片描述

2.2 密钥扩展

对密钥的扩展也是对一个矩阵进行扩展,不过128是一个4*4矩阵,192是一个4*6矩阵,256是一个4*8矩阵,以128的举例,我们会把密钥竖着排列得到一个矩阵,每一列作为一轮密钥,列数称为 N k Nk Nk,然后我们根据初始的密钥进行密钥扩展,扩展至 ( N r + 1 ) ∗ 4 (Nr+1)*4 (Nr+1)4个密钥,得到 W W W,其中 N r Nr Nr N k Nk Nk对应关系如下

NkNr
410
612
814

以128的AES举例,密钥扩展到 W W W如下

在这里插入图片描述

整体 W W W扩展规则如下
W [ i ] = { k e y [ i ]   0 ≤ i < N k W [ i − N k ] ⊕ T ( W [ i − 1 ] , i / N k )   i m o d    N k = 0 W [ i − N k ] ⊕ SubWord ( W [ i − 1 ] )   N k > 6   &   i m o d    N k = 4 W [ i − N k ] ⊕ W [ i − 1 ] e l s e W[i] = \begin{cases} key[i] \quad \ 0 ≤ i < Nk\\ W[i-Nk] \oplus \text{T}(W[i-1], i/Nk) & \ i \mod Nk = 0 \\ W[i-Nk] \oplus \text{SubWord}(W[i-1]) & \ Nk>6 \ \& \ i \mod Nk=4 \\ W[i-Nk] \oplus W[i-1] & else \end{cases} W[i]= key[i] 0i<NkW[iNk]T(W[i1],i/Nk)W[iNk]SubWord(W[i1])W[iNk]W[i1] imodNk=0 Nk>6 & imodNk=4else
其中 T T T函数是
T = SubWord ( RotWord ( W [ i − 1 ] ) ) ⊕ R C O N [ r o u n d ] < < 24 T = \text{SubWord}(\text{RotWord}(W[i-1])) \oplus RCON[round] << 24 T=SubWord(RotWord(W[i1]))RCON[round]<<24
R o t W o r d RotWord RotWord是左循环一位, S u b W o r d SubWord SubWord是字节替换, R C O N RCON RCON是一个常量

2.3 轮密钥加

单纯的消息块与密钥进行对应异或。

2.4 字节替换

利用S盒进行对应替换。

2.5 行移位

对消息块,第一行不移动,第二行循环左移1个字节,第三行循环左移2字节,第四行循环左移3字节。

2.6 列混淆

将消息块与矩阵相乘

[ b 0 , 0 b 0 , 1 b 0 , 2 b 0 , 3 b 1 , 0 b 1 , 1 b 1 , 2 b 1 , 3 b 2 , 0 b 2 , 1 b 2 , 2 b 2 , 3 b 3 , 0 b 3 , 1 b 3 , 2 b 3 , 3 ] = [ 2 3 1 1 1 2 1 1 1 1 2 3 3 1 3 2 ] [ a 0 , 0 a 0 , 1 a 0 , 2 a 0 , 3 a 1 , 0 a 1 , 1 a 1 , 2 a 1 , 3 a 2 , 0 a 2 , 1 a 2 , 2 a 2 , 3 a 3 , 0 a 3 , 1 a 3 , 2 a 3 , 3 ] \begin{bmatrix} b_{0,0} & b_{0,1} & b_{0,2} & b_{0,3} \\ b_{1,0} & b_{1,1} & b_{1,2} & b_{1,3} \\ b_{2,0} & b_{2,1} & b_{2,2} & b_{2,3} \\ b_{3,0} & b_{3,1} & b_{3,2} & b_{3,3} \\ \end{bmatrix} =\begin{bmatrix} 2 & 3 & 1 & 1 \\ 1 & 2 & 1 & 1 \\ 1 & 1 & 2 & 3 \\ 3 & 1 & 3 & 2 \\ \end{bmatrix} \begin{bmatrix} a_{0,0} & a_{0,1} & a_{0,2} & a_{0,3} \\ a_{1,0} & a_{1,1} & a_{1,2} & a_{1,3} \\ a_{2,0} & a_{2,1} & a_{2,2} & a_{2,3} \\ a_{3,0} & a_{3,1} & a_{3,2} & a_{3,3} \\ \end{bmatrix} b0,0b1,0b2,0b3,0b0,1b1,1b2,1b3,1b0,2b1,2b2,2b3,2b0,3b1,3b2,3b3,3 = 2113321111231132 a0,0a1,0a2,0a3,0a0,1a1,1a2,1a3,1a0,2a1,2a2,2a3,2a0,3a1,3a2,3a3,3

我们写代码使用 X T i m e XTime XTime乘法更加便捷

{ b 0 , j = X T i m e ( a 0 , j ) ⊕ X T i m e ( a 1 , j ) ⊕ a 1 , j ⊕ a 2 , j ⊕ a 3 , j b 1 , j = a 0 , j ⊕ X T i m e ( a 1 , j ) ⊕ X T i m e ( a 2 , j ) ⊕ a 2 , j ⊕ a 3 , j b 2 , j = a 0 , j ⊕ a 1 , j ⊕ X T i m e ( a 2 , j ) ⊕ X T i m e ( a 3 , j ) ⊕ a 3 , j b 3 , j = X T i m e ( a 0 , j ) ⊕ a 0 , j ⊕ a 1 , j ⊕ a 2 , j ⊕ X T i m e ( a 3 , j ) \begin{cases} b_{0,j} = XTime(a_{0,j}) \oplus XTime(a_{1,j}) \oplus a_{1,j} \oplus a_{2,j} \oplus a_{3,j}\\ b_{1,j} = a_{0,j} \oplus XTime(a_{1,j}) \oplus XTime(a_{2,j}) \oplus a_{2,j} \oplus a_{3,j}\\ b_{2,j} = a_{0,j} \oplus a_{1,j} \oplus XTime(a_{2,j}) \oplus XTime(a_{3,j}) \oplus a_{3,j}\\ b_{3,j} = XTime(a_{0,j}) \oplus a_{0,j} \oplus a_{1,j} \oplus a_{2,j} \oplus XTime(a_{3,j})\\ \end{cases} b0,j=XTime(a0,j)XTime(a1,j)a1,ja2,ja3,jb1,j=a0,jXTime(a1,j)XTime(a2,j)a2,ja3,jb2,j=a0,ja1,jXTime(a2,j)XTime(a3,j)a3,jb3,j=XTime(a0,j)a0,ja1,ja2,jXTime(a3,j)

这里还要强调一下逆列混淆,要乘另外一个矩阵

[ b 0 , 0 b 0 , 1 b 0 , 2 b 0 , 3 b 1 , 0 b 1 , 1 b 1 , 2 b 1 , 3 b 2 , 0 b 2 , 1 b 2 , 2 b 2 , 3 b 3 , 0 b 3 , 1 b 3 , 2 b 3 , 3 ] = [ 0 E 0 B 0 D 09 09 0 E 0 B 0 D 0 D 09 0 E 0 B 0 B 0 D 09 0 E ] [ a 0 , 0 a 0 , 1 a 0 , 2 a 0 , 3 a 1 , 0 a 1 , 1 a 1 , 2 a 1 , 3 a 2 , 0 a 2 , 1 a 2 , 2 a 2 , 3 a 3 , 0 a 3 , 1 a 3 , 2 a 3 , 3 ] \begin{bmatrix} b_{0,0} & b_{0,1} & b_{0,2} & b_{0,3} \\ b_{1,0} & b_{1,1} & b_{1,2} & b_{1,3} \\ b_{2,0} & b_{2,1} & b_{2,2} & b_{2,3} \\ b_{3,0} & b_{3,1} & b_{3,2} & b_{3,3} \\ \end{bmatrix} = \begin{bmatrix} 0E & 0B & 0D & 09 \\ 09 & 0E & 0B & 0D \\ 0D & 09 & 0E & 0B \\ 0B & 0D & 09 & 0E \\ \end{bmatrix} \begin{bmatrix} a_{0,0} & a_{0,1} & a_{0,2} & a_{0,3} \\ a_{1,0} & a_{1,1} & a_{1,2} & a_{1,3} \\ a_{2,0} & a_{2,1} & a_{2,2} & a_{2,3} \\ a_{3,0} & a_{3,1} & a_{3,2} & a_{3,3} \\ \end{bmatrix} b0,0b1,0b2,0b3,0b0,1b1,1b2,1b3,1b0,2b1,2b2,2b3,2b0,3b1,3b2,3b3,3 = 0E090D0B0B0E090D0D0B0E09090D0B0E a0,0a1,0a2,0a3,0a0,1a1,1a2,1a3,1a0,2a1,2a2,2a3,2a0,3a1,3a2,3a3,3
实现这个过程最好使用伽罗华域的二元运算,即 G M u l GMul GMul运算
{ b 0 , j = G M u l ( 0 E , a 0 , j ) ⊕ G M u l ( 0 B , a 0 , j ) ⊕ G M u l ( 0 D , a 0 , j ) ⊕ G M u l ( 09 , a 0 , j ) b 1 , j = G M u l ( 09 , a 0 , j ) ⊕ G M u l ( 0 E , a 0 , j ) ⊕ G M u l ( 0 B , a 0 , j ) ⊕ G M u l ( 0 D , a 0 , j ) b 2 , j = G M u l ( 0 D , a 0 , j ) ⊕ G M u l ( 09 , a 0 , j ) ⊕ G M u l ( 0 E , a 0 , j ) ⊕ G M u l ( 0 B , a 0 , j ) b 3 , j = G M u l ( 0 B , a 0 , j ) ⊕ G M u l ( 0 D , a 0 , j ) ⊕ G M u l ( 09 , a 0 , j ) ⊕ G M u l ( 0 E , a 0 , j ) \begin{cases} b_{0,j} = GMul(0E,a_{0,j}) \oplus GMul(0B,a_{0,j}) \oplus GMul(0D,a_{0,j}) \oplus GMul(09,a_{0,j})\\ b_{1,j} = GMul(09,a_{0,j}) \oplus GMul(0E,a_{0,j}) \oplus GMul(0B,a_{0,j}) \oplus GMul(0D,a_{0,j})\\ b_{2,j} = GMul(0D,a_{0,j}) \oplus GMul(09,a_{0,j}) \oplus GMul(0E,a_{0,j}) \oplus GMul(0B,a_{0,j})\\ b_{3,j} = GMul(0B,a_{0,j}) \oplus GMul(0D,a_{0,j}) \oplus GMul(09,a_{0,j}) \oplus GMul(0E,a_{0,j})\\ \end{cases} b0,j=GMul(0Ea0,j)GMul(0Ba0,j)GMul(0Da0,j)GMul(09a0,j)b1,j=GMul(09a0,j)GMul(0Ea0,j)GMul(0Ba0,j)GMul(0Da0,j)b2,j=GMul(0Da0,j)GMul(09a0,j)GMul(0Ea0,j)GMul(0Ba0,j)b3,j=GMul(0Ba0,j)GMul(0Da0,j)GMul(09a0,j)GMul(0Ea0,j)

3、代码实现

创建AES类

public class AES{}

明文要以4*4字节矩阵存储,使用的byte二维数组,密钥便以byte一维数组存储。

3.1 参数准备

//常量
private static final int[] RCON = {
        0x00,//占位
        0x01, 0x02, 0x04, 0x08, 0x10,
        0x20, 0x40, 0x80, 0x1B, 0x36
};
//S盒
private static final int[] S = {
        0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
        0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
        0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
        0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
        0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
        0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
        0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
        0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
        0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
        0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
        0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
        0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
        0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
        0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
        0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
        0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};
//逆S盒
private static final int[] INV_S = {
        0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
        0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
        0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
        0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
        0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
        0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
        0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
        0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
        0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
        0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
        0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
        0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
        0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
        0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
        0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
        0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
};

3.2 工具函数准备

//转换函数
private static byte[][] SHIFT(byte[] in) {
    byte[][] out = new byte[4][4];
    for (int i = 0;i < 16;i++) {
        out[i % 4][i / 4] = in[i];
    }
    return out;
}
//逆转换
private static byte[] INV_SHIFT(byte[][] in) {
    byte[] out = new byte[16];
    for (int i = 0;i < 16;i++) {
        out[i] = in[i % 4][i / 4];
    }
    return out;
}
//T函数
private static int T(int word,int round) {
    return SubWord(RotWord(word)) ^ (RCON[round] << 24);
}
//32位字节S盒代换
private static int SubWord(int word) {
    int b0 = S[(word >>> 24) & 0xFF];
    int b1 = S[(word >>> 16) & 0xFF];
    int b2 = S[(word >>> 8) & 0xFF];
    int b3 = S[word & 0xFF];
    return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
}
//32位字节循环移位
private static int RotWord(int word) {
    return (word << 8) | ((word >>> 24) & 0xFF);
}
//XTime运算
private static byte XTime(byte x) {
    return (byte) ((x << 1) ^ (((x >>> 17) & 1) * 0x1B));
}
//乘法函数
private static byte MUL(byte a,int b) {
    int aa = a & 0xFF;  // 保证无符号运算
    int bb = b & 0xFF;
    int p = 0;

    for (int i = 0; i < 8; i++) {
        if ((bb & 0x01) != 0) p ^= aa;
        boolean highBitSet = (aa & 0x80) != 0;
        aa = (aa << 1) & 0xFF;
        if (highBitSet) aa ^= 0x1B;
        bb >>= 1;
    }

    return (byte) p;
}

3.3 密钥扩展

private int[] KeyExpansion(byte[] key,int Nk,int Nr) {
    //获取轮密钥
    int[] W = new int[4 * (Nr + 1)];

    //赋值已有密钥
    for (int i = 0;i < Nk;i++) {
        W[i] = ((key[4 * i] & 0xFF) << 24) |
                ((key[4 * i + 1] & 0xFF) << 16) |
                ((key[4 * i + 2] & 0xFF) << 8) |
                (key[4 * i + 3] & 0xFF);
    }

    //生成剩下的密钥
    for (int i = Nk;i < W.length;i++) {
        int temp = W[i - 1];
        if (i % Nk == 0) temp = T(temp,i / Nk);
        else if (Nk > 6 && (i % Nk == 4)) temp = SubWord(temp);
        W[i] = W[i - Nk] ^ temp;
    }

    return W;
}

3.4 轮密钥加

private void AddRoundKey(byte[][] state,int[] W,int round) {
    for (int col = 0;col < 4;col++) {
        int word = W[round * 4 + col];

        state[0][col] ^= (byte) ((word >>> 24) & 0xFF);
        state[1][col] ^= (byte) ((word >>> 16) & 0xFF);
        state[2][col] ^= (byte) ((word >>> 8) & 0xFF);
        state[3][col] ^= (byte) (word & 0xFF);
    }
}

3.3 字节替换和逆字节替换

//字节替换
private void SubBytes(byte[][] state) {
    for (int row = 0;row < 4;row++) {
        for (int col = 0;col < 4;col++) {
            state[row][col] = (byte) (S[state[row][col] & 0xFF] & 0xFF);
        }
    }
}
//逆字节替换
private void InvSubBytes(byte[][] state) {
    for (int row = 0;row < 4;row++) {
        for (int col = 0;col < 4;col++) {
            state[row][col] = (byte) (INV_S[state[row][col] & 0xFF] & 0xFF);
        }
    }
}

3.4 行移位和逆行移位

//行移位
private void ShiftRows(byte[][] state) {
    //左移1位
    byte temp = state[1][0];
    for (int i = 0;i < 3;i++) {
        state[1][i] = state[1][i + 1];
    }
    state[1][3] = temp;

    //左移2位
    byte t1 = state[2][0],t2 = state[2][1];
    state[2][0] = state[2][2];
    state[2][1] = state[2][3];
    state[2][2] = t1;
    state[2][3] = t2;

    //左移3位(右移1位)
    temp = state[3][3];
    for (int i = 3;i > 0;i--) {
        state[3][i] = state[3][i - 1];
    }
    state[3][0] = temp;
}
//逆行移位
private void InvShiftRows(byte[][] state) {
    //右移1位
    byte temp = state[1][3];
    for (int i = 3; i > 0; i--) {
        state[1][i] = state[1][i - 1];
    }
    state[1][0] = temp;

    //右移2位
    byte t1 = state[2][0], t2 = state[2][1];
    state[2][0] = state[2][2];
    state[2][1] = state[2][3];
    state[2][2] = t1;
    state[2][3] = t2;

    //右移3位
    temp = state[3][0];
    for (int i = 0; i < 3; i++) {
        state[3][i] = state[3][i + 1];
    }
    state[3][3] = temp;
}

3.5 列混淆和逆列混淆

//列混淆
private void MixColumns(byte[][] state) {
    //使用XTime函数计算
    for (int col = 0;col < 4;col++) {
        byte s0 = state[0][col];
        byte s1 = state[1][col];
        byte s2 = state[2][col];
        byte s3 = state[3][col];

        state[0][col] = (byte) (XTime(s0) ^ XTime(s1) ^ s1 ^ s2 ^ s3);
        state[1][col] = (byte) (s0 ^ XTime(s1) ^ XTime(s2) ^ s2 ^ s3);
        state[2][col] = (byte) (s0 ^ s1 ^ XTime(s2) ^ XTime(s3) ^ s3);
        state[3][col] = (byte) (XTime(s0) ^ s0 ^ s1 ^ s2 ^ XTime(s3));
    }
}
//逆列混淆
private void InvMixColumns(byte[][] state) {
    //使用MUL函数计算
    for (int col = 0; col < 4; col++) {
        byte s0 = state[0][col];
        byte s1 = state[1][col];
        byte s2 = state[2][col];
        byte s3 = state[3][col];

        state[0][col] = (byte) (MUL(s0, 0x0e) ^ MUL(s1, 0x0b) ^ MUL(s2, 0x0d) ^ MUL(s3, 0x09));
        state[1][col] = (byte) (MUL(s0, 0x09) ^ MUL(s1, 0x0e) ^ MUL(s2, 0x0b) ^ MUL(s3, 0x0d));
        state[2][col] = (byte) (MUL(s0, 0x0d) ^ MUL(s1, 0x09) ^ MUL(s2, 0x0e) ^ MUL(s3, 0x0b));
        state[3][col] = (byte) (MUL(s0, 0x0b) ^ MUL(s1, 0x0d) ^ MUL(s2, 0x09) ^ MUL(s3, 0x0e));
    }
}

3.6 加密函数

public byte[] Encrypt(byte[] msg,byte[] key) {
    int keyLength = key.length;

    //根据密钥长度不同,处理不同
    int Nk,Nr;
    if (keyLength == 16) {
        Nk = 4;Nr = 10;
    } else if (keyLength == 24) {
        Nk = 6;Nr = 12;
    } else if (keyLength == 32) {
        Nk = 8;Nr = 14;
    } else {
        throw new IllegalArgumentException("密钥长度错误");
    }

    //使用PKCS7填充
    int paddingLength = 16 - (msg.length % 16);
    byte[] paddedMsg = new byte[msg.length + paddingLength];
    System.arraycopy(msg, 0, paddedMsg, 0, msg.length);

    // 填充 paddingLength 个值为 paddingLength 的字节
    for (int i = msg.length; i < paddedMsg.length; i++) {
        paddedMsg[i] = (byte) paddingLength;
    }

    int n = paddedMsg.length / 16;
    //获取轮密钥
    int[] W = KeyExpansion(key,Nk,Nr);
    byte[] C = new byte[n * 16];
    //对每块操作
    for (int i = 0;i < n;i++) {
        byte[] block = Arrays.copyOfRange(paddedMsg,i * 16,(i + 1) * 16);
        byte[][] blockA = SHIFT(block);
        AddRoundKey(blockA,W,0);
        for (int j = 1;j < Nr;j++) {
            SubBytes(blockA);
            ShiftRows(blockA);
            MixColumns(blockA);
            AddRoundKey(blockA,W,j);
        }
        SubBytes(blockA);
        ShiftRows(blockA);
        AddRoundKey(blockA,W,Nr);
        System.arraycopy(INV_SHIFT(blockA),0,C,i * 16,16);
    }
    return C;
}

3.7 解密函数

public byte[] Decrypt(byte[] msg,byte[] key) {
    int keyLength = key.length;

    int Nk,Nr;
    if (keyLength == 16) {
        Nk = 4;Nr = 10;
    } else if (keyLength == 24) {
        Nk = 6;Nr = 12;
    } else if (keyLength == 32) {
        Nk = 8;Nr = 14;
    } else {
        throw new IllegalArgumentException("密钥长度错误");
    }

    int n = msg.length / 16;
    byte[] paddedMsg = new byte[n * 16];
    System.arraycopy(msg,0,paddedMsg,0,msg.length);

    int[] W = KeyExpansion(key,Nk,Nr);
    byte[] M = new byte[n * 16];

    for (int i = 0;i < n;i++) {
        byte[] block = Arrays.copyOfRange(paddedMsg,i * 16,(i + 1) * 16);
        byte[][] blockA = SHIFT(block);
        AddRoundKey(blockA,W,Nr);
        for (int j = Nr - 1;j >= 1;j--) {
            InvShiftRows(blockA);
            InvSubBytes(blockA);
            AddRoundKey(blockA,W,j);
            InvMixColumns(blockA);
        }
        InvShiftRows(blockA);
        InvSubBytes(blockA);
        AddRoundKey(blockA,W,0);
        System.arraycopy(INV_SHIFT(blockA),0,M,i * 16,16);
    }

    // 去除 PKCS#7 填充
    int padding = M[M.length - 1] & 0xFF;
    if (padding <= 0 || padding > 16) throw new IllegalArgumentException("填充长度不对");

    // 验证填充是否一致
    for (int i = M.length - padding; i < M.length; i++) {
        if ((M[i] & 0xFF) != padding) {
            throw new IllegalArgumentException("填充错误");
        }
    }
    return Arrays.copyOf(M, M.length - padding);
}

4、结果验证

4.1 加密解密验证-128

测试数据

{
    "msg":"00112233445566778899aabbccddeeff",
    "key":"2b7e151628aed2a6abf7158809cf4f3c"
}

结果

在这里插入图片描述

验证

在这里插入图片描述

解密

在这里插入图片描述

4.2 加密解密验证-192

测试数据

{
    "msg":"00112233445566778899aabbccddeeff",
    "key":"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"
}

结果
在这里插入图片描述

验证
在这里插入图片描述

解密

在这里插入图片描述

4.3 加密解密验证-256

测试数据

{
    "msg":"00112233445566778899aabbccddeeff",
    "key":"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"
}

结果
在这里插入图片描述

结果验证

在这里插入图片描述

解密

在这里插入图片描述

证明AES成功实现

5、后记

本篇文章参考了

AES算法描述及C语言实现_c语言实现aes算法-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值