以节点兼容的方式编码md5

时间:2016-02-12 08:23:14

标签: node.js go md5

我正在转换节点服务。为此我需要一个兼容的md5哈希(不用于存储密码!!)生成器。但是,在这个例子中,我不断得到不同的结果:

节点crypto在创建md5时采用编码参数。

> crypto.createHash("md5").update("1Editor’s notebook: Escaping temptation for turf145468066").digest("hex")
'c7c3210bd977b049f42c487b8c6d0463'

在golang:(test_encode.go)

package main

import (
    "crypto/md5"
    "encoding/hex"
    "testing"
)

func TestFoo(t *testing.T) {
    const result = "c7c3210bd977b049f42c487b8c6d0463"

    stringToEncode := "1Editor’s notebook: Escaping temptation for turf145468066"
    hash := md5.Sum([]byte(stringToEncode))
    hashStr := hex.EncodeToString(hash[:])

    if hashStr != result {
        t.Error("Got", hashStr, "expected", result)
    }
}

然后go test test_encode.go导致:

--- FAIL: TestFoo (0.00s)
encode_test.go:17: Got c3804ddcc59fabc09f0ce2418b3a8335 expected c7c3210bd977b049f42c487b8c6d0463
FAIL
FAIL    command-line-arguments  0.006s

我已将其跟踪到节点代码中encoding的{​​{1}}参数。事实上,字符串作为crypto.update引用字符。如果我指定则可行。

"utf8"

但是:我无法更改节点代码,因此go代码必须兼容。关于该怎么做的任何想法?

2 个答案:

答案 0 :(得分:2)

正如您已经注意到的那样:您必须将UTF8字符串转换为节点应用程序中使用的任何编码。这可以通过编码包完成,例如:

golang.org/x/text/encoding/charmap

isoString, err := charmap.ISO8859_1.NewEncoder().Bytes([]byte(stringToEncode))

考虑到iso-8859-1中不允许使用字符,我们可以假设您有不同的编码。现在你只需要找出哪一个!

在更糟糕的情况下,您可能必须使用另一个包而不是charmap

答案 1 :(得分:2)

在节点和V8中进行了大量挖掘之后,我得出了以下结论:

require("crypto").createHash("md5").update(inputString).digest("hex");

非常危险,因为没有指定将输入字符串编码为“ASCII”。经过大量挖掘后,这是等效的(在我的最终输入集上进行验证):

// toNodeASCIIString converts a string to a byte of node compatible ASCII string
func toNodeASCIIString(inputString string) []byte {
    lengthOfString := utf8.RuneCountInString(string(inputString))
    stringAsRunes := []rune(inputString)

    bytes := make([]byte, lengthOfString)
    for i, r := range stringAsRunes {
        bytes[i] = byte(r % 256)
    }

    return bytes
}

基本上做的是mods 256并且忘记输入字符串的大部分。

上面的节点示例几乎是在节点中创建MD5哈希的标准和复制粘贴 - 无处不在的方式。我没有检查,但我假设这对所有其他哈希(SHA1,SHA256等)的工作原理相同。

我很想听听有人为什么这不是一个巨大的安全漏洞。