OPENSSL库的使用-AES篇

时间:2021-11-10 03:29:41

原文地址:http://blog.csdn.net/duanxingheng/article/details/11730617

一、AES算法简介

1、AES算法介绍

        密码学中的高级加密标准(Advanced Encryption Standard,AES),又称 Rijndael加密法,是美国联邦*采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。
        如下图所示,AES算法的数据分组长度为128比特、密钥长度为128/192/256比特。

 

OPENSSL库的使用-AES篇

2、AES工作模式介绍    

      1)、ECB模式简介

OPENSSL库的使用-AES篇

 

      2)、CBC模式简介

                下图中,IV一般为16字节全0,数据块长度为16字节的整数倍,则在此数据块后附加一个8字节长的数据块,

         附加的数据块为:16进制的“80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00”  

 

 OPENSSL库的使用-AES篇

 

二、AES算法ECB模式

1、使用函数AES_set_encrypt_key设置加密密钥。

函数原型:

int AES_set_encrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key);

函数作用:

设定加密用的Key;

参数说明:

userKey: 密钥数值;

bits:密钥长度,以bit为单位,如果密钥数字是16个字节,则此参数值应为128;

key: AES_KEY对象指针;

返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128,192,256;

 

2、使用函数AES_set_decrypt_key设置解密密钥。

函数原型:

int AES_set_decrypt_key(const unsigned char *userKey, const int bits,  AES_KEY *key);

函数作用:

设定解密用的Key;

参数说明:

userKey: 密钥数值;

bits:密钥长度,以bit为单位,如果密钥数字是16个字节,则此参数值应为128;

key: AES_KEY对象指针;

返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128,192,256;

 

3、使用函数AES_ecb_encrypt对数据进行加解密

函数原型:

void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,    const AES_KEY *key, const int enc);

函数说明:

AES加密/解密单个数据块(16个字节),ECB模式

参数说明:

in: 需要加密/解密的数据;

out: 计算后输出的数据;

key:密钥

enc: AES_ENCRYPT 代表加密, AES_DECRYPT代表解密;

 

三、AES算法CBC模式

1、使用函数AES_set_encrypt_key设置加密密钥。

函数原型:

int AES_set_encrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key);

函数作用:

设定加密用的Key;

参数说明:

userKey: 密钥数值;

bits:密钥长度,以bit为单位,如果密钥数字是16个字节,则此参数值应为128;

key: AES_KEY对象指针;

返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128,192,256;

 

2、使用函数AES_set_decrypt_key设置解密密钥。

函数原型:

int AES_set_decrypt_key(const unsigned char *userKey, const int bits,  AES_KEY *key);

函数作用:

设定解密用的Key;

参数说明:

userKey: 密钥数值;

bits:密钥长度,以bit为单位,如果密钥数字是16个字节,则此参数值应为128;

key: AES_KEY对象指针;

返回值: 0 成功, -1 userkey,key为空, -2: 密钥长度不是128,192,256;

 

3、使用函数AES_cbc_encrypt对数据进行加解密

函数原型:

void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,   size_t length, const AES_KEY *key,    unsigned char *ivec, const int enc);

函数作用:

AES加密/解密单个数据块(16个字节),CBC模式

参数说明:

in: 需要加密/解密的数据;

out: 计算后输出的数据;

length: 数据长度(这里不包含初始向量数据长度)

key:密钥

ivec: 初始向量(一般为16字节全0)

enc: AES_ENCRYPT 代表加密, AES_DECRYPT代表解密;

 

四、AES算法ECB、CBC两种模式下的加解密实现代码:

1、加密实现:

