Sha256 和 URI 编码问题

Sha256 and URI encoding woes

我正在尝试将此功能从 javascript/node 移植到 racket

var crypto = require("crypto");  

function getAuthorizationTokenUsingMasterKey(verb, resourceType, resourceLink, date, masterKey) {  
    var key = new Buffer(masterKey, "base64");  

    var text = (verb || "").toLowerCase() + "\n" +   
            (resourceType || "").toLowerCase() + "\n" +   
            (resourceLink || "") + "\n" +   
            date.toLowerCase() + "\n" +   
            "" + "\n";  

    var body = new Buffer(text, "utf8");  
    var signature = crypto.createHmac("sha256", key).update(body).digest("base64");  

    var MasterToken = "master";  

    var TokenVersion = "1.0";  

    return encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + signature);  
}

```

这会获取一些字符串,将它们连接起来,为它们创建一个 sha256 哈希,最后对所有内容进行编码以表示 URI。

这是我的球拍版本,遗憾的是它没有产生与 JS 版本相同的结果。 对于一个 URI 的最后编码丢失,但我也怀疑 sha256 代码不正确。

#lang racket

(require sha)
(require threading)
(require net/base64)
(require (rename-in grommet/crypto/base64
                    (base64-encode encode)
                    (base64-decode decode)))

(define (auth-token master-key date [verb ""] [res-type ""] [res-link ""]) 

    (~>> (list verb res-type res-link date)
        (map string-downcase)
        (string-join _ "\n" #:after-last "\n")
        string->bytes/utf-8
        (hmac-sha256 (string->bytes/utf-8 master-key))
        encode
        (format "type=master&ver=1.0&sig=~a")))

(define x (auth-token "master" "Das Ist Ein Datum"))

编辑 我试图归结这个例子,这样我就可以看到哪里出了问题,这就是我得到的

;; racket
(encode (hmac-sha256 (decode "master")(string->bytes/utf-8 "payload"))) 
;; => pSfWnL7WUIpZwHmYB9JI891SgmMHJauJ3e0E/D5V46c="

//javascript
crypto.createHmac("sha256", "master").update("payload").digest("base64");  
//=> 'xlPQBpUTEnLGanhDb4ebS7DlFE2jE1d5mO6VjnqjhgI='

解决方案

(define (auth-token3 master-key date [verb ""] [res-type ""] [res-link ""])
    (let* ([! string-downcase] [->bytes string->bytes/utf-8])
        (~>> (list (! verb) "\n" (! res-type) "\n" res-link "\n" (! date) "\n\n")
            string-append*
            ->bytes
            (hmac-sha256 (base64-decode (->bytes master-key)))
            base64-encode
            (format "type=master&ver=1.0&sig=~a")
            string-trim
            uri-encode)))

您的简化示例应该是

(encode (hmac-sha256 (string->bytes/utf-8 "master")(string->bytes/utf-8 "payload")))

没有

(encode (hmac-sha256 (decode "master")(string->bytes/utf-8 "payload")))

前版本returns正确结果

一个可能的缺陷是您 (map string-downcase) 覆盖了所有文本组件,而 JS 函数没有在 resourceLink 上调用 toLowerCase。试试这个:

(define (auth-token master-key date [verb ""] [res-type ""] [res-link ""])
  (let* ([! string-downcase] [->bytes string->bytes/utf-8]
         [text/list  (list (! verb) "\n" (! res-type) "\n" res-link "\n" (! date) "\n")]
         [text/bytes (->bytes (string-append* text/list))]
         [signature  (encode (hmac-sha256 (->bytes master-key) text/bytes))])
    (string-append "type=master&ver=1.0&sig=" signature)))

JS版也是调用encodeURIComponent结束。我不知道那是做什么的,但你的代码中似乎没有任何等效项