实验内容

实现128位高级加密标准AES对信息的加密与解密。

具体算法

分组长度128bit,密钥长度128bit 圈数round=10 域GF(2^8)的不可约多项式为x^8+x^4+x^3+x+1

字节替代

对每一个字节本身进行替代 首先是在有限域GF(2^8)上求乘法逆,00映射到自身。求有限域乘法逆调用的是上次实验中的求逆的子程序。使用的是扩展欧几里得算法。 接下来进行如下的仿射变换:乘以矩阵 \(\begin{pmatrix} 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 \\ \end{pmatrix}\) 计算出这个表,迭代的时候直接在表中找映射值。

将字节代换的表使用一个长度为256的数组存储,索引对应的是二进制串的数值。每一个位置存储一个8位的二进制串。对于每一个8位的二进制串,通过上述方法计算出它的字节替换结果之后填入表对应位置中。同时,也可以将逆字节代换表的对应位置也填上,只要将索引同值换一下位置即可。

在程序中,使用全局变量Sbox和Inv_Sbox来分别表示字节代换和逆字节代换。在CreateSbox函数中,计算S盒以及逆S盒,更新这两个全局变量。

/*创建S盒以及逆S盒*/
bitset<8> Sbox[256] ={0};
bitset<8> Inv_Sbox[256] = {0};
for(int i = 0; i < 256; i++){
        bitset<8> temp(i);
        bitset<8> inv_t = inv(temp);
        bitset<8> c_x("01100011");
        bitset<8> b;
        for(int j = 0; j < 8; j++){
            b[j] = inv_t[j]^inv_t[(j+4)%8]^inv_t[(j+5)%8]^inv_t[(j+6)%8]^inv_t[(j+7)%8]^c_x[j];
        }
        Sbox[i] = b;
        Inv_Sbox[b.to_ulong()] = temp;
    }

字节移位

分组长度为4的情况下,后三行循环移位字节量如下,循环左移 C1:1,C2:2,C3:3

ByteRotation函数中,接收一个二进制串的vector,以及循环左移移位量,这个vector代表的是一个word,即四个字节。这里进行的是对这四个字节进行循环左移指定位数的操作。

全局变量定义了SHIFT和INV_SHIFT,分别代表加密时每一行循环左移的移位量以及解密时每一行循环左移的移位量。在对应的加解密程序中确定每一行的移位量。

#define SHIFT {0,1,2,3}
#define INV_SHIFT {0,3,2,1}
void ByteRotation(vector<byte_def> &input,int shift_byte){
    for(int i = 0; i < shift_byte; i++){
        input.push_back(input[0]);
        input.erase(input.begin());
    }
}

列混合

加密的时候,相当于乘一个矩阵,矩阵如下 \(\begin{pmatrix} 2&3&1&1 \\ 1&2&3&1 \\ 1&1&2&3 \\ 3&1&1&2 \\ \end{pmatrix}\) 在MixColumn函数中,接收一个使用vector表示的矩阵,对此矩阵进行列混合操作。这里调用的mul函数是进行域乘法的子程序

解密的时候,相当于乘以上面矩阵在有限域下的逆矩阵,即 \(\begin{pmatrix} e&b&d&9\\ 9&e&b&d\\ d&9&e&b\\ b&d&9&e\\ \end{pmatrix}\)

