iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 20
2
Security

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

[Day20] 資料傳輸安全(完整性)MAC訊息驗證碼 (下)

為了更進一步強化訊息驗證(Message Authentication)的機密性,確保身份正確,昨天我們複習了金融產業中的訊息驗證碼MAC的概念,並且整理MAC演算法過程中需要使用到幾個運算方法。

  • 16進位字串(hexadecimal string)轉Byte array
  • Byte array轉16進位字串
  • XOR Exclusive OR運算。
  • DES加密演算法

好!今天捲起袖子寫程式(C#)。

MAC 演算法實作


演算法實作主要分成3個步驟: 明文拆解、運算、取出運算結果。

1.將明文以每8 Byte拆解成幾個Block區塊。

習慣上會將輸入的明文(plaint text)視為16進位字串(hexadecimal string),如果一段8 Byte的明文以16進位表示時,會成為16 Byte,因此MAC演算法中以8 Byte拆解區塊時,實際上需要取每16個Byte明文資料作為區塊(block)。

也因為16進位字串值(hexadecimal string)的範圍從0-F,通常取值時只會取明文中數字(digit)的部分並在取出的字串後端以0或F填補(Padding)

簡單撰寫取出明文中的數字並進行填補:

[TestMethod]
public void TestgetDigit()
{
    List<string> datas = new List<string>()
    {
        "4567-1111-2222-3333,高雄台鋁生活商場,1000",
        "4567-1111-2222-3333,台北微風信義分店,2000",
        "5567-1111-2222-3333,台南南紡購物中心,3000",
        "END,3,6000"
    };
    foreach (var item in datas)
    {
        Console.WriteLine(getDigit(item));
    }
}

public string getDigit(string plainText)
{
    var matches = Regex.Matches(plainText, @"[0-9]+", RegexOptions.Compiled);
    string s = string.Join(string.Empty, matches.Cast<Match>()
                        .Select(x => x.Value).ToArray());
    if (s.Length % 16 != 0)
    {
        return string.Format("{0}{1}", s, "".PadRight(16 - (s.Length % 16), 'F'));
    }
    return s;
}

執行結果:

http://ithelp.ithome.com.tw/upload/images/20170104/20103434wS6aAPPN0s.png

這個我們使用LINQ將輸入字串以16 Byte拆解成幾個區塊(block):

List<string> plainTexts = (from Match m in Regex.Matches(plainText, @"\S{16}")
                                       select m.Value).ToList();

2.逐一對block進行XORDES運算

演算步驟: Des_EN(Des_EN(P1) XOR P2) ~ n times

IV = 0x00,明文與IV或下一段進行XOR運算後再使用DES加密演算法運算

這邊我們假設DES加密金鑰是E6A12F079D15C437,通常金鑰會每隔一段時間交換,例如每8小時,這邊因為是範例,所以先hard code。

[TestMethod]
public void TestMethod2()
{
    //DES加密金鑰
    string DesKey = "E6A12F079D15C437";

    //輸入資料
    List<string> datas = new List<string>()
    {
        "4567-1111-2222-3333,高雄台鋁生活商場,1000",
        "4567-1111-2222-3333,台北微風信義分店,2000",
        "5567-1111-2222-3333,台南南紡購物中心,3000",
        "END,3,6000"
    };

    //輸出資料
    List<string> outdatas = new List<string>();
    foreach (var data in datas)
    {
        //拆解
        List<string> plainTexts = (from Match m in Regex.Matches(getDigit(data), @"\S{16}")
                                   select m.Value).ToList();
        //從第1段明文開始
        byte[] CipherText = plainTexts[0].HexToByte();
        for (int i = 0; i < plainTexts.Count; i++)
        {
            //XOR: SKIP第1次IV=0,
            if (i > 0)
            {
                CipherText = XOR(CipherText, plainTexts[i].HexToByte());
            }
            //Console.WriteLine("{0} time XOR: {1}", i + 1, CipherText.BToHex());

            //加密
            CipherText = Encryption(DesKey.HexToByte(), CipherText);
            //Console.WriteLine("{0} time Encryption: {1}", i + 1, CipherText.BToHex());
        }
        outdatas.Add(string.Format($"{data},{CipherText.BToHex()}"));
    }
    //寫出檔案
    using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\temp\transaction.txt", false))
    {
        foreach (var item in outdatas)
        {
            file.WriteLine(item);
        }
    }
}

寫出的檔案內容:
http://ithelp.ithome.com.tw/upload/images/20170104/20103434fODP2aICci.png

每一筆資料的後方都增加了MAC值了。

3.取出運算結果

取出的MAC值又稱押碼,通常會取最終加密結果前8個或後8個hexadecimal 16進位字串值,這邊的範例我們先完整取出16 Byte。

這兩天我們複習了MAC的驗證機制,透過DES加密金鑰定時的更新以及MAC值的驗證,我們就能在資料傳輸時對檔案內容中的重要帳務參數維繫更好的完整性。

  • 確保訊息完整未遭竄改
  • 鑑定訊息來源

參考


訊息鑑別碼 Wiki
https://zh.wikipedia.org/wiki/%E8%A8%8A%E6%81%AF%E9%91%91%E5%88%A5%E7%A2%BC

Block cipher mode of operation wiki
https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

史丹利部2016落格: 史丹利好熱。
https://dotblogs.com.tw/stanley14/2016/02/10/110559


開單again
http://ithelp.ithome.com.tw/upload/images/20170104/20103434lpa7x0xyV9.jpg
2011.10攝於Italy


上一篇
[Day19] 資料傳輸安全(完整性)MAC訊息驗證碼 (上)
下一篇
[Day21] 資料傳輸安全(完整性)數位簽章
系列文
資料安全與簡單加密演算法見面會 30

尚未有邦友留言

立即登入留言