Kong HMAC認證對接

HMAC

HMAC是一種利用密碼學中的散列函數來進行消息認證的一種機制,所能提供的消息認證包括兩方面內容:

①消息完整性認證:能夠證明消息內容在傳送過程沒有被修改。

②信源身份認證:因爲通信雙方共享了認證的密鑰,接收方能夠認證發送該數據的信源與所宣稱的一致,即能夠可靠地確認接收的消息與發送的一致。

HMAC是當前許多安全協議所選用的提供認證服務的方式,應用十分廣泛,並且經受住了多種形式攻擊的考驗。

HMAC與一般的加密重要的區別在於它具有“瞬時"性,即認證只在當時有效,而加密算法被破解後,以前的加密結果就可能被解密。

Kong配置

請求參數

參數說明

需要增加2個request header:

  • Date:當前時間(爲了方便對接,開發階段此值設定爲距當前時間1小時內),GMT格式,與北京時間相差8小時。例:Sat, 10 Oct 2020 08:10:21 GMT。(該參數除了用於參與簽名計算,更重要的作用是防止重複攻擊。假設抓包到了請求數據,包含當前日期以及認證信息,如果該日期沒有時間限制,就可以一直重複使用)
  • Authorization:hmac username="app", algorithm="hmac-sha256", headers="date request-line", signature="Vr7f7g6dzwxW6bP7dSiJutyOm8aiJl+IG5XJqyOHERU=",其中username的值由網關給出,signature爲Base64編碼後的簽名,其餘固定。

簽名算法

使用HMAC-SHA256加密算法,參數爲message和secret。secret由網關給出。僞代碼描述:

  message="date: Thu, 22 Jun 2017 17:15:21 GMT\nGET /requests HTTP/1.1"
  secret="secret"
  digest=HMAC-SHA256(message, secret)
  base64_digest=base64(digest)

message格式:

  • 如果request header的name不是request-line,追加小寫的header name,追加冒號和空格,追加值。比如date: Thu, 22 Jun 2017 17:15:21 GMT
  • 如果是request-line,追加HTTP request line
  • 多個request header中間使用\n隔開。

message參數:

  • Date:客戶端增加的參數,見參數說明,符合message格式的第一條,注意冒號和值之間有一個空格。
  • Request-Line:Request-Line=Method空格Request-URI空格HTTP-Version。例如:GET /request?a=11&b=22 HTTP/1.1
  • Request-URI:上面Request-Line的一部分,the path with the querystring。例如:url爲 https://example.com:1234/v1/movies?movie=foo,則Request-URI=/v1/movies?movie=foo

完整的message示例:date: Thu, 22 Jun 2017 17:15:21 GMT\nGET /request?a=11&b=22 HTTP/1.1

舉個例子

假設有GET請求接口地址爲:http://kong.alicontainer.com/app/hot

Date爲:Sat, 15 Oct 2020 07:40:21 GMT

則message爲:date: Sat, 15 Oct 2020 07:40:21 GMT\nGET /app/hot HTTP/1.1

signature爲:cCUTMy/11ZkyAtp+iSh1/BftKJODibZQgf4Oi8q/d9o=

異常說明

http status:401

  1. header中沒有date參數,或者date時間不合法(距當前時間5分鐘內,gmt格式,與北京時間差8小時)

    { "message": "HMAC signature cannot be verified, a valid date or x-date header is required for HMAC Authentication"}
    
  2. 簽名錯誤

    {  "message": "HMAC signature does not match"}
    

客戶端實現

客戶端當根據自己的環境使用攔截器思想,在請求即將發出前統一攔截,在header中增加認證參數,以下僅給出獲取計算signature的代碼示例。

Java版本

  /**
     * 獲取當前GMT format 時間
     *
     * @return
     */
    public static String getGMTTime() {
        DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        return dateFormat.format(Calendar.getInstance().getTime());
    }
public static String sign(String secret, String message) {
    try {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
        mac.init(secretKey);
        return Base64.encodeBase64String(mac.doFinal(message.getBytes()));
    } catch (NoSuchAlgorithmException | InvalidKeyException e) {
        throw new IllegalArgumentException("簽名錯誤:" + e.getMessage());
    }
}
public static void main(String[] args) {
    String secret = "dapeng";
    String message = "date: Sat, 10 Oct 2020 08:10:21 GMT\nGET /mock?a=1 HTTP/1.1";
    String sign = sign(secret, message);
    System.out.println(sign);//Vr7f7g6dzwxW6bP7dSiJutyOm8aiJl+IG5XJqyOHERU=
}
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>

body驗證

body數據簽名驗證需要增加另一個header:Digest,value爲:Digest: SHA-256=base64(sha256(<body>)),例如:SHA-256=RgecWaKvMqh5T79Ps93OuyZ5CZuPnZ6dTgsh5i9xJUs=

將body字符串使用sha256加密,再使用base64編碼,這裏不涉及secret。

java版本:

public static String String2SHA256(String str) {
    try {
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        byte[] hash = messageDigest.digest(str.getBytes());
        return Base64.encodeBase64String(hash);
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("簽名錯誤:" + e.getMessage());
    }
}
public static void main(String[] args) {
    Map<String, String> map = new HashMap<>(1);
    map.put("name", "123");
    String body = JSON.toJSONString(map);
    System.out.println(String2SHA256(body));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章