/*列混合加密*/
void MixColumn(vector<vector<byte_def>> &input){
    byte_def result[4][4] = {0};
    byte_def x("00000010");
    byte_def x1("00000011");
    for(int col = 0; col < 4; col++){
        result[0][col] = mul(x,input[0][col])^mul(x1,input[1][col])^input[2][col]^input[3][col];
        result[1][col] = mul(x,input[1][col])^mul(x1,input[2][col])^input[3][col]^input[0][col];
        result[2][col] = mul(x,input[2][col])^mul(x1,input[3][col])^input[0][col]^input[1][col];
        result[3][col] = mul(x,input[3][col])^mul(x1,input[0][col])^input[1][col]^input[2][col];
    }
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < ROW_SIZE; j++){
            input[i][j] = result[i][j];
        }
    }
}
/*列混合解密*/
void Inv_MixColumn(vector<vector<byte_def>> &input){
    byte_def result[4][4] = {0};
    byte_def x_0e(0x0e);
    byte_def x_0b(0x0b);
    byte_def x_0d(0x0d);
    byte_def x_09(0x09);
    for(int col = 0; col < 4; col++){
        result[0][col] = mul(x_0e,input[0][col])^mul(x_0b,input[1][col])^mul(x_0d,input[2][col])^mul(x_09,input[3][col]);
        result[1][col] = mul(x_0e,input[1][col])^mul(x_0b,input[2][col])^mul(x_0d,input[3][col])^mul(x_09,input[0][col]);
        result[2][col] = mul(x_0e,input[2][col])^mul(x_0b,input[3][col])^mul(x_0d,input[0][col])^mul(x_09,input[1][col]);
        result[3][col] = mul(x_0e,input[3][col])^mul(x_0b,input[0][col])^mul(x_0d,input[1][col])^mul(x_09,input[2][col]);
    }
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < ROW_SIZE; j++){
            input[i][j] = result[i][j];
        }
    }
}

圈密相加

将圈密钥与状态按比特异或,圈密钥长度为分组长度128bit。AddRoundKey函数接收一个矩阵以及轮数作为输入,取相对应轮数的圈密钥,加到矩阵上

void AddRoundKey(vector<vector<byte_def>> &input, int round){
    vector<vector<byte_def>> this_round_key = expand_key[round];
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < ROW_SIZE; j++){
            input[i][j] ^= this_round_key[i][j];
        }
    }
}

密钥扩展

密钥总长度=分组长度*(圈数+1) 最开始明文需要异或密钥,以及每一轮最后需要异或密钥 初始密钥K0,K1,K2,K3 SubWord子程序对输入的word的每一个字节进行S盒操作,RotWord子程序对输入的word进行一个字节的移位。

在密钥扩展的子程序KeyExpansion中,接收一个初始的矩阵,即圈密钥0。依据这个初始密钥生成剩下的10个圈密钥。使用一个全局变量expand_key来存储每一轮使用的圈密钥。密钥扩展中需要用到的Rcon使用全局变量来定义。由于这里的一个word使用了四个byte来表示,而Rcon的后面三个byte全为0,因此其实只需要对word的第一个byte进行异或Rcon的第一个byte即可。Rcon的定义只取了它每一个的第一个byte

vector<vector<vector<byte_def>>> expand_key;
byte_def Rcon[10] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36};
void KeyExpansion(vector<vector<byte_def>> initialKey){
    vector<vector<byte_def>> w_key;
    //处理一下初始的密钥,将它拆分为四个word,并按照密钥扩展的指定顺序存放到w_key里
    for(int i = 0; i < ROW_SIZE; i++){
        vector<byte_def> helper;
        helper.push_back(initialKey[0][i]);
        helper.push_back(initialKey[1][i]);
        helper.push_back(initialKey[2][i]);
        helper.push_back(initialKey[3][i]);
        w_key.push_back(helper);
    }
    //进行密钥扩展,操作单位为word
    vector<byte_def> temp;
    for(int i = 4; i <44; i++){
        temp = w_key[i-1];
        if(i % 4 == 0){
            RotWord(temp);
            SubWord(temp);
            temp[0] ^= Rcon[i/4-1];
        }
        for(int k = 0; k < ROW_SIZE; k++){
            temp[k] ^= w_key[i-4][k];
        }
        w_key.push_back(temp);

    }
    //取w_key中的word四个一组,存放到全局变量expand_key中
    for(int i = 0; i <= ROUND; i++){
        vector<vector<byte_def>> round_temp;
        vector<byte_def> key_temp;
        for(int j = 0; j < 4; j++){
            key_temp.clear();
            key_temp.push_back(w_key[i*4][j]);
            key_temp.push_back(w_key[i*4+1][j]);
            key_temp.push_back(w_key[i*4+2][j]);
            key_temp.push_back(w_key[i*4+3][j]);
            round_temp.push_back(key_temp);
        }
        expand_key.push_back(round_temp);
    }
}

