OPENSSL庫的使用-DES篇

轉自:http://blog.csdn.net/duanxingheng/article/details/11655037


一、DES算法簡介

1、DES算法介紹

        DES算法爲密碼體制中的對稱密碼體制,又被稱爲美國數據加密標準,是1972年美國IBM公司研製的對稱密碼體制加密算法。 明文按64位進行分組,密鑰長64位,密鑰事實上是56位參與DES運算(第8、16、24、32、40、48、56、64位是校驗位, 使得每個密鑰都有奇數個1)分組後的明文組和56位的密鑰按位替代或交換的方法形成密文組的加密方法。

2、工作模式

      1)ECB模式

            DES ECB(電子密本方式)其實非常簡單,就是將數據按照8個字節一段進行DES加密或解密得到一段8個字節的密文或者明文,最後一段不足8個字節,按照需求補足8個字節進行計算,之後按照順序將計算所得的數據連在一起即可,各段數據之間互不影響。

      2)CBC模式

     DES CBC(密文分組鏈接方式)有點麻煩,它的實現機制使加密的各段數據之間有了聯繫。其實現的機理如下:

   加密步驟如下:

a)首先將數據按照8個字節一組進行分組得到D1、D2......Dn(若數據不是8的整數倍,用指定的PADDING數據補位)

b)第一組數據D1與初始化向量I異或後的結果進行DES加密得到第一組密文C1(初始化向量I爲全零)

c)第二組數據D2與第一組的加密結果C1異或以後的結果進行DES加密,得到第二組密文C2

d)之後的數據以此類推,得到Cn

e)按順序連爲C1C2C3......Cn即爲加密結果。

解密是加密的逆過程,步驟如下:

a)首先將數據按照8個字節一組進行分組得到C1C2C3......Cn

b)將第一組數據進行解密後與初始化向量I進行異或得到第一組明文D1(注意:一定是先解密再異或)

c)將第二組數據C2進行解密後與第一組密文數據進行異或得到第二組數據D2

d)之後依此類推,得到Dn

e)按順序連爲D1D2D3......Dn即爲解密結果。

這裏注意一點,解密的結果並不一定是我們原來的加密數據,可能還含有你補得位,一定要把補位去掉纔是你的原來的數據。

 

3、3DES 算法

3DES算法顧名思義就是3次DES算法,其算法原理如下:

設Ek()和Dk()代表DES算法的加密和解密過程,K代表DES算法使用的密鑰,P代表明文,C代表密表,這樣,


      3DES加密過程爲:C=Ek3(Dk2(Ek1(P))) 
      3DES解密過程爲:P=Dk1((EK2(Dk3(C)))

這裏可以K1=K3,但不能K1=K2=K3(如果相等的話就成了DES算法了)

3DES算法圖示如下:

 

3DES with 2 diffrent keys(K1=K3),可以是3DES-CBC,也可以是3DES-ECB,3DES-CBC整個算法的流程和DES-CBC一樣,但是在原來的加密或者解密處增加了異或運算的步驟,使用的密鑰是16字節長度的密鑰,將密鑰分成左8字節和右8字節的兩部分,即k1=左8字節,k2=右8字節,然後進行加密運算和解密運算。

3DES with 3 different keys,和3DES-CBC的流程完全一樣,只是使用的密鑰是24字節的,但在每個加密解密加密時候用的密鑰不一樣,將密鑰分爲3段8字節的密鑰分別爲密鑰1、密鑰2、密鑰3,在3DES加密時對加密解密加密依次使用密鑰1、密鑰2、密鑰3,在3DES解密時對解密加密解密依次使用密鑰3、密鑰2、密鑰1。

 

二、單DES算法ECB模式加解密

1、使用函數DES_set_key_unchecked設置密鑰。

備註:

1)自己指定密鑰時,切記勿使用函數DES_string_to_key,該函數是根據輸入的string隨機計算key,並不是將輸入的string當作key。

2)設置key必須使用DES_set_key_unchecked函數,而不能使用DES_set_key_check函數,否則計算出來的數據會不正確。

3)openssl在進行DES運算時,僅按8字節塊加密,所以必須自己進行數據拆分

 

2、使用函數DES_ecb_encrypt來進行數據加解密

void DES_ecb_encrypt(const_DES_cblock *input,DES_cblock *output,
             DES_key_schedule *ks,int enc);

