iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 26
1
Security

資料安全與簡單加密演算法見面會 系列 第 26

[Day26]對稱金鑰加密系統(DEA x TDEA x 2TDEA)

DES演算法是70年代末藍色巨人IBM旗下力挺的新人,發音是ˈdɛz,在許多檔案傳輸與晶片卡文件中,為了和資料加密標準DES(Data Encryption Standard)有所區隔,也許我們也見過她的另外一個名稱:DEA(Data Encryption Algorithm),資料加密演算法。

80年代後,信用卡對於卡片安全的需求提升,許多信用卡磁條或晶片內儲存的驗證值都應用上了DEA演算法來運算,算是風靡了當時的資訊安全保護。

DEA演算法的金鑰長度為64 bits(實際使用56 bits),每一次只加密 64 bits (8 byte)區塊的明文資料,經過混淆與擴散運算後,輸出的加密結果也是64 bits (8 byte)。

DEA加解密


DEA是對稱金鑰加密系統家族的成員(Symmetric-key algorithm),我們簡單畫一個流程圖可以觀察到,DEA所使用的加密金鑰與簡單金鑰是同一把

http://ithelp.ithome.com.tw/upload/images/20170110/20103434rPYyQWqGNr.png

對稱金鑰加密系統就是這樣的概念,用哪一把金鑰鎖門就得用哪一把金鑰開門。

在C#中只要引用DESCryptoServiceProvider就可以呼叫DEA加解密功能了。
我們寫了簡單的函式,傳入Byte[]型別的加密金鑰及明文。。