AES加密

函数void AES(vector<vector> &current_group)接收一个矩阵作为输入,对此矩阵进行AES的加密操作:异或圈密钥0,然后进行9轮的字节替换,字节移位,列混合以及密钥加的操作,最后再进行一轮字节替换,字节移位,异或圈密钥10。

encode函数接收字符串明文作为输入,循环读入长度为16的字符串,将这16个字符串转化成AES输入的矩阵,先异或一下IV之后放进AES子程序中进行加密,加密完之后,密文作为下一组的IV,更新IV的值,并将密文存入ciphertext变量中。其中,将明文转换为矩阵通过一个名为Padding的函数进行,在此函数中,读入一定长度的字符串,先判断长度是否小于等于16,再计算此字符串的长度比16少多少,将少的长度记为n,将字符串填充为16长度的时候补充0x0n。

AES解密

函数void Inv_AES(vector<vector> & current_group)接收一个矩阵作为输入,对此矩阵进行AES解密的操作:异或圈密钥10,逆行变换,逆字节替代,异或K9,然后进行剩下9轮的逆列变换,逆行变换,逆字节替代,密钥加的操作,其中这里使用的圈密钥是逆序使用的,即先使用圈密钥8,再使用圈密钥7以此类推。

decode函数接收密文,ciphertext。循环读入16个字节,将这16个字节依序放入矩阵中,将此矩阵放到AES解密的子程序里面进行解密,最后再异或一下IV,并更新IV为这一组原来的密文,供下一组解密使用。

运行截图

计算出来的S盒以及逆S盒

w_key计算

圈密钥

加密解密结果

结果分析

S盒的计算以及逆S盒,对比书上给出的S盒以及这里计算出的S盒,结果相同说明S盒计算无误。另外,S盒的索引值以及其对应的值,刚好与逆S盒的值和索引一一相互对应回去。说明逆S盒计算也无误。(比如S盒中索引为00的地方值是63,逆S盒中索引为63的地方值为00)

w_key的计算,根据书上给出的算法实现。手动计算了一下粗略验证了w5和w6,发现计算的结果无误,可以推定w_key的算法实现无误

圈密钥的生成。一个圈密钥是由四个wkey生成的,其中要注意的是从wkey到圈密钥的排放顺序,wkey0对应的是圈密钥的第一列,wkey1是第二列,以此类推。可以看到圈密钥输出的结果正是4个wkey按照给定规则排列成的。

程序加密的结果和网站加密的结果相同,且能够正确解密出密文,说明加密和解密的结果无误。

网站加密结果

