1. 程式人生 > >openssl AES 加密演算法及程式碼例項

openssl AES 加密演算法及程式碼例項

一、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位元。

2、AES工作模式介紹    

      1)、ECB模式簡介

      2)、CBC模式簡介

                下圖中,IV一般為16位元組全0,資料塊長度為16位元組的整數倍,則在此資料塊後附加一個8位元組長的資料塊,

         附加的資料塊為:16進位制的“80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00”  

 

二、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);
}