iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 17
0
Security

看完眼眶濕濕的App開發者慘烈對抗險惡資安環境血與淚的控訴!系列 第 17

Day 17. 幫訊息申請一個簽證,訊息鑑別碼 MAC

此MAC 非此 MAC 。訊息鑑別碼 (Message authentication code , 簡稱 MAC ) 在網路通訊中,我們無法確定使用的媒介傳輸是否不可靠。因此傳輸內容完整性(integrity)校驗,在某些情景下就十分重要。

訊息鑑別碼 MAC 有如幫訊息申請一個入境簽證一樣,讓入境國家知道,這個是合法申請人,不是非法入境者

訊息鑑別碼 (MAC)

訊息鑑別碼 (Message authentication code , 簡稱 MAC ) ,訊息鑑別碼 MAC可以實現『身分識別˙』以及『訊息完整性』

1322px-MAC.svg

圖片來源-Wiki

使用共享密鑰作完整性校驗的方法常稱爲MAC(Message Authentication Code)。通常MAC在共享密鑰的雙方之間,校驗相互傳遞的信息。

簡易使用&驗證流程說明

  1. 雙方(客戶端及伺服器)選定好計算訊息鑑別碼用的演算法(MAC Algorithm)
  2. 雙方使用金鑰交換,或事前商量好共享金鑰(shared key)
  3. 客戶端將訊息使用 步驟1 和 步驟2 計算出訊息鑑別碼(MAC)

image-20201001234038903

  1. 訊息訊息鑑別碼傳送給伺服器

image-20201001234107098

  1. 伺服器收資料後將 訊息 使用 步驟1 和 步驟2 計算出訊息鑑別碼(MAC)
  2. 比對計算的訊息鑑別碼 與收到的訊息鑑別碼 是否相同

image-20201001234148851

比對相同即為正常

金鑰雜湊訊息鑑別碼 (HMAC)

上一小節提到訊息鑑別碼,有提到要選定一種演算法,因此製作MAC 方式有好幾種,包括『HMAC (hash-based mac )』、『OMAC (one-key mac) 』、『CMAC (cipher-based mac)』等。

常見使用演算法為 Hash 因此 金鑰雜湊訊息鑑別碼**(Keyed-hash message authentication code),又稱雜湊訊息鑑別碼(Hash-based message authentication code,縮寫為HMAC)

使用 HMAC

Swift

import CryptoSwift
let message = "咩"
let key = "key"
let signature = try! HMAC(key: key.bytes, variant: .sha256).authenticate(message.bytes)
print("HMAC \(signature.toHexString())")

output: HMAC 4231f7ea6d0ddf2b9029f58513dbbb8f279b7e1261facaf60043991a7fdb8812

NodeJS / ES6

import hmacSHA256 from 'crypto-js/hmac-sha256';
import Hex from 'crypto-js/enc-hex';

const message = "咩"
const key = "key"
let hmac = hmacSHA256(message , key )
const hmacHex = hmac.toString();

hmacHex : 4231f7ea6d0ddf2b9029f58513dbbb8f279b7e1261facaf60043991a7fdb8812

Android

private void generateHashWithHmac256(String message, String key) {
    try {
        final String hashingAlgorithm = "HmacSHA256"; //or "HmacSHA1", "HmacSHA512"

        byte[] bytes = hmac(hashingAlgorithm, key.getBytes(), message.getBytes());

        final String messageDigest = bytesToHex(bytes);

        Log.i(TAG, "message digest: " + messageDigest);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static byte[] hmac(String algorithm, byte[] key, byte[] message) throws NoSuchAlgorithmException, InvalidKeyException {
    Mac mac = Mac.getInstance(algorithm);
    mac.init(new SecretKeySpec(key, algorithm));
    return mac.doFinal(message);
}

public static String bytesToHex(byte[] bytes) {
    final char[] hexArray = "0123456789abcdef".toCharArray();
    char[] hexChars = new char[bytes.length * 2];
    for (int j = 0, v; j < bytes.length; j++) {
        v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}

小結

很多 API 串接,為了辨識身分以及驗證完整性,大多會使用訊息鑑別碼進行驗證

操作不會很複雜,容易實現,將產生的 MAC 放在 header 即可

就可以大幅度提高防止被串改的風險


上一篇
Day 016. 什麼都能尬的果汁機 - 雜湊 Hash
下一篇
Day 018. 聽起來好像很厲害的 - 密碼學
系列文
看完眼眶濕濕的App開發者慘烈對抗險惡資安環境血與淚的控訴!31

尚未有邦友留言

立即登入留言