為了更進一步強化訊息驗證(Message Authentication)的機密性,確保身份正確,昨天我們複習了金融產業中的訊息驗證碼MAC的概念,並且整理MAC演算法過程中需要使用到幾個運算方法。
好!今天捲起袖子寫程式(C#)。
演算法實作主要分成3個步驟: 明文拆解、運算、取出運算結果。
習慣上會將輸入的明文(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;
}
執行結果:
這個我們使用LINQ將輸入字串以16 Byte拆解成幾個區塊(block):
List<string> plainTexts = (from Match m in Regex.Matches(plainText, @"\S{16}")
select m.Value).ToList();
XOR
及DES
運算演算步驟: 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);
}
}
}
寫出的檔案內容:
每一筆資料的後方都增加了MAC值了。
取出的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
2011.10攝於Italy