如果資料傳輸的環境是在安全加密的通道內,要確保訊息完整未遭竄改,使用昨天選擇的雜湊Hash algorithm計算(SHA)就很給力了;但如果傳輸通道的安全沒辦法confirm,非經授權的第三者還是有可能竄改並重新運算新的Hash值詐欺我們,因此系統間若要傳送重要的資訊,鑑定訊息完整性的保護需要再進化。
為了使傳輸中的資料不會被非經授權的第三者竄改或破壞,同時也希望強化機密性,在金融產業中有一種訊息驗證碼或稱訊息鑑別碼MAC,一個與彩妝品牌M.A.C與蘋果電腦MAC同名的演算法。
MAC全文是M
essage A
uthentication C
ode,訊息驗證碼,有時在銀行也聽到押碼。是一種卡片交易訊息保護的應用,目的:
傳送端依照雙方固定期間交換好的金鑰,將檔案內容以特定的演算法計算雜湊值,然後連同原始檔案一起傳送到接收端。
接收端收到資料後,也依照雙方約定好的金鑰以特定的演算法對檔案作雜湊運算,然後鑑定雜湊是否相符。
圖片來源:Wiki Mac
https://zh.wikipedia.org/wiki/%E8%A8%8A%E6%81%AF%E9%91%91%E5%88%A5%E7%A2%BC
MAC目前也是**ISO國際標準(編號:9807)及CNS國家標準(編號:13526)**的項目之一,雖然計算MAC雜湊值演算法也是國際公開的標準,不過MAC的機制中每隔一段時間就會進行加密金鑰的交換,機密性提升了許多。
ISO9807:
Used to validate the source and the text of the message between the sender and receiver
CNS13526:
適用範圍:本標準適用於往來機構間交換金融訊息,它可被用在任格通信服務或其他通信模式的訊息鑑別。本標準提供一些方法來保護在某些機關間(例:銀行間、銀行和公司客戶或政府間)批發式金融訊息的確實性,此乃藉著訊息鑑別碼(Message Authentication Code,簡稱MAC)來達成。
演算法主要分成3個步驟: 明文拆解、運算、取出運算結果。
1.將明文以每8 Byte拆解成幾個Block區塊。
2.逐一進行運算
演算步驟: Des_EN(Des_EN(P1) XOR P2) ~ n times
IV = 0x00,明文與IV或下一段進行XOR運算後再使用DES加密演算法運算。
類似Wiki介紹區塊鏈加密Cipher Block Chaining (CBC)的概念
圖片來源:wiki Cipher Block Chaining (CBC)
https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
3.取最終加密結果前8個或後8個Hex 16進位運算結果。
整理MAC演算法過程中需要使用到幾個運算方法。
在密碼演算法(Algorithm)中,有時會遇到特殊的邏輯運算,這次先介紹常用的Exclusive OR(XOR)⊕。
在C#中需要將將明文字串轉換為整數/布林/位元
再用^
就解決了,這邊我們選擇轉換為位元。
public static byte[] XOR(byte[] bHEX1, byte[] bHEX2)
{
byte[] bHEX_OUT = new byte[bHEX1.Length];
for (int i = 0; i < bHEX1.Length; i++)
{
bHEX_OUT[i] = (byte)(bHEX1[i] ^ bHEX2[i]);
}
return bHEX_OUT;
}
碰到的幾種密碼演算法將明文的組成及密文的輸出使用16進位字串(Hex string),但進行邏輯運算時則需要轉換為Byte[],為了便於使用,偷偷把轉換功能寫進Extensions。
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("-", "");
}
寫一段簡單的DES演算法,輸入金鑰及明文進行DES運算。
假設加密工作模式為CBC,初始向量=0
public static byte[] Encryption(byte[] Deskey, byte[] plainText)
{
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.CreateEncryptor(desAlg.Key, desAlg.IV);
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, ict, CryptoStreamMode.Write);
cStream.Write(plainText, 0, plainText.Length);
cStream.FlushFinalBlock();
cStream.Close();
return mStream.ToArray();
}
今天我們先花一些時間準備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
被開單了。
2011.10攝於Siena,Italy