AES加密

目录

AES算法实验

一、实验目的

二、实验内容

三、实验原理

四、实验步骤

4.1 AES加解密流程设计

4.2 test流程设计(AES调用程序)

4.3存储格式设计

4.3.1 S盒与逆S盒

4.3.2 明文设计

4.3.3 密钥设计

4.4 实验过程

4.4.1 S盒测试

4.4.2 单轮加密测试

4.4.3 加密测试

4.4.4 解密测试

4.4.5 test文件测试

4.5 实验难点及解决

4.5.1 字符转16进制

4.5.2 明文及密钥存储格式

附录:AES加密程序代码

1.AES.h

2.Test.h

3.AES.cpp

4.test.cpp

5.main.cpp


AES算法实验

一、实验目的

深刻掌握AES算法的运行原理

编程实现AES算法加解密过程

掌握对称密码工作模式

编程实现支持多种工作模式和填充方式的AES加解密程序

二、实验内容

完成AES加解密程序编写。

三、实验原理

AES(高级加密标准)是一种对称加密算法,广泛用于数据加密和保护。它的原理可以概括为以下几个关键点:

对称加密:AES使用相同的密钥进行加密和解密,这意味着发送方和接收方必须安全地共享该密钥。

分组加密:AES对数据进行分组处理,每个分组为128位(16字节)。较大的数据会被分成多个分组进行加密。

密钥长度:AES支持三种密钥长度:128位、192位和256位,密钥长度越长,安全性越高。

加密过程:AES的加密过程分为多个轮次(rounds),根据密钥长度不同,轮次数为:

10轮(128位密钥)

12轮(192位密钥)

14轮(256位密钥)

每一轮包括以下步骤:

字节替换(SubBytes):使用S-Box替换每个字节。

行移位(ShiftRows):对行进行循环左移。

列混合(MixColumns):对列进行线性变换,增强扩散性(最后一轮不进行此步骤)。

轮密钥加(AddRoundKey):将当前状态与轮密钥进行异或运算

解密过程:解密过程与加密相反,步骤顺序调整,并使用反向操作(反S-Box、行反移位、列反混合、轮密钥加)。

四、实验步骤

4.1 AES加解密流程设计

4.2 test流程设计(AES调用程序)

4.3存储格式设计

4.3.1 S盒与逆S盒

  本次实验中的S盒使用unsigned char数组,非程序生成。

4.3.2 明文设计

本次实验设计中,明文以字符串的形式输入test程序中,在test程序中转换为16进制数存储在[4][4]大小的矩阵中,将16进制状态矩阵以参数形式传送至AES算法中进行加解密运算。

4.3.3 密钥设计

本次实验设计中,密钥以字符串的形式输入test程序中,在test程序中转换为16进制数存储在[4][4]大小的矩阵中,在AES扩展算法后转换为[44][4]大小的矩阵存储,和正常的轮密钥相比,每一个子密钥的行、列其实是相反的,在使用时利用[j][i]的形式调用,以保证正常的加解密。

4.4 实验过程

4.4.1 S盒测试

输入16位16进制数,测试S盒和逆S盒可以正常转换

4.4.2 单轮加密测试

进行单论数据测试,测试课本案例,得到相同结论。

4.4.3 加密测试

进行10轮加密后得到

4.4.4 解密测试

进行10轮解密后得到

4.4.5 test文件测试

4.5 实验难点及解决

4.5.1 字符转16进制

使用include <sstream>库函数,将字符串中的每两个字符转换为一个十六进制数字。

4.5.2 明文及密钥存储格式

由于涉及到异或运算,采用二维数组的存储方式利于计算、移位、代码阅读。

但是扩展密钥存储时,若按照[4]*[44]的方式进行存储,则不方便进行轮运算,若按照[44]*[4]存储,则进行密钥扩展时,按实际的存储方式是按照行进行的,但是在进行轮加密运算时,要注意行列区别

下图是测试案例中轮密钥实际的存储形式:

   

                

  

下图是明文矩阵的存储形式:

  

附录:AES加密程序代码

1.AES.h

#pragma once

#include <iostream>
#include <iomanip>
#include <cstdint>
#include <sstream>
#include"AES.h"