函數功能說明:DES ECB計算

參數說明:

input: 輸入數據;(8字節長度)

output: 輸出數據;(8字節長度)

ks: 密鑰;

enc:加密:DES_ENCRYPT , 解密:DES_DECRYPT;

 

三、單DES算法CBC模式加解密

1、使用函數DES_set_key_unchecked設置密鑰

2、使用函數DES_ncbc_encrypt來進行數據加解密

void DES_ncbc_encrypt(const unsigned char *input,unsigned char *output,
              long length,DES_key_schedule *schedule,DES_cblock *ivec,
              int enc);

參數說明:

input: 輸入數據;(8字節長度)

output: 輸出數據;(8字節長度)

length: 數據長度;(這裏數據長度不包含初始化向量長度

schedule:密鑰;

ivec: 初始化向量;(一般爲8個字節0)

enc:加密:DES_ENCRYPT , 解密:DES_DECRYPT;

 

四、T-DES算法ECB模式加解密

1、使用函數DES_set_key_unchecked設置密鑰

2、使用函數DES_ecb3_encrypt來進行加解密

void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
              DES_key_schedule *ks1,DES_key_schedule *ks2,
              DES_key_schedule *ks3, int enc);

函數說明:

3DES ECB算法

參數說明:

input: 輸入數據

output: 輸出數據

ks1,ks2,ks3, 3DES算法的三隻密鑰,實際應用中,大家更習慣於用兩隻密鑰,調用此函數時,只需在ks3處傳入ks1即可;

enc:加密:DES_ENCRYPT , 解密:DES_DECRYPT

 

五、T-DES算法CBC模式加解密

1、使用函數DES_set_key_unchecked設置密鑰

2、使用函數DES_ede3_cbc_encrypt來進行加解密

void DES_ede3_cbc_encrypt(const unsigned char *input,unsigned char *output, 
              long length,
              DES_key_schedule *ks1,DES_key_schedule *ks2,
              DES_key_schedule *ks3,DES_cblock *ivec,int enc);

函數功能說明:

3DES CBC模式計算;

參數說明:

input: 輸入數據;(8字節長度)

output: 輸出數據;(8字節長度)