void CPage3::OnButtonEncrypt() 
{
 // TODO: Add your control notification handler code here
 unsigned char key_hex[256] = {0};
 unsigned char data_hex[256] = {0};
 unsigned char initval_hex[256] = {0};
 unsigned char temp[256] = {0};
 int i = 0;
 int keylen = 0;
 int datalen = 0;
 int InitialLen = 0;
 AES_KEY key;

    UpdateData(TRUE);

 m_key.Remove(' ');
 m_data.Remove(' ');
 m_initval.Remove(' ');
 
 keylen = m_key.GetLength()/2;
    datalen = m_data.GetLength()/2;
 InitialLen = m_initval.GetLength()/2;

 if (datalen%16!=0)
 {
  AfxMessageBox("输入数据长度不是16的整数倍,请重新输入!");
  return; 
 }

 StrToHex(m_key,key_hex,keylen);
 StrToHex(m_data,data_hex,datalen);
 StrToHex(m_initval,initval_hex,InitialLen);

 if (keylen == 16)
 {
  //设置加密密钥
  AES_set_encrypt_key(key_hex,128,&key);
 }
 else if (keylen == 24)
 {
        //设置加密密钥
  AES_set_encrypt_key(key_hex,192,&key);
 }
 else if (keylen == 32)
 {
  //设置加密密钥
  AES_set_encrypt_key(key_hex,256,&key);
 }
 else
 {
        AfxMessageBox("输入密钥长度不是16/24/32字节,请重新输入!");
  return; 
 }
 
 //ECB模式
 if (((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck())
 {
  for(i = 0;i < datalen/16;i++)
  {
   AES_ecb_encrypt(data_hex+i*16, temp+i*16,&key,AES_ENCRYPT);
  }
 }
 //CBC模式
 else if (((CButton*)GetDlgItem(IDC_RADIO2))->GetCheck())
 {
  memcpy(data_hex+datalen,"\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",16);

  datalen = datalen+16;
  
  for(i = 0;i < datalen/16;i++)
  {
   AES_cbc_encrypt(data_hex+i*16, temp+i*16,16,&key,initval_hex, AES_ENCRYPT);
  }
  
 }
 
 HexToStr(temp,datalen,m_result);

    UpdateData(FALSE);
}

 

2、解密实现

void CPage3::OnButtonDecrypt() 
{
 // TODO: Add your control notification handler code here
 unsigned char key_hex[256] = {0};
 unsigned char data_hex[256] = {0};
 unsigned char initval_hex[256] = {0};
 unsigned char temp[256] = {0};
 int i = 0;
 int keylen = 0;
 int datalen = 0;
 int InitialLen = 0;
 AES_KEY key;

    UpdateData(TRUE);

 m_key.Remove(' ');
 m_data.Remove(' ');
 m_initval.Remove(' ');
 
 keylen = m_key.GetLength()/2;
    datalen = m_data.GetLength()/2;
 InitialLen = m_initval.GetLength()/2;

 if (datalen%16!=0)
 {
  AfxMessageBox("输入数据长度不是16的整数倍,请重新输入!");
  return; 
 }

 StrToHex(m_key,key_hex,keylen);
 StrToHex(m_data,data_hex,datalen);
 StrToHex(m_initval,initval_hex,InitialLen);

 if (keylen == 16)
 {
  //设置解密密钥
  AES_set_decrypt_key(key_hex,128,&key);
 }
 else if (keylen == 24)
 {
        //设置解密密钥
  AES_set_decrypt_key(key_hex,192,&key);
 }
 else if (keylen == 32)
 {
  //设置解密密钥
  AES_set_decrypt_key(key_hex,256,&key);
 }
 else
 {
        AfxMessageBox("输入密钥长度不是16/24/32字节,请重新输入!");
  return; 
 }
 
 //ECB模式
 if (((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck())
 {
  for(i = 0;i < datalen/16;i++)
  {
   AES_ecb_encrypt(data_hex+i*16, temp+i*16,&key,AES_DECRYPT);
  }
 }
 //CBC模式
 else if (((CButton*)GetDlgItem(IDC_RADIO2))->GetCheck())
 {
  for(i = 0;i < datalen/16;i++)
  {
   AES_cbc_encrypt(data_hex+i*16, temp+i*16,16,&key,initval_hex, AES_DECRYPT);
  }
 }
 
 HexToStr(temp,datalen,m_result);

    UpdateData(FALSE);
}