在一个与节点兼容的方式中对md5进行编码。

huangapple go评论104阅读模式
英文:

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 md5s.

> 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.

huangapple
  • 本文由 发表于 2016年2月12日 16:23:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/35357841.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定