//cipher key "yaojieqian"
//work mode: CBC
//IV: "123"
//PKCS5Padding
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<bitset>
#include<cmath>
#include<vector>
#include<iomanip>
#define GROUP_LEN 128 //分组长度128
#define ROW_LEN 32 //单行长度
#define ROW_SIZE 4 //单行字节数
#define SHIFT {0,1,2,3}
#define INV_SHIFT {0,3,2,1} //仅用在解密处,循环左移的位数
#define ROUND 10
#define SIZE_N 8
#define r_str "11011"//x^4+x^3+x+1
#define poly_str "100011011"
#define debug 1
using namespace std;
typedef bitset<8> byte_def;
typedef bitset<32> word_def;
bitset<8> Sbox[256] ={0};
bitset<8> Inv_Sbox[256] = {0};
vector<vector<vector<byte_def>>> expand_key;
byte_def Rcon[10] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36};
bitset<SIZE_N> mod(bitset<SIZE_N*2> op1, bitset<SIZE_N> r){
    bitset<SIZE_N> res(0);
    bitset<SIZE_N*2> helper;
    bitset<SIZE_N*2> extend_r(r.to_ulong());
    for(int i = SIZE_N*2-1; i >= SIZE_N; i--){
        if(op1[i]){
            helper = extend_r << (i-SIZE_N);
            op1 ^= helper;
            op1[i] = 0;
        }
    }
    for(int i = 0; i < SIZE_N; i++) 
        res[i] = op1[i];
    return res;    
}
bitset<SIZE_N> mul(bitset<SIZE_N> op1, bitset<SIZE_N> op2){
    bitset<SIZE_N*2> raw_res(0);//存储两数相乘的直接结果
    bitset<SIZE_N> res(0);//经过模运算之后的结果
    bitset<SIZE_N> r(r_str);
    bitset<SIZE_N*2> extend_op1(op1.to_string());//需要对其进行左移,故扩展成原长度的两倍
    for(int i = 0; i < SIZE_N; i++){
        if(op2[i]){
            raw_res ^= (extend_op1<<i);
        }
    }
    res = mod(raw_res,r);
    return res;
}
int max_exp(bitset<SIZE_N+1> op){
    for(int i = SIZE_N; i > -1; i--){
        if(op[i])
            return i;
    }
    return 0;
}
bitset<SIZE_N> inv(bitset<SIZE_N> op){
    if(!op.any()){
        bitset<SIZE_N> res(0);
        return  res;
    }
    bitset<SIZE_N+1> poly(poly_str);
    bitset<SIZE_N+1> k1(op.to_string());
    bitset<SIZE_N+1> k2(poly.to_string());
    bitset<SIZE_N+1> ktemp;
    bitset<SIZE_N> x1(0);
    bitset<SIZE_N> x2(0);
    bitset<SIZE_N> temp;
    x1[0] = 1;
    int diff_exp;
    while(max_exp(k1)){
        diff_exp = max_exp(k1)-max_exp(k2);
        if(diff_exp < 0){
            diff_exp = -diff_exp;
            ktemp = k1;
            k1 = k2;
            k2 = ktemp;
            temp = x1;
            x1 = x2;
            x2 = temp;
        }
        k1 ^= (k2<<diff_exp);
        x1 ^= (x2<<diff_exp);
    }
    return x1;
}
//创建S盒以及逆S盒
void CreateSbox(){
    for(int i = 0; i < 256; i++){
        bitset<8> temp(i);
        bitset<8> inv_t = inv(temp);
        bitset<8> c_x("01100011");
        bitset<8> b;
        for(int j = 0; j < 8; j++){
            b[j] = inv_t[j]^inv_t[(j+4)%8]^inv_t[(j+5)%8]^inv_t[(j+6)%8]^inv_t[(j+7)%8]^c_x[j];
        }
        Sbox[i] = b;
        Inv_Sbox[b.to_ulong()] = temp;
    }
    cout<<"S box calculated:"<<endl;
    for(int i = 0; i < 16; i++){
        for(int j = 0; j < 16; j++){
            cout<<setw(2)<<setfill('0')<<hex<<Sbox[i*16+j].to_ulong()<<" ";
        }
        cout<<endl;
    }
    cout<<"Inv S box calculated:"<<endl;
    for(int i = 0; i < 16; i++){
        for(int j = 0; j < 16; j++){
            cout<<setw(2)<<setfill('0')<<hex<<Inv_Sbox[i*16+j].to_ulong()<<" ";
        }
        cout<<endl;
    }
}
byte_def ByteSubsitution(byte_def input){
    return Sbox[input.to_ulong()];
}
byte_def Inv_ByteSusitution(byte_def input){
    return Inv_Sbox[input.to_ulong()];
}
//对分组进行行移位
//input输入是128bit的
void ByteRotation(vector<byte_def> &input,int shift_byte){
    for(int i = 0; i < shift_byte; i++){
        input.push_back(input[0]);
        input.erase(input.begin());
    }
    return;
}
void MixColumn(vector<vector<byte_def>> &input){
    byte_def result[4][4] = {0};
    byte_def x("00000010");
    byte_def x1("00000011");
    for(int col = 0; col < 4; col++){
        result[0][col] = mul(x,input[0][col])^mul(x1,input[1][col])^input[2][col]^input[3][col];
        result[1][col] = mul(x,input[1][col])^mul(x1,input[2][col])^input[3][col]^input[0][col];
        result[2][col] = mul(x,input[2][col])^mul(x1,input[3][col])^input[0][col]^input[1][col];
        result[3][col] = mul(x,input[3][col])^mul(x1,input[0][col])^input[1][col]^input[2][col];
    }
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < ROW_SIZE; j++){
            input[i][j] = result[i][j];
        }
    }
    return;
}
void Inv_MixColumn(vector<vector<byte_def>> &input){
    byte_def result[4][4] = {0};
    byte_def x_0e(0x0e);
    byte_def x_0b(0x0b);
    byte_def x_0d(0x0d);
    byte_def x_09(0x09);
    for(int col = 0; col < 4; col++){
        result[0][col] = mul(x_0e,input[0][col])^mul(x_0b,input[1][col])^mul(x_0d,input[2][col])^mul(x_09,input[3][col]);
        result[1][col] = mul(x_0e,input[1][col])^mul(x_0b,input[2][col])^mul(x_0d,input[3][col])^mul(x_09,input[0][col]);
        result[2][col] = mul(x_0e,input[2][col])^mul(x_0b,input[3][col])^mul(x_0d,input[0][col])^mul(x_09,input[1][col]);
        result[3][col] = mul(x_0e,input[3][col])^mul(x_0b,input[0][col])^mul(x_0d,input[1][col])^mul(x_09,input[2][col]);
    }
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < ROW_SIZE; j++){
            input[i][j] = result[i][j];
        }
    }
}
void AddRoundKey(vector<vector<byte_def>> &input, int round){
    vector<vector<byte_def>> this_round_key = expand_key[round];
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < ROW_SIZE; j++){
            input[i][j] ^= this_round_key[i][j];
        }
    }
}