length: 長度;(這裏數據長度不包含初始化向量長度

ks1:密鑰1;(爲16字節密鑰的左邊8字節)

ks2:密鑰2;(爲16字節密鑰的右邊8字節)

ks3:密鑰3;(爲16字節密鑰的左邊8字節)

ivec:初始化向量;;(一般爲8個字節0)

enc:DES_ENCRYPT , 解密:DES_DECRYPT;

3、CBC模式簡介

數據加密採用3DES-CBC算法,初始向量爲16進制數“0000000000000000”,如圖所示:

數據塊長度爲8字節整數倍,則在此數據塊後附加一個8字節長的數據塊,附加的數據塊爲:16進制的“80 00 00 00 00 00 00 00”

六、示例代碼

1、加密實現:

void CPage1::OnButtonEncrypt() 
{
 // TODO: Add your control notification handler code here
 DES_cblock key;

 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;
 DES_key_schedule schedule;
 DES_key_schedule schedule2;
 DES_key_schedule schedule3;
 const_DES_cblock input;
 DES_cblock output;
 DES_cblock ivec;

    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 (keylen%8!=0)
 {
  AfxMessageBox("輸入密鑰長度不是8的整數倍,請重新輸入!");
  return; 
 }

 if (datalen%8!=0)
 {
  AfxMessageBox("輸入數據長度不是8的整數倍,請重新輸入!");
  return; 
 }

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

 

 if (keylen == 8)
 {
  memcpy(key,key_hex,keylen);
  DES_set_key_unchecked(&key, &schedule); 
 }
 else if (keylen == 16)
 {
  memcpy(key,key_hex,8);
        DES_set_key_unchecked(&key, &schedule); 
  memcpy(key,key_hex+8,8);
        DES_set_key_unchecked(&key, &schedule2); 
  memcpy(key,key_hex,8);
        DES_set_key_unchecked(&key, &schedule3); 
 }
    
 
 memcpy(ivec,initval_hex,InitialLen);

 //單DES算法
 if (keylen == 8)
 {
  //ECB模式
        if (((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck())
  {
   for(i = 0;i < datalen/8;i++)
   {
    memcpy(input,data_hex+i*8,8);
    DES_ecb_encrypt(&input, &output, &schedule, DES_ENCRYPT);
    memcpy(temp+i*8,output,8);
   }
  }
  //CBC模式
  else if (((CButton*)GetDlgItem(IDC_RADIO2))->GetCheck())
  {
   memcpy(data_hex+datalen,"\x80\x00\x00\x00\x00\x00\x00\x00",8);
   datalen += 8;
   
   for(i = 0;i < datalen/8;i++)
   {
    DES_ncbc_encrypt(data_hex+i*8, temp+i*8,8,&schedule,&ivec, DES_ENCRYPT);
   }
  }
 }
 //TDES算法
 else if (keylen == 16)
 {
  //ECB模式
        if (((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck())
  {
   for (i = 0;i < datalen/8;i++)
   {
    memcpy(input,data_hex+i*8,8);
    DES_ecb3_encrypt(&input, &output, &schedule, &schedule2, &schedule3, DES_ENCRYPT);
    memcpy(temp+i*8,output,8);
   }
   
  }
  //CBC模式
  else if (((CButton*)GetDlgItem(IDC_RADIO2))->GetCheck())
  {
   memcpy(data_hex+datalen,"\x80\x00\x00\x00\x00\x00\x00\x00",8);
   datalen += 8;

   for(i = 0;i < datalen/8;i++)
   {
    DES_ede3_cbc_encrypt(data_hex+i*8, temp+i*8,8,&schedule, &schedule2, &schedule3,&ivec, DES_ENCRYPT);
   }
  }

 }
 
 HexToStr(temp,datalen,m_result);

    UpdateData(FALSE);
}

 

2、解密實現:

void CPage1::OnButtonDecrypt() 
{
 // TODO: Add your control notification handler code here
 DES_cblock key;

 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;
 DES_key_schedule schedule;
 DES_key_schedule schedule2;
 DES_key_schedule schedule3;
 const_DES_cblock input;
 DES_cblock output;
 DES_cblock ivec;

    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 (keylen%8!=0)
 {
  AfxMessageBox("輸入密鑰長度不是8的整數倍,請重新輸入!");
  return; 
 }

 if (datalen%8!=0)
 {
  AfxMessageBox("輸入數據長度不是8的整數倍,請重新輸入!");
  return; 
 }

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

 if (keylen == 8)
 {
  memcpy(key,key_hex,keylen);
  DES_set_key_unchecked(&key, &schedule); 
 }
 else if (keylen == 16)
 {
  memcpy(key,key_hex,8);
        DES_set_key_unchecked(&key, &schedule); 
  memcpy(key,key_hex+8,8);
        DES_set_key_unchecked(&key, &schedule2); 
  memcpy(key,key_hex,8);
        DES_set_key_unchecked(&key, &schedule3); 
 }
 
 memcpy(ivec,initval_hex,InitialLen);

 if (keylen == 8)
 {
  if (((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck())
  {
   for(i = 0;i < datalen/8;i++)
   {
    memcpy(input,data_hex+i*8,8);
    DES_ecb_encrypt(&input, &output, &schedule, DES_DECRYPT);
    memcpy(temp+i*8,output,8);
   }
  }
  else if (((CButton*)GetDlgItem(IDC_RADIO2))->GetCheck())
  {
   for(i = 0;i < datalen/8;i++)
   {
    DES_ncbc_encrypt(data_hex+i*8, temp+i*8,8,&schedule,&ivec, DES_DECRYPT);
   }
  }
 }
 else if (keylen == 16)
 {
  //ECB模式
        if (((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck())
  {
   for (i = 0;i < datalen/8;i++)
   {
    memcpy(input,data_hex+i*8,8);
    DES_ecb3_encrypt(&input, &output, &schedule, &schedule2, &schedule3, DES_DECRYPT);
    memcpy(temp+i*8,output,8);
   }
   
  }
  //CBC模式
  else if (((CButton*)GetDlgItem(IDC_RADIO2))->GetCheck())
  {
   for(i = 0;i < datalen/8;i++)
   {
    DES_ede3_cbc_encrypt(data_hex+i*8, temp+i*8,8,&schedule, &schedule2, &schedule3,&ivec, DES_DECRYPT);
   }
  }
 }
   
 HexToStr(temp,datalen,m_result);

    UpdateData(FALSE);
}

 


發佈了2 篇原創文章 · 獲贊 7 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章