一、AES介绍

AES,高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图:
下面简单介绍下各个部分的作用与意义:

明文P

没有经过加密的数据。

密钥K

用来加密明文的密码,在对称加密算法中,加密与解密的密钥是相同的。密钥为接收方与发送方协商产生,但不可以直接在网络上传输,否则会导致密钥泄漏,通常是通过非对称加密算法加密密钥,然后再通过网络传输给对方,或者直接面对面商量密钥。密钥是绝对不可以泄漏的,否则会被攻击者还原密文,窃取机密数据。

AES加密函数

设AES加密函数为E,则 C = E(K, P),其中P为明文,K为密钥,C为密文。也就是说,把明文P和密钥K作为加密函数的参数输入,则加密函数E会输出密文C。

密文C

经加密函数处理后的数据

AES解密函数

设AES解密函数为D,则 P = D(K, C),其中C为密文,K为密钥,P为明文。也就是说,把密文C和密钥K作为解密函数的参数输入,则解密函数会输出明文P。

在这里简单介绍下对称加密算法与非对称加密算法的区别。

对称加密算法

加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦。

非对称加密算法

加密和解密用的密钥是不同的,这种加密方式是用数学上的难解问题构造的,通常加密解密的速度比较慢,适合偶尔发送数据的场合。优点是密钥传输方便。常见的非对称加密算法为RSA、ECC和EIGamal。

实际中,一般是通过RSA加密AES的密钥,传输到接收方,接收方解密得到AES密钥,然后发送方和接收方用AES密钥来通信。

二、AES结构

AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同,如下表所示:
|AES 密钥长度(32位比特字) |分组长度(32位比特字) |加密轮数
AES-128 4 4 10
AES-192 6 4 12
AES-256 8 4 14

这里实现的是AES-128,也就是密钥的长度为128位,加密轮数为10轮。
上面说到,AES的加密公式为C = E(K,P),在加密函数E中,会执行一个轮函数,并且执行10次这个轮函数,这个轮函数的前9次执行的操作是一样的,只有第10次有所不同。也就是说,一个明文分组会被加密10轮。AES的核心就是实现一轮中的所有操作。

AES的处理单位是字节,128位的输入明文分组P和输入密钥K都被分成16个字节,分别记为P = P0 P1 … P15 和 K = K0 K1 … K15。如,明文分组为P = abcdefghijklmnop,其中的字符a对应P0,p对应P15。一般地,明文分组用字节为单位的正方形矩阵描述,称为状态矩阵。在算法的每一轮中,状态矩阵的内容不断发生变化,最后的结果作为密文输出。该矩阵中字节的排列顺序为从上到下、从左至右依次排列

解密过程仍为10轮,每一轮的操作是加密操作的逆操作。由于AES的4个轮操作都是可逆的,因此,解密操作的一轮就是顺序执行逆行移位、逆字节代换、轮密钥加和逆列混合。同加密操作类似,最后一轮不执行逆列混合,在第1轮解密之前,要执行1次密钥加操作。

AES的S和逆S盒

AES的字节代换其实就是一个简单的查表操作。AES定义了一个S盒和一个逆S盒,S盒如下:

行/列  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
0   0x63    0x7c    0x77    0x7b    0xf2    0x6b    0x6f    0xc5    0x30    0x01    0x67    0x2b    0xfe    0xd7    0xab    0x76
1   0xca    0x82    0xc9    0x7d    0xfa    0x59    0x47    0xf0    0xad    0xd4    0xa2    0xaf    0x9c    0xa4    0x72    0xc0
2   0xb7    0xfd    0x93    0x26    0x36    0x3f    0xf7    0xcc    0x34    0xa5    0xe5    0xf1    0x71    0xd8    0x31    0x15
3   0x04    0xc7    0x23    0xc3    0x18    0x96    0x05    0x9a    0x07    0x12    0x80    0xe2    0xeb    0x27    0xb2    0x75
4   0x09    0x83    0x2c    0x1a    0x1b    0x6e    0x5a    0xa0    0x52    0x3b    0xd6    0xb3    0x29    0xe3    0x2f    0x84
5   0x53    0xd1    0x00    0xed    0x20    0xfc    0xb1    0x5b    0x6a    0xcb    0xbe    0x39    0x4a    0x4c    0x58    0xcf
6   0xd0    0xef    0xaa    0xfb    0x43    0x4d    0x33    0x85    0x45    0xf9    0x02    0x7f    0x50    0x3c    0x9f    0xa8
7   0x51    0xa3    0x40    0x8f    0x92    0x9d    0x38    0xf5    0xbc    0xb6    0xda    0x21    0x10    0xff    0xf3    0xd2
8   0xcd    0x0c    0x13    0xec    0x5f    0x97    0x44    0x17    0xc4    0xa7    0x7e    0x3d    0x64    0x5d    0x19    0x73
9   0x60    0x81    0x4f    0xdc    0x22    0x2a    0x90    0x88    0x46    0xee    0xb8    0x14    0xde    0x5e    0x0b    0xdb
A   0xe0    0x32    0x3a    0x0a    0x49    0x06    0x24    0x5c    0xc2    0xd3    0xac    0x62    0x91    0x95    0xe4    0x79
B   0xe7    0xc8    0x37    0x6d    0x8d    0xd5    0x4e    0xa9    0x6c    0x56    0xf4    0xea    0x65    0x7a    0xae    0x08
C   0xba    0x78    0x25    0x2e    0x1c    0xa6    0xb4    0xc6    0xe8    0xdd    0x74    0x1f    0x4b    0xbd    0x8b    0x8a
D   0x70    0x3e    0xb5    0x66    0x48    0x03    0xf6    0x0e    0x61    0x35    0x57    0xb9    0x86    0xc1    0x1d    0x9e
E   0xe1    0xf8    0x98    0x11    0x69    0xd9    0x8e    0x94    0x9b    0x1e    0x87    0xe9    0xce    0x55    0x28    0xdf
F   0x8c    0xa1    0x89    0x0d    0xbf    0xe6    0x42    0x68    0x41    0x99    0x2d    0x0f    0xb0    0x54    0xbb    0x16

状态矩阵中的元素按照下面的方式映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。

逆字节代换也就是查逆S盒来变换,逆S盒如下:

行/列  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
0   0x52    0x09    0x6a    0xd5    0x30    0x36    0xa5    0x38    0xbf    0x40    0xa3    0x9e    0x81    0xf3    0xd7    0xfb
1   0x7c    0xe3    0x39    0x82    0x9b    0x2f    0xff    0x87    0x34    0x8e    0x43    0x44    0xc4    0xde    0xe9    0xcb
2   0x54    0x7b    0x94    0x32    0xa6    0xc2    0x23    0x3d    0xee    0x4c    0x95    0x0b    0x42    0xfa    0xc3    0x4e
3   0x08    0x2e    0xa1    0x66    0x28    0xd9    0x24    0xb2    0x76    0x5b    0xa2    0x49    0x6d    0x8b    0xd1    0x25
4   0x72    0xf8    0xf6    0x64    0x86    0x68    0x98    0x16    0xd4    0xa4    0x5c    0xcc    0x5d    0x65    0xb6    0x92
5   0x6c    0x70    0x48    0x50    0xfd    0xed    0xb9    0xda    0x5e    0x15    0x46    0x57    0xa7    0x8d    0x9d    0x84
6   0x90    0xd8    0xab    0x00    0x8c    0xbc    0xd3    0x0a    0xf7    0xe4    0x58    0x05    0xb8    0xb3    0x45    0x06
7   0xd0    0x2c    0x1e    0x8f    0xca    0x3f    0x0f    0x02    0xc1    0xaf    0xbd    0x03    0x01    0x13    0x8a    0x6b
8   0x3a    0x91    0x11    0x41    0x4f    0x67    0xdc    0xea    0x97    0xf2    0xcf    0xce    0xf0    0xb4    0xe6    0x73
9   0x96    0xac    0x74    0x22    0xe7    0xad    0x35    0x85    0xe2    0xf9    0x37    0xe8    0x1c    0x75    0xdf    0x6e
A   0x47    0xf1    0x1a    0x71    0x1d    0x29    0xc5    0x89    0x6f    0xb7    0x62    0x0e    0xaa    0x18    0xbe    0x1b
B   0xfc    0x56    0x3e    0x4b    0xc6    0xd2    0x79    0x20    0x9a    0xdb    0xc0    0xfe    0x78    0xcd    0x5a    0xf4
C   0x1f    0xdd    0xa8    0x33    0x88    0x07    0xc7    0x31    0xb1    0x12    0x10    0x59    0x27    0x80    0xec    0x5f
D   0x60    0x51    0x7f    0xa9    0x19    0xb5    0x4a    0x0d    0x2d    0xe5    0x7a    0x9f    0x93    0xc9    0x9c    0xef
E   0xa0    0xe0    0x3b    0x4d    0xae    0x2a    0xf5    0xb0    0xc8    0xeb    0xbb    0x3c    0x83    0x53    0x99    0x61
F   0x17    0x2b    0x04    0x7e    0xba    0x77    0xd6    0x26    0xe1    0x69    0x14    0x63    0x55    0x21    0x0c    0x7d

三、实现

说那么多没用,只需要了解对应原理就行,最终还是落在代码的实现上,为了可复用性、模块化和组件化,我依然封装为dll库,提供了如下三个接口:

  1. 秘钥初始化接口
    因为AES是对称加密,加解密用的同一个密码,这里我提供了一个秘钥初始化接口,初始化后加密和解密则使用该秘钥进行加解密。
// ------------------------------------------------------------------------
// Function:
//      Initial Encode or Decoder private key
// Remark:
//      This interface must be invoked before Encode_Data or Decoder_Data
// Parameter:
//      pPrivateKey[in]     :  private key
//      nKeyByteLen[in]     :  private key len
// Return:
//      return 0 if initial success else return -1
// ------------------------------------------------------------------------
AESENCRYPT_API int AES_InitlizeKey(char* pPrivateKey, AESKey nKeyByteLen);

该接口提供了两个参数,指定秘钥信息以及秘钥长度。

  1. 数据加密接口
// ------------------------------------------------------------------------
// Function:
//      Encode source data
// Remark:
//      AES_InitlizeKey must be invoked before invoke AES_Encode_Data
// Parameter:
//      pSrcData[in]        :  not encrypted source data
//      pDestBuf[in]        :  buffer that stored encrypted data
//      nSrcDataLenOrBufLen[in-out] :
//                             input source data len or the result len,
//                             AES algorithmic does not change the len
//                             of input data len,so the input length equal
//                             result length
// Return:
//      return 0 if initial success else return -1
// ------------------------------------------------------------------------
AESENCRYPT_API long AES_Encode_Data(char* pSrcData, char* pDestBuf, unsigned long  nSrcDataLenOrBufLen);

该接口提供了三个参数,需要加密的文本数据,加密后存放的数据缓存以及缓存长度。

  1. 解密数据接口
// ------------------------------------------------------------------------
// Function:
//      Decode source data
// Remark:
//      AES_InitlizeKey must be invoked before invoke AES_Decode_Data
// Parameter:
//      pSrcEncryptData[in]     :  encrypted source data
//      pDestBuf[in]            :  buffer that stored decoded data
//      nSrcEncryptDataLenOrBufLen[in-out]  :
//                             input encrypted data len or the result len,
//                             AES algorithmic does not change the len
//                             of input data len,so the input length equal
//                             result length
// Return:
//      return 0 if initial success else return -1
// ------------------------------------------------------------------------
AESENCRYPT_API long AES_Decode_Data(char* pSrcEncryptData, char* pDestBuf, unsigned long  nSrcEncryptDataLenOrBufLen);

