Python 与 Go 哈希差异
Python vs Go Hashing Differences
我有围棋程序
package main
import (
"crypto/hmac"
"crypto/sha1"
"fmt"
)
func main() {
val := []byte("nJ1m4Cc3")
hasher := hmac.New(sha1.New, val)
fmt.Printf("%x\n", hasher.Sum(nil))
// f7c0aebfb7db2c15f1945a6b7b5286d173df894d
}
还有一个 Python (2.7) 程序试图重现 Go 代码(使用 crypto/hmac
)
import hashlib
val = u'nJ1m4Cc3'
hasher = hashlib.new("sha1", val)
print hasher.hexdigest()
# d67c1f445987c52bceb8d6475c30a8b0e9a3365d
使用 hmac
模块得到了不同的结果,但仍然与 Go 代码不同。
import hmac
val = 'nJ1m4Cc3'
h = hmac.new("sha1", val)
print h.hexdigest()
# d34435851209e463deeeb40cba7b75ef
当它们对相同的输入使用相同的散列时,为什么它们打印出不同的值?
你必须确保
- 两种情况下的输入是等价的
- 两种场景下的处理方式是等同的
在这两种情况下,输入都应该是相同的二进制 blob。在您的 Python 程序中,您定义了一个 unicode 对象,并且您没有控制它的二进制表示。将 u
前缀替换为 b
,就可以了(这是在 Python 2.7 和 3 中定义字节序列的显式方法)。这不是实际问题,但最好在这里明确说明。
问题是您在 Go 和 Python 实现中应用了不同的方法。
鉴于Python是参考
在 Go 中,根本不需要导入 "crypto/hmac"
,在 Python 中,您只需构建数据的 SHA1 哈希。在 Go 中,等价的是:
package main
import (
"crypto/sha1"
"fmt"
)
func main() {
data := []byte("nJ1m4Cc3")
fmt.Printf("%x", sha1.Sum(data))
}
测试并输出:
go run hashit.go
d67c1f445987c52bceb8d6475c30a8b0e9a3365d
这将重现您的第一个 Python 片段创建的内容。
编辑:我稍微简化了 Go 代码,不让 Python 看起来更优雅。 Go 在这里也很优雅 :-).
以Go为参考
import hmac
import hashlib
data = b'nJ1m4Cc3'
h = hmac.new(key=data, digestmod=hashlib.sha1)
print h.hexdigest()
测试&输出:
python hashit.py
f7c0aebfb7db2c15f1945a6b7b5286d173df894d
这会重现您的 Go 代码段创建的内容。但是,当确实使用空消息时,我不确定 HMAC 的加密意义。
我有围棋程序
package main
import (
"crypto/hmac"
"crypto/sha1"
"fmt"
)
func main() {
val := []byte("nJ1m4Cc3")
hasher := hmac.New(sha1.New, val)
fmt.Printf("%x\n", hasher.Sum(nil))
// f7c0aebfb7db2c15f1945a6b7b5286d173df894d
}
还有一个 Python (2.7) 程序试图重现 Go 代码(使用 crypto/hmac
)
import hashlib
val = u'nJ1m4Cc3'
hasher = hashlib.new("sha1", val)
print hasher.hexdigest()
# d67c1f445987c52bceb8d6475c30a8b0e9a3365d
使用 hmac
模块得到了不同的结果,但仍然与 Go 代码不同。
import hmac
val = 'nJ1m4Cc3'
h = hmac.new("sha1", val)
print h.hexdigest()
# d34435851209e463deeeb40cba7b75ef
当它们对相同的输入使用相同的散列时,为什么它们打印出不同的值?
你必须确保
- 两种情况下的输入是等价的
- 两种场景下的处理方式是等同的
在这两种情况下,输入都应该是相同的二进制 blob。在您的 Python 程序中,您定义了一个 unicode 对象,并且您没有控制它的二进制表示。将 u
前缀替换为 b
,就可以了(这是在 Python 2.7 和 3 中定义字节序列的显式方法)。这不是实际问题,但最好在这里明确说明。
问题是您在 Go 和 Python 实现中应用了不同的方法。
鉴于Python是参考
在 Go 中,根本不需要导入 "crypto/hmac"
,在 Python 中,您只需构建数据的 SHA1 哈希。在 Go 中,等价的是:
package main
import (
"crypto/sha1"
"fmt"
)
func main() {
data := []byte("nJ1m4Cc3")
fmt.Printf("%x", sha1.Sum(data))
}
测试并输出:
go run hashit.go
d67c1f445987c52bceb8d6475c30a8b0e9a3365d
这将重现您的第一个 Python 片段创建的内容。
编辑:我稍微简化了 Go 代码,不让 Python 看起来更优雅。 Go 在这里也很优雅 :-).
以Go为参考
import hmac
import hashlib
data = b'nJ1m4Cc3'
h = hmac.new(key=data, digestmod=hashlib.sha1)
print h.hexdigest()
测试&输出:
python hashit.py
f7c0aebfb7db2c15f1945a6b7b5286d173df894d
这会重现您的 Go 代码段创建的内容。但是,当确实使用空消息时,我不确定 HMAC 的加密意义。