using namespace std;

// 轮密钥加
void AddRoundKey(int round, uint8_t state[4][4], uint8_t roundKey[44][4]);

// S-Box字节替换
void SubBytes(uint8_t state[4][4]);

// 行移位
void ShiftRows(uint8_t state[4][4]);

// 把十六进制字符串转换为矩阵(按列填入)
void hexStringToStateMatrix(const string& input, uint8_t state[4][4]);

//矩阵转为十六进制字符串
string stateMatrixToHexString(const uint8_t state[4][4]);

// GF(2^8) 中的乘法
uint8_t gmul(uint8_t a, uint8_t b);

// 列混淆(MixColumns)
void MixColumns(uint8_t state[4][4]);

//打印矩阵
void printmatrix(uint8_t state[4][4]);

// 密钥扩展函数
void KeyExpansion(uint8_t key[4][4], uint8_t expandedKeys[44][4]);

// AES加密函数
void AES_Encrypt(uint8_t state[4][4], uint8_t expandedKeys[44][4]);

// 逆S-Box字节替换
void InvSubBytes(uint8_t state[4][4]);

// 逆行移位
void InvShiftRows(uint8_t state[4][4]);

// 逆列混淆(InvMixColumns)
void InvMixColumns(uint8_t state[4][4]);

// AES解密函数
void AES_Decrypt(uint8_t state[4][4], uint8_t expandedKeys[44][4]);

void SBoxFill();

2.Test.h

#pragma once

#include"AES.h"
#include"test.h"

//从文件中读出明文
bool readPlaintext(const string& filename, string& plaintext);

//从文件中读出密文
bool readKey(const string& filename, string& key);

//将解密后的字符串写入文件中
bool writeHexString(const string& filename, const string& hexString);

int text();

3.AES.cpp

#include "AES.h"


/*————————————————两个S盒————————————————*/

//定义AES的加密S盒
unsigned char SBox[256] = {
    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
};


//定义AES的解密逆S盒
unsigned char InvSBox[256] = {
    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
};




// 轮密钥加
void AddRoundKey(int round,uint8_t state[4][4], uint8_t roundKey[44][4]) {

    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            state[j][i] ^= roundKey[round * 4 + i][j];
        }
    }
}

// S-Box字节替换
void SubBytes(uint8_t state[4][4]) {
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            state[i][j] = SBox[state[i][j]];
        }
    }
}

// 行移位
void ShiftRows(uint8_t state[4][4]) {
    uint8_t temp;

    // 第二行左移一位
    temp = state[1][0];
    for (int i = 0; i < 3; ++i)
        state[1][i] = state[1][i + 1];
    state[1][3] = temp;

    // 第三行左移两位
    for (int i = 0; i < 2; ++i) {
        temp = state[2][i];
        state[2][i] = state[2][i + 2];
        state[2][i + 2] = temp;
    }

    // 第四行左移三位
    temp = state[3][3];
    for (int i = 3; i > 0; --i)
        state[3][i] = state[3][i - 1];
    state[3][0] = temp;
}

// 把十六进制字符串转换为矩阵(按列填入)
void hexStringToStateMatrix(const string& input, uint8_t state[4][4]) {
    for (int i = 0; i < 16; ++i) {
        // 每次取两个字符,转换为一个字节
        stringstream ss;
        ss << hex << input.substr(2 * i, 2);
        int val;
        ss >> val;
        state[i % 4][i / 4] = static_cast<uint8_t>(val);  // 按列填入
    }
}
//矩阵转为十六进制字符串
string stateMatrixToHexString(const uint8_t state[4][4]) {
    stringstream ss;
    for (int col = 0; col < 4; ++col) {  // 按列读取
        for (int row = 0; row < 4; ++row) {
            ss << hex << setw(2) << setfill('0') << static_cast<int>(state[row][col]);
        }
    }
    return ss.str();
}


// GF(2^8) 中的乘法
uint8_t gmul(uint8_t a, uint8_t b) {
    uint8_t p = 0;
    uint8_t hi_bit_set;
    for (int i = 0; i < 8; ++i) {
        if (b & 1)
            p ^= a;
        hi_bit_set = a & 0x80;
        a <<= 1;
        if (hi_bit_set)
            a ^= 0x1b; // AES 中的不可约多项式
        b >>= 1;
    }
    return p;
}

