對稱加密DES和TripleDES

一、 對稱加密
對稱加密,是一種比較傳統的加密方式,其加密運算、解密運算使用的是同樣的密鑰,信息的發送者和信息的接收者在進行信息的傳輸與處理時,必須共同持有該密碼(稱爲對稱密碼)。因此,通信雙方都必須獲得這把鑰匙,並保持鑰匙的祕密。
單鑰密碼系統的安全性依賴於以下兩個因素:
第一、加密算法必須是足夠強的,僅僅基於密文本身去解密信息在實踐上是不可能的。
第二、加密方法的安全性依賴於密鑰的祕密性,而不是算法的祕密性,因此,我們沒有必要確保算法的祕密性(事實上,現實中使用的很多單鑰密碼系統的算法都是公開的),但是我們一定要保證密鑰的祕密性。
DES(Data Encryption Standard)和TripleDES是對稱加密的兩種實現。
DES和TripleDES基本算法一致,只是TripleDES算法提供的key位數更多,加密可靠性更高。
DES使用的密鑰key爲8字節,初始向量IV也是8字節。
TripleDES使用24字節的key,初始向量IV也是8字節。
兩種算法都是以8字節爲一個塊進行加密,一個數據塊一個數據塊的加密,一個8字節的明文加密後的密文也是8字節。如果明文長度不爲8字節的整數倍,添加值爲0的字節湊滿8字節整數倍。所以加密後的密文長度一定爲8字節的整數倍。

本文測試源代碼:http://files.cnblogs.com/files/chnking/TripleDESTest.rar

二、 加密解密過程

這裏寫圖片描述

1、 生成key和IV
System.Security.Cryptography. TripleDESCryptoServiceProvider類是dotnet中實現TripleDES算法的主要的類。
TripleDESCryptoServiceProvider類只有一個構造方法TripleDESCryptoServiceProvider(),這個方法把一些屬性初始化:
KeySize(加密密鑰長度,以位爲單位)= 192(24字節)
BlockSize(加密處理的數據塊大小,以位爲單位)= 64(8字節)
FeedbackSize(加密數據塊後返回的數據大小,以位爲單位)= 64(8字節)

TripleDESCryptoServiceProvider構造方法同時會初始化一組隨機的key和IV。
默認的TripleDESCryptoServiceProvider的key爲24字節,IV爲8字節,加密數據塊爲8字節。
生成key和IV的代碼很簡單:

TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();
byte[] keyArray = tDESalg.Key;
byte[] IVArray = tDESalg.IV;

生成的key和IV在加密過程和解密過程都要使用。

2、 字符串明文轉成某一代碼頁對應的編碼字節流
待加密的數據可能有兩種形式,一種是二進制的數據,本身就是一組字節流,這樣的數據可以跳過這一步,直接進入加密步驟。還有一種情況是字符串數據,字符串中同樣的字符使用不同的代碼頁會生成不同的字節碼,所以從字符串到字節流的轉換是需要指定使用何種編碼的。在解密之後,要從字節流轉換到字符串就要使用相同的代碼頁解碼,否則就會出現亂碼。

// 待加密的字符串
string plainTextString = "Here is some data to encrypt. 這裏是一些要加密的數據。";
// 使用utf-8編碼(也可以使用其它的編碼)
Encoding sEncoding = Encoding.GetEncoding("utf-8");
// 把字符串明文轉換成utf-8編碼的字節流
byte[] plainTextArray = sEncoding.GetBytes(plainTextString);

3、 加密操作
加密的原料是明文字節流,TripleDES算法對字節流進行加密,返回的是加密後的字節流。同時要給定加密使用的key和IV。

// 把字符串明文轉換成utf-8編碼的字節流
byte[] plainTextArray = sEncoding.GetBytes(plainTextString);
public static byte[] EncryptString(byte[] plainTextArray, byte[] Key, byte[] IV)
{
    // 建立一個MemoryStream,這裏面存放加密後的數據流
    MemoryStream mStream = new MemoryStream();
    // 使用MemoryStream 和key、IV新建一個CryptoStream 對象
    CryptoStream cStream = new CryptoStream(mStream,
        new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV),
        CryptoStreamMode.Write);
    // 將加密後的字節流寫入到MemoryStream
    cStream.Write(plainTextArray, 0, plainTextArray.Length);
    //把緩衝區中的最後狀態更新到MemoryStream,並清除cStream的緩存區
    cStream.FlushFinalBlock();
    // 把解密後的數據流轉成字節流
    byte[] ret = mStream.ToArray();
    // 關閉兩個streams.
    cStream.Close();
    mStream.Close();
    return ret;
}

4、 解密操作
解密操作解密上面步驟生成的密文byte[],需要使用到加密步驟使用的同一組Key和IV。
// 調用解密方法,返回已解密數據的byte[]

byte[] finalPlainTextArray = DecryptTextFromMemory(Data, keyArray, IVArray);
public static byte[] DecryptTextFromMemory(byte[] EncryptedDataArray, byte[] Key, byte[] IV)
{
    // 建立一個MemoryStream,這裏面存放加密後的數據流
    MemoryStream msDecrypt = new MemoryStream(EncryptedDataArray);
    // 使用MemoryStream 和key、IV新建一個CryptoStream 對象
    CryptoStream csDecrypt = new CryptoStream(msDecrypt,
        new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV),
        CryptoStreamMode.Read);
    // 根據密文byte[]的長度(可能比加密前的明文長),新建一個存放解密後明文的byte[]
    byte[] DecryptDataArray = new byte[EncryptedDataArray.Length];
    // 把解密後的數據讀入到DecryptDataArray
    csDecrypt.Read(DecryptDataArray, 0, DecryptDataArray.Length);
    msDecrypt.Close();
    csDecrypt.Close();
    return DecryptDataArray;
}

有一點需要注意,DES加密是以數據塊爲單位加密的,8個字節一個數據塊,如果待加密明byte[]的長度不是8字節的整數倍,算法先用值爲“0”的byte補足8個字節,然後進行加密。所以加密後的密文長度一定是8的整數倍。這樣的密文解密後如果補了0值的byte,則解密後這些0值的byte依然存在。比如上例中要加密的明文是:
“Here is some data to encrypt. 這裏是一些要加密的數據。”
轉成明文byte[]後是66個字節,DES算法就會補上6個0值的byte,補到72個字節。這樣加密後再解密回來的密文byte[]解碼後的字符串就是這樣的:
“Here is some data to encrypt. 這裏是一些要加密的數據。\0\0\0\0\0\0”
5、 從編碼字節流轉成字符串明文
// 使用前面定義的Encoding,utf-8的編碼把byte[]轉成字符串
plainTextString = sEncoding.GetString(finalPlainTextArray);

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