zoukankan      html  css  js  c++  java
  • 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,"x80x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00",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); 
    }

    转自:http://www.tuicool.com/articles/aeE3ui

  • 相关阅读:
    POJ 1721 CARDS(置换群)
    HDU 4609 3-idiots(FFT)
    BZOJ 4259 残缺的字符串(FFT)
    HDU 5763 Another Meaning(FFT)
    BZOJ 4503 两个串(FFT)
    hihoCoder 1388 Periodic Signal(FFT)
    HDU 5823 color II(FWT)
    HDU 5768 Lucky7(CRT+容斥原理)
    HDU 5446 Unknown Treasure(Lucas定理+CRT)
    HDU 5741 Helter Skelter(构造法)
  • 原文地址:https://www.cnblogs.com/banwhui/p/5146012.html
Copyright © 2011-2022 走看看