// 列混淆(MixColumns)
void MixColumns(uint8_t state[4][4]) {
    uint8_t temp_state[4][4];

    for (int c = 0; c < 4; ++c) {
        temp_state[0][c] = gmul(0x02, state[0][c]) ^ gmul(0x03, state[1][c]) ^ state[2][c] ^ state[3][c];
        temp_state[1][c] = state[0][c] ^ gmul(0x02, state[1][c]) ^ gmul(0x03, state[2][c]) ^ state[3][c];
        temp_state[2][c] = state[0][c] ^ state[1][c] ^ gmul(0x02, state[2][c]) ^ gmul(0x03, state[3][c]);
        temp_state[3][c] = gmul(0x03, state[0][c]) ^ state[1][c] ^ state[2][c] ^ gmul(0x02, state[3][c]);
    }

    // 将结果拷贝回原始状态矩阵
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            state[i][j] = temp_state[i][j];
        }
    }
}


//打印矩阵
void printmatrix(uint8_t state[4][4]) {
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            cout << hex << setw(2) << setfill('0') << (int)state[i][j] << " ";
        }
        cout << endl;
    }
}



uint8_t Rcon[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 }; // 轮常数



// 密钥扩展函数
void KeyExpansion(uint8_t key[4][4], uint8_t expandedKeys[44][4]) {
    // 将原始密钥复制到expandedKeys的前四个字中
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            expandedKeys[i][j] = key[j][i];
        }
    }

    // 每一轮扩展
    for (int i = 4; i < 44; ++i) {
        uint8_t temp[4];
        // 从前一个字生成temp
        for (int j = 0; j < 4; ++j) {
            temp[j] = expandedKeys[i - 1][j];
        }

        // 每四轮进行特殊变换
        if (i % 4 == 0) {
            // 字循环
            uint8_t t = temp[0];
            temp[0] = temp[1];
            temp[1] = temp[2];
            temp[2] = temp[3];
            temp[3] = t;

            // S盒替换
            for (int j = 0; j < 4; ++j) {
                temp[j] = SBox[temp[j]];
            }

            // 轮常数异或
            temp[0] ^= Rcon[(i / 4) - 1];
        }

        // 扩展密钥
        for (int j = 0; j < 4; ++j) {
            expandedKeys[i][j] = expandedKeys[i - 4][j] ^ temp[j];
        }
    }
}


// AES加密函数
void AES_Encrypt(uint8_t state[4][4], uint8_t expandedKeys[44][4]) {
    // 初始轮密钥加
    AddRoundKey(0,state, expandedKeys);

    // 进行10轮加密
    for (int round = 1; round <= 10; ++round) {
        // SubBytes
        SubBytes(state);
        

        // ShiftRows
        ShiftRows(state);
        

        // 只有前9轮进行MixColumns
        if (round < 10) {
          
            MixColumns(state);
           
        }

        // 添加轮密钥
        AddRoundKey(round,state, expandedKeys);
    }
}

// 逆S-Box字节替换
void InvSubBytes(uint8_t state[4][4]) {
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            state[i][j] = InvSBox[state[i][j]];
        }
    }
}

// 逆行移位
void InvShiftRows(uint8_t state[4][4]) {
    uint8_t temp;

    // 第四行左移一位
    temp = state[3][0];
    for (int i = 0; i < 3; ++i)
        state[3][i] = state[3][(i +1)%4];
    state[3][3] = temp;

    // 第三行右移两位
    for (int i = 0; i < 2; ++i) {
        temp = state[2][3 - i];
        state[2][3 - i] = state[2][1 - i];
        state[2][1 - i] = temp;
    }

    // 第二行右移三位
    temp = state[1][3];
    for (int i = 3; i > 0; --i)
        state[1][i] = state[1][i - 1];
    state[1][0] = temp;
}