public static byte[] Encryption(byte[] Deskey, byte[] plainText)
{
    SymmetricAlgorithm mCSP = new DESCryptoServiceProvider();
    //設定金鑰
    mCSP.Key = Deskey;
    //加密工作模式:CBC
    mCSP.Mode = CipherMode.CBC;
    //補充字元方式:0
    mCSP.Padding = PaddingMode.Zeros;
    //初始向量IV = 0
    mCSP.IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    //建立對稱加密物件
    ICryptoTransform ct = mCSP.CreateEncryptor(mCSP.Key, mCSP.IV);
    using (MemoryStream ms = new MemoryStream())
    {
        using (CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
        {
            cs.Write(plainText, 0, plainText.Length);
            cs.FlushFinalBlock();
            cs.Close();
            return ms.ToArray();
        }
    }
}

解密也類似,但把建立加密器的部分從CreateEncryptor改成解密器CreateDecryptor。

public static byte[] Decryption(byte[] Deskey, byte[] CipherText)
{
    SymmetricAlgorithm desAlg = new DESCryptoServiceProvider();
    //設定金鑰
    desAlg.Key = Deskey;
    //加密工作模式:CBC
    desAlg.Mode = CipherMode.CBC;
    //補充字元方式:0
    desAlg.Padding = PaddingMode.Zeros;
    //初始向量IV = 0
    desAlg.IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    ICryptoTransform ict = desAlg.CreateDecryptor(desAlg.Key, desAlg.IV);
    using (MemoryStream mStream = new MemoryStream())
    {
        using (CryptoStream cStream = new CryptoStream(mStream, ict, CryptoStreamMode.Write))
        {
            cStream.Write(CipherText, 0, CipherText.Length);
            cStream.FlushFinalBlock();
        }
        return mStream.ToArray();
    }
}

在應用加解密功能時,有時會碰到將明文視為16進位字串的情形,像是我們有一組16位數的卡號,就必須以8 Byte方式輸入進行DES運算。為了便於使用,偷偷把轉換功能寫進Extensions。

[Day19] 資料傳輸安全(完整性)MAC訊息驗證碼 (上)也曾寫過相同的程式碼喔。(16進位字串與位元組陣列相互間轉換)

16進位字串轉換Byte array

public static byte[] HexToByte(this string hexString)
{
    //運算後的位元組長度:16進位數字字串長/2
    byte[] byteOUT = new byte[hexString.Length / 2];
    for (int i = 0; i < hexString.Length; i = i + 2)
    {
        //每2位16進位數字轉換為一個10進位整數
        byteOUT[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
    }
    return byteOUT;
}

最後返回結果時,Byte array轉換為16進位字串

public static string BToHex(this byte[] Bdata)
{
    return BitConverter.ToString(Bdata).Replace("-", "");
}

好!來測試看看DEA加解密!

[TestMethod]
public void TestMethod1()
{
    string PlaintText = "0A202020544F2059";
    string key = "E6A12F079D15C437";
    Console.WriteLine($"明文:{PlaintText}");
    byte[] bCipherText = Encryption(key.HexToByte(), PlaintText.HexToByte());
    Console.WriteLine("加密:{0}", bCipherText.BToHex());
    byte[] bPlaintText = Decryption(key.HexToByte(), bCipherText);
    Console.WriteLine("解密:{0}", bPlaintText.BToHex());
}

http://ithelp.ithome.com.tw/upload/images/20170110/20103434B56Nuv54or.png

除了把明文視為16進位字串外,DEA也能支援中文字,但需要靠編碼來解,這邊我們以unicode編碼為例。

[TestMethod]
public void TestMethod2()
{
   string PlaintText = "我是機密";
   string key = "E6A12F079D15C437";
   Console.WriteLine($"明文:{PlaintText}");
   byte[] bCipherText = Encryption(key.HexToByte(), Encoding.Unicode.GetBytes(PlaintText));
   byte[] bPlaintText = Decryption(key.HexToByte(), bCipherText);
   Console.WriteLine("加密結果:{0}", Encoding.Unicode.GetString(bCipherText));
   Console.WriteLine("解密結果:{0}", Encoding.Unicode.GetString(bPlaintText));
}

http://ithelp.ithome.com.tw/upload/images/20170110/20103434YhNivJWqbc.png

由於DEA金鑰長度不夠而存在金鑰破解問題,後來有衍生了兩種Triple DEA的演算法,主要在運算過程強化金鑰及運算步驟。

  • TDEA: Triple DEA(Data Encryption Algorithm)
  • 2TDEA: 2 Key Triple DEA

TDEA


簡單的描述TDEA的演算過程,她將明文資料使用3把金鑰依序進行(1)加密、(2)解密、(3)加密,經過 DES 3次運算所得出的運算結果。

簡單畫Triple DEA 的流程圖:
1.加密流程: KEY3_DES加密(KEY2_DES解密(KEY1_DES加密(明文)))
2.解密流程: KEY1_DES解密(KEY2_DES加密(KEY3_DES解密(密文)))
http://ithelp.ithome.com.tw/upload/images/20170110/20103434ItpetjZAaC.png

加解密程式段落幾乎和DES一模一樣樣,只差加密法元件不同。
DES

SymmetricAlgorithm mCSP = new DESCryptoServiceProvider();

Triple DES

TripleDESCryptoServiceProvider mCSP = new TripleDESCryptoServiceProvider();

TDEA (Triple DES)加密

public static byte[] TDEAEncryption(byte[] Deskey, byte[] plainText)
{
    TripleDESCryptoServiceProvider mCSP = new TripleDESCryptoServiceProvider();
    //設定金鑰
    mCSP.Key = Deskey;
    //加密工作模式:CBC
    mCSP.Mode = CipherMode.CBC;
    //補充字元方式:0
    mCSP.Padding = PaddingMode.Zeros;
    //初始向量IV = 0
    mCSP.IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    //建立對稱加密物件
    ICryptoTransform ct = mCSP.CreateEncryptor(mCSP.Key, mCSP.IV);
    using (MemoryStream ms = new MemoryStream())
    {
        using (CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
        {
            cs.Write(plainText, 0, plainText.Length);
            cs.FlushFinalBlock();
            cs.Close();
            return ms.ToArray();
        }
    }
}

TDEA (Triple DES)解密

public static byte[] TDEADecryption(byte[] Deskey, byte[] CipherText)
{
    TripleDESCryptoServiceProvider desAlg = new TripleDESCryptoServiceProvider();
    //設定金鑰
    desAlg.Key = Deskey;
    //加密工作模式:CBC
    desAlg.Mode = CipherMode.CBC;
    //補充字元方式:0
    desAlg.Padding = PaddingMode.Zeros;
    //初始向量IV = 0
    desAlg.IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    ICryptoTransform ict = desAlg.CreateDecryptor(desAlg.Key, desAlg.IV);
    using (MemoryStream mStream = new MemoryStream())
    {
        using (CryptoStream cStream = new CryptoStream(mStream, ict, CryptoStreamMode.Write))
        {
            cStream.Write(CipherText, 0, CipherText.Length);
            cStream.FlushFinalBlock();
        }
        return mStream.ToArray();
    }
}

測試Triple DES加解密
注意輸入金鑰的地方,我們一次輸入3把金鑰長度的16進位字串(16 * 3 = 48)

[TestMethod]
public void TestTDEA()
{
    string PlaintText = "0A202020544F2059";
    string key = "E6A12F079D15C4371234567890ABCDEFFEDCBA0987654321";
    Console.WriteLine($"明文:{PlaintText}");
    byte[] bCipherText = TDEAEncryption(key.HexToByte(), PlaintText.HexToByte());
    Console.WriteLine("加密:{0}", bCipherText.BToHex());
    byte[] bPlaintText = TDEADecryption(key.HexToByte(), bCipherText);
    Console.WriteLine("解密:{0}", bPlaintText.BToHex());
}

執行結果
http://ithelp.ithome.com.tw/upload/images/20170110/20103434qUIOGKxXDj.png

2TDEA


2TDEA則是使用2把金鑰依序進行(1)加密、(2)解密、(3)加密,第1次加密與第3次加密所使用的金鑰相同。

簡單畫Two key Triple DEA 的流程圖
1.加密流程: KEY1_DES加密(KEY2_DES解密(KEY1_DES加密(明文)))
2.解密流程: KEY1_DES解密(KEY2_DES加密(KEY1_DES解密(密文)))
http://ithelp.ithome.com.tw/upload/images/20170110/201034347Ih7DJmmkP.png

2TDEA可以直接使用TDEA的程式段落,只要輸入金鑰的長度,從3把金鑰長度改為2把金鑰的16進位字串長度(16 * 2 = 32)

[TestMethod]
public void Test2TDEA()
{
    string PlaintText = "0A202020544F2059";
    string key = "1234567890ABCDEFFEDCBA0987654321";
    Console.WriteLine($"明文:{PlaintText}");
    byte[] bCipherText = TDEAEncryption(key.HexToByte(), PlaintText.HexToByte());
    Console.WriteLine("加密:{0}", bCipherText.BToHex());
    byte[] bPlaintText = TDEADecryption(key.HexToByte(), bCipherText);
    Console.WriteLine("解密:{0}", bPlaintText.BToHex());
}

http://ithelp.ithome.com.tw/upload/images/20170110/20103434FtXByrCjKK.png


DEA在2000年後已經被公認為是一種不安全的加密方法,主要原因加密所使用的金鑰過短(56 bits),甚至有神祕組織EFF製造了DES cracker及Deep cracker在22小時內就破解金鑰,也因此後起之秀AES(高階加密標準)逐漸取代了她,2002年後已成為美國聯邦政府新的標準。

不過在支付卡產業中,幾乎所有的驗證值,卡片磁條內的、卡片背後的、卡片晶片內的,還有許多檢算還是維持在DEA或是2TDEA演算法,也因為支付卡產業只使用在運算驗證值上而不是加密整段明文,如果金鑰的保護得宜,也還是一個安全的保護機制。

AES也是對稱金鑰加密系統家族成員,她可以支援更大的資料區塊運算(128 bits),同時金鑰長度從128、192到256 bits金鑰長度,我們前面曾經在[Day22] 資料傳輸安全(機密性) RSA x AES 混搭風見過她,後面就不多花時間複習了,我們今天很快的複習DEA、2TDEA及TDEA,如果有對稱金鑰加密的需求,建議以AES 256優先


連續第3天講古,也是古代時候,已經成為系統設計師(SD)的史丹利有次到外頭和某機構研究所的資訊專家們討論資料保護,自知大敵當前不能緊張,史丹利壓抑住緊張很有自信的回答保護機制,講到金鑰都被保護在"DES機器"中,登楞....講完後察覺到專家們好像都不太明白DES機,後來發現其實這這名詞是我們公司學長學弟間自創的,而且還有薪火相傳,其實本來要形容的應該是HSM(Hardware Security Module),囧。

相信曾是Mainframe(大型主機) cobol工程師的朋友都能理解,Mainframe 是一個很封閉但相較安全的系統環境,除了網路封閉,可能技術發展已經很成熟,也很少和外面交流,技術用語有時也產生一種組織內特有文化,有時和外界溝通時會發生很窘(囧)的遭遇。

/images/emoticon/emoticon37.gif

參考


資料加密標準wiki
https://zh.wikipedia.org/wiki/%E8%B3%87%E6%96%99%E5%8A%A0%E5%AF%86%E6%A8%99%E6%BA%96

進階加密標準 wiki
https://zh.wikipedia.org/wiki/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86

EFF DES破解機 wiki
https://zh.wikipedia.org/wiki/EFF_DES%E7%A0%B4%E8%A7%A3%E6%9C%BA


Bodensee波登湖港口
http://ithelp.ithome.com.tw/upload/images/20170110/20103434Ip5VmDLiYo.jpg
2014.12攝於林島,德國


上一篇
[Day25] 簡單加密演算法見面
下一篇
[Day27] 非對稱金鑰加密系統(RSA)
系列文
資料安全與簡單加密演算法見面會 30

尚未有邦友留言

立即登入留言