英文:
Encoding md5 in a node compatible way
问题
我正在将一个Node服务转换为Go语言。为此,我需要一个兼容的md5哈希生成器(不用于存储密码!)。然而,在这个例子中,我一直得到不同的结果:
Node的crypto
在创建md5
时需要一个编码参数。
crypto.createHash("md5").update("1Editor’s notebook: Escaping temptation for turf145468066").digest("hex")
'c7c3210bd977b049f42c487b8c6d0463'
在Go语言中:(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
我已经追踪到问题出在Node代码的crypto.update
的编码参数上。以及字符串中包含了一个’
引号字符。如果我指定"utf8"
,它就可以工作了。
crypto.createHash("md5").update("1Editor’s notebook: Escaping temptation for turf145468066", "utf8").digest("hex")
但是:我不能更改Node代码,所以Go代码必须兼容。有什么想法吗?
英文:
I'm converting a node service to go. For this I need a compatible md5 hash (not for storing passwords!!) generator. However, in this example, I keep getting different results:
Node's crypto
takes an encoding parameter when creating md5
s.
> crypto.createHash("md5").update("1Editor’s notebook: Escaping temptation for turf145468066").digest("hex")
'c7c3210bd977b049f42c487b8c6d0463'
In 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)
}
}
Then go test test_encode.go
results in:
--- FAIL: TestFoo (0.00s)
encode_test.go:17: Got c3804ddcc59fabc09f0ce2418b3a8335 expected c7c3210bd977b049f42c487b8c6d0463
FAIL
FAIL command-line-arguments 0.006s
I've tracked it down to the encoding
parameter of crypto.update
in the node code. And the fact that the string as a ’
quote character in it. If I specify "utf8"
it works.
crypto.createHash("md5").update("1Editor’s notebook: Escaping temptation for turf145468066", "utf8").digest("hex")
BUT: I can't change the node code, so the go code has to be compatible. Any ideas on what to do?
答案1
得分: 2
如您已经注意到的:您必须将UTF8字符串转换为您的节点应用程序中使用的编码。可以使用编码包来完成这个操作,例如:
golang.org/x/text/encoding/charmap
isoString, err := charmap.ISO8859_1.NewEncoder().Bytes([]byte(stringToEncode))
考虑到字符’
在iso-8859-1中不被允许,我们可以假设您使用了不同的编码。现在您只需要找出使用的是哪种编码!
在最糟糕的情况下,您可能需要使用charmap
之外的其他包。
英文:
As you've already noted: you must convert the UTF8 string to whatever encoding is used in your node application. This can be done with encoding packages such as:
golang.org/x/text/encoding/charmap
isoString, err := charmap.ISO8859_1.NewEncoder().Bytes([]byte(stringToEncode))
Considering that the character ’
is not allowed in iso-8859-1, we can assume you have a different encoding. Now you just need to figure out which one!
And in worse case, you might have to use another package than charmap
.
答案2
得分: 2
在对Node和V8进行了大量研究后,我得出了以下结论:
require("crypto").createHash("md5").update(inputString).digest("hex");
这种写法非常危险,因为没有指定编码,输入字符串会被编码为"ASCII"。经过深入研究后,我发现这与以下代码的结果相同(在我的测试中验证过):
// toNodeASCIIString将字符串转换为与Node兼容的ASCII字符串的字节
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
}
这段代码的作用是对256取模,从而丢弃了输入字符串的很大一部分。
上述的Node示例几乎是在任何地方都可以找到的创建MD5哈希的标准代码。我没有进行验证,但我认为对于所有其他哈希函数(如SHA1、SHA256等),这种写法应该也是相同的。
我很想听听别人对于为什么这不是一个巨大的安全漏洞的看法。
英文:
After a lot of digging in node and V8 I was able to conclude the following:
require("crypto").createHash("md5").update(inputString).digest("hex");
Is pretty dangerous, as not specifying a encodes the input string as "ASCII". Which, after a lot of digging, is the equivalent (verified on a large input set from my end):
// 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
}
What is basically does is mods by 256 and forgets a large part of the input string.
The node example above is pretty much the standard and copy-pasted-everywhere way to create MD5 hashes in node. I have not checked but I'm assuming this works the same for all other hashes (SHA1, SHA256, etc).
I would love to hear someones thoughts on why this is not huge security hole.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论