// 逆列混淆(InvMixColumns)
void InvMixColumns(uint8_t state[4][4]) {
    uint8_t temp_state[4][4];

    for (int c = 0; c < 4; ++c) {
        temp_state[0][c] = gmul(0x0E, state[0][c]) ^ gmul(0x0B, state[1][c]) ^ gmul(0x0D, state[2][c]) ^ gmul(0x09, state[3][c]);
        temp_state[1][c] = gmul(0x09, state[0][c]) ^ gmul(0x0E, state[1][c]) ^ gmul(0x0B, state[2][c]) ^ gmul(0x0D, state[3][c]);
        temp_state[2][c] = gmul(0x0D, state[0][c]) ^ gmul(0x09, state[1][c]) ^ gmul(0x0E, state[2][c]) ^ gmul(0x0B, state[3][c]);
        temp_state[3][c] = gmul(0x0B, state[0][c]) ^ gmul(0x0D, state[1][c]) ^ gmul(0x09, state[2][c]) ^ gmul(0x0E, state[3][c]);
    }

    // 将结果拷贝回原始状态矩阵
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            state[i][j] = temp_state[i][j];
        }
    }
}

// AES解密函数
void AES_Decrypt(uint8_t state[4][4], uint8_t expandedKeys[44][4]) {    
    // 进行10轮解密
    for (int round = 10; round >= 1; --round) {
        // 逆行密钥
        AddRoundKey(round, state, expandedKeys);

        // 逆列混淆
        if (round <=9) {
            
            InvMixColumns(state);
           
        }
       
        InvShiftRows(state);
        
        // 逆S-Box替代
        InvSubBytes(state);
       
    }

    
    AddRoundKey(0, state, expandedKeys);
   
}

4.test.cpp

#include"AES.h"
#include <fstream>
#include <string>

//从文件中读出明文
bool readPlaintext(const string& filename, string& plaintext) {
    ifstream inputFile(filename);
    if (inputFile.is_open()) {
        getline(inputFile, plaintext);
        inputFile.close();
        return true;
    }
    return false;
}


//从文件中读出密文
bool readKey(const string& filename, string& key) {
    ifstream inputFile(filename);
    if (inputFile.is_open()) {
        // 跳过第一行(明文)
        string dummy;
        getline(inputFile, dummy);
        getline(inputFile, key);
        inputFile.close();
        return true;
    }
    return false;
}

//将解密后的字符串写入文件中
bool writeHexString(const string& filename, const string& hexString) {
    ofstream outputFile(filename, ios::app); // 以追加模式打开文件
    if (outputFile.is_open()) {
      
        outputFile << hexString << endl;
        outputFile.close();
        return true;
    }
    return false;
}

//测试
int text() {
    string filename;
    string plaintext;
    string key;

    cout << "请输入文件名: ";
    cin >> filename;

    if (readPlaintext(filename, plaintext) && readKey(filename, key)) {
        // 检查明文和密钥长度
        if (plaintext.length() == 32 && key.length() == 32) {
            cout << "明文: " << plaintext << endl;
            cout << "密钥: " << key << endl;
        }
        else {
            cout << "文件内容格式不正确,明文和密钥应为16字节(32个十六进制字符)。" << endl;
        }
    }
    else {
        cout << "无法打开文件或读取内容,请检查文件名是否正确。" << endl;
    }

    // 定义AES状态矩阵(4x4字节)
    uint8_t state[4][4];
    uint8_t roundKey[4][4];
    uint8_t expandedKeys[44][4];

    // 将输入转换为状态矩阵
    hexStringToStateMatrix(plaintext, state);
    hexStringToStateMatrix(key, roundKey);

    KeyExpansion(roundKey, expandedKeys);

    AES_Encrypt(state, expandedKeys);

    AES_Decrypt(state, expandedKeys);

    string hexString = stateMatrixToHexString(state);
    cout << "Hex String: " << hexString << endl;

    if (hexString.length() == 32) {
        if (writeHexString(filename, hexString)) {
            cout << "已成功将hexString写入文件!" << endl;
        }
        else {
            cout << "写入文件失败。" << endl;
        }
    }
    else {
        cout << "输入的hexString应为16字节(32个十六进制字符)。" << endl;
    }

    return 0;
}

5.main.cpp

#include"test.h"

int main() {
    text();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值