void SubWord(vector<byte_def> &input){
    for(int i = 0; i < 4; i++){
        input[i] = Sbox[input[i].to_ulong()];
    }
}
void RotWord(vector<byte_def> &input){
    input.push_back(input[0]);
    input.erase(input.begin());
}
//128 bit AES round = 10, so we should create 10 round key
void KeyExpansion(vector<vector<byte_def>> initialKey){
    vector<vector<byte_def>> w_key;
    for(int i = 0; i < ROW_SIZE; i++){
        vector<byte_def> helper;
        helper.push_back(initialKey[0][i]);
        helper.push_back(initialKey[1][i]);
        helper.push_back(initialKey[2][i]);
        helper.push_back(initialKey[3][i]);
        w_key.push_back(helper);
    }
    vector<byte_def> temp;
    for(int i = 4; i <44; i++){
        temp = w_key[i-1];
        if(i % 4 == 0){
            RotWord(temp);
            SubWord(temp);
            temp[0] ^= Rcon[i/4-1];
        }
        for(int k = 0; k < ROW_SIZE; k++){
            temp[k] ^= w_key[i-4][k];
        }
        w_key.push_back(temp);

    }
    int count_key = 0;
    for(auto it = w_key.begin(); it != w_key.end(); it++){
        cout<<"w_key"<<setw(2)<<count_key++<<" = ";
        for(auto iter = (*it).begin(); iter != (*it).end(); iter++)
            cout<<setw(2)<<setfill('0')<<(*iter).to_ulong()<<" ";
        cout<<endl;
    }
    for(int i = 0; i <= ROUND; i++){
        vector<vector<byte_def>> round_temp;
        vector<byte_def> key_temp;
        for(int j = 0; j < 4; j++){
            key_temp.clear();
            key_temp.push_back(w_key[i*4][j]);
            key_temp.push_back(w_key[i*4+1][j]);
            key_temp.push_back(w_key[i*4+2][j]);
            key_temp.push_back(w_key[i*4+3][j]);
            round_temp.push_back(key_temp);
        }
        expand_key.push_back(round_temp);
    }
    cout<<"key after expansion"<<endl;
    int count = 0;
    for(auto it = expand_key.begin(); it != expand_key.end(); it++){
        cout<<"Round key:"<<count++<<endl;
        for(auto it1 = (*it).begin(); it1 != (*it).end(); it1++){
            for(auto it2 = (*it1).begin(); it2 != (*it1).end(); it2++){
                cout<<setw(2)<<setfill('0')<<hex<<(*it2).to_ulong()<<" ";
            }
            cout<<endl;
        }
    } 
    
}
void AES(vector<vector<byte_def>> &current_group, ofstream &encode_log){
    if(debug){
        encode_log<<"AES initial input:"<<endl;
        for(auto it = current_group.begin(); it != current_group.end(); it++){
            for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                encode_log<<hex<<(*iter).to_ulong()<<" ";
            }
            encode_log<<endl;
        }
    }
    //和圈密钥0异或一下
    AddRoundKey(current_group,0);
    if(debug){
        encode_log<<"After xor round Key0:"<<endl;
        for(auto it = current_group.begin(); it != current_group.end(); it++){
            for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                encode_log<<hex<<(*iter).to_ulong()<<" ";
            }
            encode_log<<endl;
        }
    }
    int shift[4] = SHIFT;
    //前面的ROUND-1轮,对于128bit的来说是9轮
    for(int round = 1; round < ROUND; round++){
        if(debug){
            encode_log<<"This is round"<<round<<endl;
        }
        for(int i = 0; i < 4; i++){
            for(int j = 0; j < ROW_SIZE; j++){
                current_group[i][j] = ByteSubsitution(current_group[i][j]);
            }
        }
        if(debug){
            encode_log<<"After Byte subsitution:"<<endl;
            for(auto it = current_group.begin(); it != current_group.end(); it++){
                for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                    encode_log<<hex<<(*iter).to_ulong()<<" ";
                }
                encode_log<<endl;
            }
        }
        for(int i = 0; i < 4; i++){
            ByteRotation(current_group[i],shift[i]);
        }
        if(debug){
            encode_log<<"After ByteRotation:"<<endl;
            for(auto it = current_group.begin(); it != current_group.end(); it++){
                for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                    encode_log<<hex<<(*iter).to_ulong()<<" ";
                }
                encode_log<<endl;
            }
        }
        MixColumn(current_group);
        if(debug){
            encode_log<<"After Mixcolumn:"<<endl;
            for(auto it = current_group.begin(); it != current_group.end(); it++){
                for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                    encode_log<<hex<<(*iter).to_ulong()<<" ";
                }
                encode_log<<endl;
            }
        }
        AddRoundKey(current_group,round);
        if(debug){
            encode_log<<"After add round key "<<round<<":"<<endl;
            for(auto it = current_group.begin(); it != current_group.end(); it++){
                for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                    encode_log<<hex<<(*iter).to_ulong()<<" ";
                }
                encode_log<<endl;
            }
        }
    }
    //最后一轮
    if(debug){
        encode_log<<"This is Round 10"<<endl;
    }
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < ROW_SIZE; j++){
            current_group[i][j] = ByteSubsitution(current_group[i][j]);
        }
    }
    if(debug){
            encode_log<<"After ByteSubsitution:"<<endl;
            for(auto it = current_group.begin(); it != current_group.end(); it++){
                for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                    encode_log<<hex<<(*iter).to_ulong()<<" ";
                }
                encode_log<<endl;
            }
    }
    for(int i = 0; i < 4; i++){
        ByteRotation(current_group[i],shift[i]);
    }
    if(debug){
            encode_log<<"After ByteRotaion:"<<endl;
            for(auto it = current_group.begin(); it != current_group.end(); it++){
                for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                    encode_log<<hex<<(*iter).to_ulong()<<" ";
                }
                encode_log<<endl;
            }
    }
    AddRoundKey(current_group,ROUND);
    if(debug){
            encode_log<<"After add round key 10:"<<endl;
            for(auto it = current_group.begin(); it != current_group.end(); it++){
                for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                    encode_log<<hex<<(*iter).to_ulong()<<" ";
                }
                encode_log<<endl;
            }
    }
}
void Inv_AES(vector<vector<byte_def>> &current_group, ofstream &decode_log){
    if(debug){
        decode_log<<"Inv_AES initial input:"<<endl;
        for(auto it = current_group.begin(); it != current_group.end(); it++){
            for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
            }
            decode_log<<endl;
        }
    }
    //和圈密钥10异或一下,最开始的一轮不用列变换
    AddRoundKey(current_group,10);
    if(debug){
        decode_log<<"After add Round key 10:"<<endl;
        for(auto it = current_group.begin(); it != current_group.end(); it++){
            for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
            }
            decode_log<<endl;
        }
    }
    int inv_shift[4] = INV_SHIFT;
    //逆行变换
    for(int i = 0; i < 4; i++){
        ByteRotation(current_group[i],inv_shift[i]);
    }
    if(debug){
        decode_log<<"After Inv ByteRotation:"<<endl;
        for(auto it = current_group.begin(); it != current_group.end(); it++){
            for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
            }
            decode_log<<endl;
        }
    }
    //逆字节替代
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < ROW_SIZE; j++){
            current_group[i][j] = Inv_ByteSusitution(current_group[i][j]);
        }
    }
    if(debug){
        decode_log<<"After Inv ByteSubsitution:"<<endl;
        for(auto it = current_group.begin(); it != current_group.end(); it++){
            for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
            }
            decode_log<<endl;
        }
    }
    //异或一下K9
    AddRoundKey(current_group,9);
    if(debug){
        decode_log<<"After add Round key 9:"<<endl;
        for(auto it = current_group.begin(); it != current_group.end(); it++){
            for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
            }
            decode_log<<endl;
        }
    }
    //进行剩下的9轮
    for(int round = 8; round >= 0; round--){
        Inv_MixColumn(current_group);
        if(debug){
            decode_log<<"After Inv Mixcolumn:"<<endl;
            for(auto it = current_group.begin(); it != current_group.end(); it++){
                for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                    decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
                }
                decode_log<<endl;
            }
        }
        for(int i = 0; i < 4; i++){
            ByteRotation(current_group[i],inv_shift[i]);
        }
        if(debug){
            decode_log<<"After Inv ByteRotation:"<<endl;
            for(auto it = current_group.begin(); it != current_group.end(); it++){
                for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                    decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
                }
                decode_log<<endl;
            }
        }
        for(int i = 0; i < 4; i++){
            for(int j = 0; j< ROW_SIZE; j++){
                current_group[i][j] = Inv_ByteSusitution(current_group[i][j]);
            }
        }
        if(debug){
            decode_log<<"After Inv Subsitution:"<<endl;
            for(auto it = current_group.begin(); it != current_group.end(); it++){
                for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                    decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
                }
                decode_log<<endl;
            }
        }
        AddRoundKey(current_group,round);
        if(debug){
            decode_log<<"After add Round key "<<round<<":"<<endl;
            for(auto it = current_group.begin(); it != current_group.end(); it++){
                for(auto iter = (*it).begin(); iter != (*it).end(); iter++){
                    decode_log<<setw(2)<<hex<<(*iter).to_ulong()<<" ";
                }
                decode_log<<endl;
            }
        }
    }

}
//将字符串转化为128bit,如长度不够,使用padding补0x0N
vector<vector<byte_def>> Padding(string input){
    vector<vector<byte_def>> result(4);
    if(input.size() > 16){
        cout<<"String exceed size"<<endl;
        return result;
    }
    //calculate n
    int n = 16-input.size();
    for(int i = 0; i < 16; i++){
        if(i < input.size()){
            byte_def temp(int(input[i]+0));
            result[i%4].push_back(temp);
        }
        else{
            byte_def temp(n);
            result[i%4].push_back(temp);
        }
    }
    return result;
}
vector<vector<byte_def>> turnStringIntoBits(string input){
    vector<vector<byte_def>> result(4);
    if(input.size() > 16){
        cout<<"String exceed size"<<endl;
        return result;
    }
    for(int i = 0; i < 16; i++){
        if(i < input.size()){
            byte_def temp(int(input[i]+0));
            result[i%4].push_back(temp);
        }
        else{
            byte_def temp(0);
            result[i%4].push_back(temp);
        }
    }
    return result;
}
void encode(string plaintext,vector<byte_def> &ciphertext){
    int group_num = ceil((double)plaintext.size()/16);
    //IV开始的时候是字符串123
    vector<vector<byte_def>> IV = turnStringIntoBits("123");
    ofstream encode_log("encode_log.txt");
    for(int i = 0; i < group_num; i++){
        //每次取16个字符,最后不足十六个字符substr函数读到字符串末尾自己会终止
        vector<vector<byte_def>> plain_group = Padding(plaintext.substr(i*16,16));
        //明文异或一下IV
        for(int i = 0; i < 4; i++){
            for(int j = 0; j < ROW_SIZE; j++){
                plain_group[i][j] ^= IV[i][j];
            }
        }
        encode_log<<endl<<"Encoding group "<<i<<": "<<plaintext.substr(i*16,16)<<endl;
        //放进AES里面进行运算
        AES(plain_group,encode_log);
        //将这组的输出存进总输出里面,并且更新IV的值
        encode_log<<"group "<<i<<" ciphertext:";
        for(int i = 0; i < 4; i++){
            for(int j = 0; j < ROW_SIZE; j++){
                IV[i][j] = plain_group[i][j];
                ciphertext.push_back(plain_group[j][i]);
                encode_log<<hex<<plain_group[j][i].to_ulong();
            }
        }
        encode_log<<endl<<endl;
    }
    encode_log.close();
    cout<<"encode result:"<<endl;
    for(auto it = ciphertext.begin(); it != ciphertext.end(); it++){
        cout<<setw(2)<<setfill('0')<<hex<<(*it).to_ulong();
    }
    cout<<endl;
}
void decode(vector<byte_def> ciphertext){
    //128bits一组,16个字节一组
    int group_num = ceil(ciphertext.size()/16);
    vector<vector<byte_def>> IV = turnStringIntoBits("123");
    vector<byte_def> plaintext;
    ofstream decode_log("decode.log.txt");
    int index = 0;
    for(int i = 0; i < group_num; i++){
        vector<vector<byte_def>> cipher_group(4);
        //密文丢进去
        for(int j = 0; j < 4; j++){
            cipher_group[0].push_back(ciphertext[index++]);
            cipher_group[1].push_back(ciphertext[index++]);
            cipher_group[2].push_back(ciphertext[index++]);
            cipher_group[3].push_back(ciphertext[index++]);
        }
        decode_log<<endl<<"decoding group "<<i<<endl;
        Inv_AES(cipher_group,decode_log);
        decode_log<<endl;
        //异或IV,得到明文,并更新IV的值
        for(int j = 0; j < 4; j++){
            for(int k = 0; k < 4; k++){
                cipher_group[j][k] ^= IV[j][k];
                IV[j][k] = ciphertext[i*16+k*4+j];
            }
        }
        for(int j = 0; j < 4; j++){
            for(int k = 0; k < 4; k++){
                plaintext.push_back(cipher_group[k][j]);
            }
        }
    }
    decode_log.close();
    cout<<"decode result:"<<endl;
    for(auto it = plaintext.begin(); it != plaintext.end(); it++){
        cout<<(char)(*it).to_ulong();
    }
    cout<<endl;
}
int main(){
    CreateSbox();
    string key = "yaojieqian";//名字作为key
    vector<vector<byte_def>> initialKey = turnStringIntoBits(key);
    KeyExpansion(initialKey);
    string plaintext = "ilearnedhowtocalculatetheamountofpaperneededforaroomwheniwasatschoolyoumultiplythesquarefootageofthewallsbythecubiccontentsofthefloorandceilingcombinedanddoubleityouthenallowhalfthetotalforopeningssuchaswindowsanddoorsthenyouallowtheotherhalfformatchingthepatternthenyoudoublethewholethingagaintogiveamarginoferrorandthenyouorderthepaper";
    vector<byte_def> ciphertext;
    encode(plaintext,ciphertext);
    decode(ciphertext);
    
}