该接口提供数据解密,第一个参数为需要解密的数据,第二个为解密之后的数据缓存以及数据缓存长度。

加密核心实现

AES是分段多轮加密过程,其核心实现代码如下:

void Cipher(unsigned char* input, unsigned char* output)
{int i = 0;memset(&State[0][0],0,16);// 明文[128bit=16字节=4*4状态举证]状态数据初始化for(i=0;i<4*g_Nb;i++)                             {State[i%4][i/4]=input[i];                    }// 轮密钥加[初始轮1加上Nr轮=Nr+1轮=Nr+1轮秘钥数组]AddRoundKey(0);                                  // 进行Nr-1轮加密,最后一轮不需要列混淆for (int round = 1; round <= g_Nr; round++)  {SubBytes();                                 //字节代换ShiftRows();                              //行移位if(round != g_Nr)MixColumns();                            //列混淆AddRoundKey(round);                            //轮密钥加}  // 输出加密后的状态数据[加密前明文与加密后明文长度未变化]// 因为它是针对状态数据进行各项复杂操作的for (i = 0; i < (4 * g_Nb); i++){output[i] =  State[i % 4][ i / 4];}}

解密核心实现

解密其实就是一个逆向过程,实现核心代码如下:

void InvCipher(unsigned char* input,unsigned char* output)
{memset(&State[0][0],0,16);for (int i = 0; i < (4 * g_Nb); i++){State[i % 4][ i / 4] = input[i];}AddRoundKey(g_Nr);for (int round = g_Nr-1; round >= 1; round--)  // main round loop{InvShiftRows();InvSubBytes();AddRoundKey(round);InvMixColumns();}  // end main round loop for InvCipherInvShiftRows();InvSubBytes();AddRoundKey(0);// output = statefor (int i = 0; i < (4 * g_Nb); i++){output[i] =  State[i % 4][ i / 4];}
}

相关函数实现

// 轮密钥加
void AddRoundKey(int round)
{// 注: 秘钥块大小为Nk行一共Nr+1轮秘钥Nk为4-6-8大于等于明文矩阵行4//     故而多出秘钥块后面[所有行最后多出的不是每个秘钥块多出的]不参与//     秘钥加运行,Nk的增加也就是秘钥长度的增加只是起了增加轮Nr的作用//     所以每轮的作用行只有4行//                              b0 b4 b8 b12      k0 k1 k2 k3 //                            b0 b4 b8 b12  ^   k4 k5 k6 k7//                             b0 b4 b8 b12      k8 k9 k10k11//                            b0 b4 b8 b12      k12k13k14k15    int i,j;  //i行 j列           //因为密钥w是一列一列排列的,即 k0 k4 k8 k12for(j=0;j<4;j++)           //                              k1 k5 k9 k13{                           //                              k2 k6 k10k14for(i=0;i<4;i++)          //                              k3 k7 k11k15{                       // 所以i行j列的下标是4*((round*4)+j)+i即16*round+4*j+iState[i][j]=(unsigned char)((int)State[i][j]^(int)w[4*((round*4)+j)+i]);  }}
}// 字节代换函数
void SubBytes()
{int i,j;for(j=0;j<4;j++){for(i=0;i<4;i++){State[i][j]=AesSbox[State[i][j]];//因为 16*(State[i][j]>>4)+State[i][j]&0x0f=State[i][j]}}
}// 逆字节代换函数
void InvSubBytes()
{int i,j;for(j=0;j<4;j++){for(i=0;i<4;i++){State[i][j]=AesiSbox[State[i][j]]; //因为 16*(State[i][j]>>4)+State[i][j]&0x0f=State[i][j]}}
}// 行移位
void ShiftRows()
{unsigned char temp[4*4];                                        //Page105int i,j;for(j=0;j<4;j++){for(i=0;i<4;i++){temp[4*i+j]=State[i][j];}}for(i=1;i<4;i++){for(j=0;j<4;j++){if(i==1)State[i][j]=temp[4*i+(j+1)%4];                   //第一行左移1位else if(i==2)State[i][j]=temp[4*i+(j+2)%4];               //第二行左移2位else if(i==3)State[i][j]=temp[4*i+(j+3)%4];               //第三行左移3位}}}// 逆行移位
void InvShiftRows()
{unsigned char temp[4*4];int i,j;for(j=0;j<4;j++){for(i=0;i<4;i++){temp[4*i+j]=State[i][j];}}for(i=1;i<4;i++){for(j=0;j<4;j++){//if(i==1)State[i][j]=temp[4*i+(j-1)%4];    在此犯了一个错误 -1%4=-1 而不是3,所以采用了下面再加一个4的做法if(i==1)State[i][j]=temp[4*i+(j+3)%4];           //第一行右移1位 j-1+4=j+3else if(i==2)State[i][j]=temp[4*i+(j+2)%4];      //第二行右移2位 j-2+4=j+2else if(i==3)State[i][j]=temp[4*i+(j+1)%4];      //第三行右移3位 j-3+4=j+2}}}

四、测试

一下提供AES测试代码:

int _tmain(int argc, _TCHAR* argv[])
{// 32byte秘钥(256bit)char* pKey = "12345678123456781234567812345678";AES_InitlizeKey(pKey,AESKey_32);// 需要加密的数据char* pSrc = "dw123456";int nLen = strlen(pSrc);// 加密数据char szBuf[1024] = {0};int nOutLen = AES_Encode_Data(pSrc,szBuf,nLen);cout << "Encrypt source:" << pSrc << endl;cout << "Encrypt Result:" << szBuf << endl;// 将秘钥base分装--传输string strBase64 = Base64Helper::encode((const BYTE*)szBuf, nOutLen);int x = strBase64.length();// 解密秘闻char szUncrypt[1024] = {0};int nUnLen = strlen(szBuf);nOutLen = AES_Decode_Data(szBuf,szUncrypt,nUnLen);cout << "UnEncrypt Result:" << szUncrypt << endl;system("pause");
}

加密和解密测试如下:

可以看到明文dw123456经过AES加密之后变成了密文,然后又被解密为dw123456

五、文件加解密

加密测试

通过以上封装之后,我们就可以实现对文件的加密和解密了,这里我封装了一个demon,需要加密的原文如下(问题列表):

我们将使用如下demon进行加密,密码为24字节(192bit)-123456781234567812345678:

加密完成后生成文件“问题_Encrypt.txt”,密文如下:

解密测试

通过加密完成之后,文件是基本无法阅读的,所以我们需要用我们的密码解密,我们重新选择输入文件为加密后的密文文件,再次解密:

解密之后生成文件“问题_Encrypt_Dcrypt.txt”,文件内容如下:

通过文件内容,我们可以看到密文确实被解密了,核心加密代码如下:

BOOL CFileEncoderDlg::Encrypt(CString strInputFile, CString strKey,CString strDirectory)
{AESKey eKeyType = AESKey_16;if(24 == strKey.GetLength()){eKeyType = AESKey_24;} else if (32 == strKey.GetLength()){eKeyType = AESKey_32;}AES_InitlizeKey((LPTSTR)(LPCTSTR)strKey, eKeyType);TCHAR szTitle[MAX_PATH] = {_T("")};CFileUtil::GetFileTitleEx(strInputFile, szTitle, MAX_PATH);CString strFileName(szTitle);TCHAR szExt[MAX_PATH] = {_T("")};CFileUtil::GetFileExtName(strInputFile, szExt, MAX_PATH);strFileName += _T("_Encrypt.");strFileName += szExt;CString strOutputPath = strDirectory + _T("/");strOutputPath += strFileName;FILE* pFile = fopen((LPTSTR)(LPCTSTR)strInputFile, "rb");if(NULL == pFile){return FALSE;}FILE* pOutputFile = fopen((LPTSTR)(LPCTSTR)strOutputPath, "wb");if(NULL == pOutputFile){fclose(pFile);return FALSE;}while (0 == feof(pFile)){char szBuffer[1024] = {0};int nLen = fread(szBuffer, 1, 1024, pFile);if (nLen > 0){char szEncrypt[1024+16+16] = {0};   // 可能多出16字节加密长度int nEncryptLen = AES_Encode_Data(szBuffer, szEncrypt, nLen);if (nEncryptLen > 0){fwrite(szEncrypt, 1, nEncryptLen, pOutputFile);}}}fclose(pFile);fclose(pOutputFile);return TRUE;
}

核心解码代码如下:

BOOL CFileEncoderDlg::Decrypt(CString strInputFile, CString strKey, CString strDirectory)
{AESKey eKeyType = AESKey_16;if(24 == strKey.GetLength()){eKeyType = AESKey_24;} else if (32 == strKey.GetLength()){eKeyType = AESKey_32;}AES_InitlizeKey((LPTSTR)(LPCTSTR)strKey, eKeyType);TCHAR szTitle[MAX_PATH] = {_T("")};CFileUtil::GetFileTitleEx(strInputFile, szTitle, MAX_PATH);CString strFileName(szTitle);TCHAR szExt[MAX_PATH] = {_T("")};CFileUtil::GetFileExtName(strInputFile, szExt, MAX_PATH);strFileName += _T("_Dcrypt.");strFileName += szExt;CString strOutputPath = strDirectory + _T("/");strOutputPath += strFileName;FILE* pFile = fopen((LPTSTR)(LPCTSTR)strInputFile, "rb");if(NULL == pFile){return FALSE;}FILE* pOutputFile = fopen((LPTSTR)(LPCTSTR)strOutputPath, "wb");if(NULL == pOutputFile){fclose(pFile);return FALSE;}while (0 == feof(pFile)){char szBuffer[1024+16] = {0};int nLen = fread(szBuffer, 1, 1024+16, pFile);if (nLen > 0){char szDcrypt[2048] = {0};int nDcryptLen = AES_Decode_Data(szBuffer, szDcrypt, nLen);if (nDcryptLen > 0){fwrite(szDcrypt, 1, nDcryptLen, pOutputFile);}}}fclose(pFile);fclose(pOutputFile);return TRUE;
}

源码获取、合作、技术交流请获取如下联系方式:
QQ交流群:961179337

微信账号:lixiang6153
公众号:IT技术快餐
电子邮箱:lixx2048@163.com

AES加解密之C++实现相关推荐

  1. C语言实现AES加解密

    C语言实现AES加解密 AES算法 具体代码 AES算法 (AES)RIJNDAEL算法是一个数据块长度盒密钥长度都可变的分组加密算法,其数据块长度和密钥长度都可独立地选定为大于等于128位且小于等于 ...

  2. Java code lib aes 加解密

    Java aes 加解密 /*** Created by LvJianwei on 2018/2/8.*/import javax.crypto.Cipher; import javax.crypto ...

  3. 数据採集器服务——Socket(今天才发现AES加解密代码跟贴的时候不一样,貌似乱码,不知什么情况)...

    近期刚做的一个项目.关于 Socket TCP 通信. 需求方提供了一个 ARM 机器,及数据採集器,须要我做一个服务端与数据採集器进行交互. 目的: 数据採集器:定时将读取到的数据发送到服务端. 服 ...

  4. 前端 crypto-js aes 加解密

    背景 前段时间公司做项目,该项目涉及到的敏感数据比较多,经过的一波讨论之后,决定前后端进行接口加密处理,采用的是 AES + BASE64 算法加密~ 网上关于 AES 对称加密的算法介绍看上一篇! ...

  5. 记一次Java AES 加解密 对应C# AES加解密 的一波三折

    最近在跟三方对接 对方采用AES加解密 作为一个资深neter Ctrl CV 是我最大的优点 所以我义正言辞的问他们要了demo java demo代码: public class EncryptD ...

  6. C语言实现AES加解密算法

    C语言实现AES加解密算法 AES加解密 AES加解密 #include <stdio.h> #include <stdint.h> #include <memory.h ...

  7. openssl c++实现bouncycastle中AES加解密

    0x01 为什么要用bouncycastle 先说说JCE(Java Cryptography Extension)是一组包,它们提供用于加密.密钥生成和协商以及 Message Authentica ...

  8. aes加密php源码,AES加解密类源码 · ThinkPHP5高阶实战教程 --诠释为API开发而生 · 看云...

    # AES加解密类源码 > 根据网络整理 ~~~ /** * Created by PhpStorm. * Power by Mikkle * QQ:776329498 * Date: 2017 ...

  9. Golang AES 加解密

    文章目录 AES 简介 AES 加解密实现 小结 参考文献 AES 简介 利用 Go 提供的 AES 加解密与 Base64 编解码包,我们可以轻松实现 AES 加解密.实现之前,首先了解一下 AES ...

  10. aes js 加盐值 解密_cryptoJS AES 加解密简单使用

    简单记录一下,前端利用 cryptoJS 如何加解密的.主要是关于 AES 加解密. 需求描述:需要对 url 中的参数进行 AES 解密,然后再把该参数进行 MD5 加密通过接口传递. AES AE ...

最新文章

  1. InfBox V7.0 企业绩效助手客户端使用简介
  2. 网口扫盲二:Mac与Phy组成原理的简单分析
  3. JavaFX FileChooser文件选择器,缓存上一次打开的目录
  4. golang sdk后端怎么用_Python比Golang慢多少?实际上两者差异并不大
  5. Falcon 快速开始
  6. C语言内存的动态分配
  7. [转] Vb中FSO 对象的介绍
  8. js和jquery获取父级元素、子级元素、兄弟元素的方法{转}
  9. 树莓派 口罩识别 python_RaspberryPi上实现佩戴口罩识别——2020电赛F题小记
  10. java中this代表什么
  11. EXCEL TIPS From Webs
  12. 大学英语六级翻译分类高频词汇
  13. 腾讯云与本地主机socket通信网络问题
  14. 配置java win10_win10 Java14安装及配置
  15. 2019icpc徐州站 H题 Yuuki and a problem(树套树(树状数组套主席树))
  16. 探讨!自媒体的推荐机制提高百家号阅读收益方法!
  17. 安卓仿手机网易新闻app项目开发系列之(二)轮播图显示和RecyclerView适配器编写
  18. 纪念第二块Kaggle金牌
  19. 上海交大牵手淘宝成立媒体计算实验室:推动视频超分等关键技术发展
  20. 浅谈蓝湖使用ps插件快速构建代码

热门文章

  1. hdu4339 Query (字符串公共长度,树状数组+二分)
  2. Outlook开机自启+关闭时最小化
  3. WinSCP下载,安装
  4. sql中按姓氏的拼音排序查询
  5. 企业招采系统实现方案(SRM系统)
  6. 都说互联网不相信眼泪,但洋哥偏偏不信邪
  7. 解决Steam火炬之光2起动器在DeepinV20中显示空白透明的问题
  8. Loj 6053(EES筛法)
  9. 【第7节】零基础新手的Python入门实战宝典(五) —— 最基础的表达(数据类型 · 下)
  10. 合宙Air724UG二次开发(1):搭建开发环境