• AES加密算法C++实现


      我从网上下载了一套AES加密算法的C++实现,代码如下:

    (1)aes.h

    #ifndef SRC_UTILS_AES_H
    #define SRC_UTILS_AES_H
    
    class AES  
    {
    public:
        AES(unsigned char* key);
        virtual ~AES();
        unsigned char* Cipher(unsigned char* input);    // 加密,传入的数组大小必须是16字节
        unsigned char* InvCipher(unsigned char* input);  // 解密,传入的数组也必须是16字节
        void* Cipher(void* input, int length=0);      // 可以传入数组,大小必须是16的整数倍,如果不是将会越界操作;如果不传length而默认为0,那么将按照字符串处理,遇''结束
        void* InvCipher(void* input, int length);      // 必须传入数组和大小,必须是16的整数倍
    
    private:
        unsigned char Sbox[256];
        unsigned char InvSbox[256];
        unsigned char w[11][4][4];
    
        void KeyExpansion(unsigned char* key, unsigned char w[][4][4]);
        unsigned char FFmul(unsigned char a, unsigned char b);
    
        void SubBytes(unsigned char state[][4]);
        void ShiftRows(unsigned char state[][4]);
        void MixColumns(unsigned char state[][4]);
        void AddRoundKey(unsigned char state[][4], unsigned char k[][4]);
    
        void InvSubBytes(unsigned char state[][4]);
        void InvShiftRows(unsigned char state[][4]);
        void InvMixColumns(unsigned char state[][4]);
    };
    
    #endif    // SRC_UTILS_AES_H

    (2)aes.cpp

      1 #include "aes.h"
      2 #include "string.h"
      3 
      4 AES::AES(unsigned char* key)
      5 {
      6     unsigned char sBox[] =
      7     { /*  0    1    2    3    4    5    6    7    8    9    a    b    c    d    e    f */ 
      8         0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, /*0*/  
      9         0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, /*1*/
     10         0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, /*2*/ 
     11         0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, /*3*/ 
     12         0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, /*4*/ 
     13         0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, /*5*/
     14         0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, /*6*/  
     15         0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, /*7*/ 
     16         0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, /*8*/ 
     17         0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, /*9*/ 
     18         0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, /*a*/
     19         0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, /*b*/
     20         0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, /*c*/ 
     21         0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, /*d*/
     22         0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, /*e*/ 
     23         0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16  /*f*/
     24     };
     25     unsigned char invsBox[256] = 
     26     { /*  0    1    2    3    4    5    6    7    8    9    a    b    c    d    e    f  */  
     27         0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, /*0*/ 
     28         0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, /*1*/
     29         0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, /*2*/ 
     30         0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, /*3*/ 
     31         0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, /*4*/ 
     32         0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, /*5*/ 
     33         0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, /*6*/ 
     34         0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, /*7*/
     35         0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, /*8*/ 
     36         0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, /*9*/
     37         0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, /*a*/
     38         0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, /*b*/ 
     39         0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, /*c*/ 
     40         0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, /*d*/ 
     41         0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, /*e*/ 
     42         0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d  /*f*/
     43     }; 
     44     memcpy(Sbox, sBox, 256);
     45     memcpy(InvSbox, invsBox, 256);
     46     KeyExpansion(key, w);
     47 }
     48 
     49 AES::~AES()
     50 {
     51 
     52 }
     53 
     54 unsigned char* AES::Cipher(unsigned char* input)
     55 {
     56     unsigned char state[4][4];
     57     int i,r,c;
     58 
     59     for(r=0; r<4; r++)
     60     {
     61         for(c=0; c<4 ;c++)
     62         {
     63             state[r][c] = input[c*4+r];
     64         }
     65     }
     66 
     67     AddRoundKey(state,w[0]);
     68 
     69     for(i=1; i<=10; i++)
     70     {
     71         SubBytes(state);
     72         ShiftRows(state);
     73         if(i!=10)MixColumns(state);
     74         AddRoundKey(state,w[i]);
     75     }
     76 
     77     for(r=0; r<4; r++)
     78     {
     79         for(c=0; c<4 ;c++)
     80         {
     81             input[c*4+r] = state[r][c];
     82         }
     83     }
     84 
     85     return input;
     86 }
     87 
     88 unsigned char* AES::InvCipher(unsigned char* input)
     89 {
     90     unsigned char state[4][4];
     91     int i,r,c;
     92 
     93     for(r=0; r<4; r++)
     94     {
     95         for(c=0; c<4 ;c++)
     96         {
     97             state[r][c] = input[c*4+r];
     98         }
     99     }
    100 
    101     AddRoundKey(state, w[10]);
    102     for(i=9; i>=0; i--)
    103     {
    104         InvShiftRows(state);
    105         InvSubBytes(state);
    106         AddRoundKey(state, w[i]);
    107         if(i)
    108         {
    109             InvMixColumns(state);
    110         }
    111     }
    112     
    113     for(r=0; r<4; r++)
    114     {
    115         for(c=0; c<4 ;c++)
    116         {
    117             input[c*4+r] = state[r][c];
    118         }
    119     }
    120 
    121     return input;
    122 }
    123 
    124 void* AES::Cipher(void* input, int length)
    125 {
    126     unsigned char* in = (unsigned char*) input;
    127     int i;
    128     if(!length)        // 如果是0则当做字符串处理
    129     {
    130         while(*(in+length++));
    131         in = (unsigned char*) input;
    132     }
    133     for(i=0; i<length; i+=16)
    134     {
    135         Cipher(in+i);
    136     }
    137     return input;
    138 }
    139 
    140 void* AES::InvCipher(void* input, int length)
    141 {
    142     unsigned char* in = (unsigned char*) input;
    143     int i;
    144     for(i=0; i<length; i+=16)
    145     {
    146         InvCipher(in+i);
    147     }
    148     return input;
    149 }
    150 
    151 void AES::KeyExpansion(unsigned char* key, unsigned char w[][4][4])
    152 {
    153     int i,j,r,c;
    154     unsigned char rc[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
    155     for(r=0; r<4; r++)
    156     {
    157         for(c=0; c<4; c++)
    158         {
    159             w[0][r][c] = key[r+c*4];
    160         }
    161     }
    162     for(i=1; i<=10; i++)
    163     {
    164         for(j=0; j<4; j++)
    165         {
    166             unsigned char t[4];
    167             for(r=0; r<4; r++)
    168             {
    169                 t[r] = j ? w[i][r][j-1] : w[i-1][r][3];
    170             }
    171             if(j == 0)
    172             {
    173                 unsigned char temp = t[0];
    174                 for(r=0; r<3; r++)
    175                 {
    176                     t[r] = Sbox[t[(r+1)%4]];
    177                 }
    178                 t[3] = Sbox[temp];
    179                 t[0] ^= rc[i-1];
    180             }
    181             for(r=0; r<4; r++)
    182             {
    183                 w[i][r][j] = w[i-1][r][j] ^ t[r];
    184             }
    185         }
    186     }
    187 }
    188 
    189 unsigned char AES::FFmul(unsigned char a, unsigned char b)
    190 {
    191     unsigned char bw[4];
    192     unsigned char res=0;
    193     int i;
    194     bw[0] = b;
    195     for(i=1; i<4; i++)
    196     {
    197         bw[i] = bw[i-1]<<1;
    198         if(bw[i-1]&0x80)
    199         {
    200             bw[i]^=0x1b;
    201         }
    202     }
    203     for(i=0; i<4; i++)
    204     {
    205         if((a>>i)&0x01)
    206         {
    207             res ^= bw[i];
    208         }
    209     }
    210     return res;
    211 }
    212 
    213 void AES::SubBytes(unsigned char state[][4])
    214 {
    215     int r,c;
    216     for(r=0; r<4; r++)
    217     {
    218         for(c=0; c<4; c++)
    219         {
    220             state[r][c] = Sbox[state[r][c]];
    221         }
    222     }
    223 }
    224 
    225 void AES::ShiftRows(unsigned char state[][4])
    226 {
    227     unsigned char t[4];
    228     int r,c;
    229     for(r=1; r<4; r++)
    230     {
    231         for(c=0; c<4; c++)
    232         {
    233             t[c] = state[r][(c+r)%4];
    234         }
    235         for(c=0; c<4; c++)
    236         {
    237             state[r][c] = t[c];
    238         }
    239     }
    240 }
    241 
    242 void AES::MixColumns(unsigned char state[][4])
    243 {
    244     unsigned char t[4];
    245     int r,c;
    246     for(c=0; c< 4; c++)
    247     {
    248         for(r=0; r<4; r++)
    249         {
    250             t[r] = state[r][c];
    251         }
    252         for(r=0; r<4; r++)
    253         {
    254             state[r][c] = FFmul(0x02, t[r])
    255                         ^ FFmul(0x03, t[(r+1)%4])
    256                         ^ FFmul(0x01, t[(r+2)%4])
    257                         ^ FFmul(0x01, t[(r+3)%4]);
    258         }
    259     }
    260 }
    261 
    262 void AES::AddRoundKey(unsigned char state[][4], unsigned char k[][4])
    263 {
    264     int r,c;
    265     for(c=0; c<4; c++)
    266     {
    267         for(r=0; r<4; r++)
    268         {
    269             state[r][c] ^= k[r][c];
    270         }
    271     }
    272 }
    273 
    274 void AES::InvSubBytes(unsigned char state[][4])
    275 {
    276     int r,c;
    277     for(r=0; r<4; r++)
    278     {
    279         for(c=0; c<4; c++)
    280         {
    281             state[r][c] = InvSbox[state[r][c]];
    282         }
    283     }
    284 }
    285 
    286 void AES::InvShiftRows(unsigned char state[][4])
    287 {
    288     unsigned char t[4];
    289     int r,c;
    290     for(r=1; r<4; r++)
    291     {
    292         for(c=0; c<4; c++)
    293         {
    294             t[c] = state[r][(c-r+4)%4];
    295         }
    296         for(c=0; c<4; c++)
    297         {
    298             state[r][c] = t[c];
    299         }
    300     }
    301 }
    302 
    303 void AES::InvMixColumns(unsigned char state[][4])
    304 {
    305     unsigned char t[4];
    306     int r,c;
    307     for(c=0; c< 4; c++)
    308     {
    309         for(r=0; r<4; r++)
    310         {
    311             t[r] = state[r][c];
    312         }
    313         for(r=0; r<4; r++)
    314         {
    315             state[r][c] = FFmul(0x0e, t[r])
    316                         ^ FFmul(0x0b, t[(r+1)%4])
    317                         ^ FFmul(0x0d, t[(r+2)%4])
    318                         ^ FFmul(0x09, t[(r+3)%4]);
    319         }
    320     }
    321 }
    View Code

      上面的加密算法是没问题的,但是接口有两个需要注意的地方,也就是在头文件中备注的地方:

    1、数组的大小必须是16字节或者16的整数倍。

    2、不能直接使用字符串输出,因为加密后的数组内容可能有'',字符串会被截断。

      为了更方便的使用此加密算法,我封装了一个接口类,声明如下:

    (3)aes_encryptor.h

    #ifndef SRC_UTILS_AES_ENCRYPTOR_H
    #define SRC_UTILS_AES_ENCRYPTOR_H
    
    #include <string>
    
    class AES;
    
    class AesEncryptor
    {
    public:
        AesEncryptor(unsigned char* key);
        ~AesEncryptor(void);
    
        std::string EncryptString(std::string strInfor);
        std::string DecryptString(std::string strMessage);
    
        void EncryptTxtFile(const char* inputFileName, const char* outputFileName);
        void DecryptTxtFile(const char* inputFileName, const char* outputFileName);
    
    private:
        void Byte2Hex(const unsigned char* src, int len, char* dest);
        void Hex2Byte(const char* src, int len, unsigned char* dest);
        int  Char2Int(char c);
    
    private:
        AES* m_pEncryptor;
    };
    
    #endif        // SRC_UTILS_AES_ENCRYPTOR_H

     (4)aes_encryptor.cpp

      1 #include "aes.h"
      2 #include "aes_encryptor.h"
      3 #include "log.h"
      4 
      5 #include <fstream>
      6 using namespace std;
      7 
      8 AesEncryptor::AesEncryptor(unsigned char* key)
      9 {
     10     m_pEncryptor = new AES(key);
     11 }
     12 
     13 
     14 AesEncryptor::~AesEncryptor(void)
     15 {
     16     delete m_pEncryptor;
     17 }
     18 
     19 void AesEncryptor::Byte2Hex(const unsigned char* src, int len, char* dest) {
     20     for (int i=0; i<len; ++i) {
     21         sprintf_s(dest + i * 2, 3, "%02X", src[i]);    
     22     }
     23 }
     24 
     25 void AesEncryptor::Hex2Byte(const char* src, int len, unsigned char* dest) {
     26     int length = len / 2;
     27     for (int i=0; i<length; ++i) {
     28         dest[i] = Char2Int(src[i * 2]) * 16 + Char2Int(src[i * 2 + 1]);
     29     }
     30 }
     31 
     32 int AesEncryptor::Char2Int(char c) {
     33     if ('0' <= c && c <= '9') {
     34         return (c - '0');
     35     }
     36     else if ('a' <= c && c<= 'f') {
     37         return (c - 'a' + 10);
     38     }
     39     else if ('A' <= c && c<= 'F') {
     40         return (c - 'A' + 10);
     41     }
     42     return -1;
     43 }
     44 
     45 string AesEncryptor::EncryptString(string strInfor) {
     46     int nLength = strInfor.length();
     47     int spaceLength = 16 - (nLength % 16);
     48     unsigned char* pBuffer = new unsigned char[nLength + spaceLength];
     49     memset(pBuffer, '', nLength + spaceLength);
     50     memcpy_s(pBuffer, nLength + spaceLength, strInfor.c_str(), nLength);
     51     m_pEncryptor->Cipher(pBuffer, nLength + spaceLength);
     52     
     53     // 这里需要把得到的字符数组转换成十六进制字符串 
     54     char* pOut = new char[2 * (nLength + spaceLength)];
     55     memset(pOut, '', 2 * (nLength + spaceLength));
     56     Byte2Hex(pBuffer, nLength + spaceLength, pOut);
     57 
     58     string retValue(pOut);
     59     delete[] pBuffer;
     60     delete[] pOut;
     61     return retValue;
     62 }
     63 
     64 string AesEncryptor::DecryptString(string strMessage) {
     65     int nLength = strMessage.length() / 2;
     66     unsigned char* pBuffer = new unsigned char[nLength];
     67     memset(pBuffer, '', nLength);
     68     Hex2Byte(strMessage.c_str(), strMessage.length(), pBuffer);
     69 
     70     m_pEncryptor->InvCipher(pBuffer, nLength);
     71     string retValue((char*)pBuffer);
     72     delete[] pBuffer;
     73     return retValue;
     74 }
     75 
     76 void AesEncryptor::EncryptTxtFile(const char* inputFileName, const char* outputFileName) {
     77     ifstream ifs;
     78 
     79     // Open file:
     80     ifs.open(inputFileName);
     81     if (!ifs) {
     82         UNILOGW("AesEncryptor::EncryptTxtFile() - Open input file failed!");
     83         return ;
     84     }
     85 
     86     // Read config data:
     87     string strInfor;
     88     string strLine;
     89     while (!ifs.eof()) {
     90         char temp[1024];
     91         memset(temp, '', 1024);
     92         ifs.read(temp, 1000);
     93         strInfor += temp;
     94     }
     95     ifs.close();
     96 
     97     // Encrypt
     98     strLine = EncryptString(strInfor);
     99 
    100     // Writefile 
    101     ofstream ofs;
    102     ofs.open(outputFileName);
    103     if (!ofs) {
    104         UNILOGW("AesEncryptor::EncryptTxtFile() - Open output file failed!");
    105         return ;
    106     }
    107     ofs << strLine;
    108     ofs.close();
    109 }
    110 
    111 void AesEncryptor::DecryptTxtFile(const char* inputFile, const char* outputFile) {
    112     ifstream ifs;
    113 
    114     // Open file:
    115     ifs.open(inputFile);
    116     if (!ifs) {
    117         UNILOGW("AesEncryptor::DecryptTxtFile() - Open input file failed!");
    118         return ;
    119     }
    120 
    121     // Read config data:
    122     string strInfor;
    123     string strLine;
    124     while (!ifs.eof()) {
    125         char temp[1024];
    126         memset(temp, '', 1024);
    127         ifs.read(temp, 1000);
    128         strInfor += temp;
    129     }
    130     ifs.close();
    131 
    132     // Encrypt
    133     strLine = DecryptString(strInfor);
    134 
    135     // Writefile 
    136     ofstream ofs;
    137     ofs.open(outputFile);
    138     if (!ofs) {
    139         UNILOGW("AesEncryptor::DecryptTxtFile() - Open output file failed!");
    140         return ;
    141     }
    142     ofs << strLine;
    143     ofs.close();
    144 }
    View Code

      从代码中可以看到增加了以下特性:

    1、支持对std::string 字符串类型的加密,并返回相应的字符串,这个字符串是将加密后的内容转换成十六进制表示的,所以不存在截断的问题。当然了,解密的时候也需要转换成真正的unsigned char数组;

    2、支持直接对文本文件进行加密,指定输入和输出的文件名即可。

    PS: 多说一句,从网上看别人封装的代码时,先看评论和反应,有的时候网友写个带漏洞的程序坑死人不负责的。

  • 相关阅读:
    时间戳与时间之间的相互转化
    源代码管理之Git命令的使用
    ios最新设置状态栏字体颜色总结
    iOS 代码方式设置按钮标题、图片的偏移
    runloop简单介绍
    iOS中的多线程NSThread/GCD/NSOperation & NSOperationQueue
    AFNetworking的详细解析
    MATLAB相关快捷键以及常用函数
    CentOS 5.8下快速搭建FTP服务器
    php获取跳转后的真实链接
  • 原文地址:https://www.cnblogs.com/kuliuheng/p/5709217.html
Copyright © 2020-2023  润新知