mrc*_*clx 5 hash json cryptography go
我需要对JSON进行签名,但是我发现解组/编组可以更改JSON的顺序,这可能会使签名无效。
无论如何,是否有可能从JSON字符串中产生相同的哈希值?
我看过JOSE,但找不到真正散列JSON的函数。
JOSE JWS 绝对会做您想做的事,但代价是必须管理签名和验证密钥。
但我们假设您并不真正需要 JOSE 中的全部密钥管理内容和一般加密功能,并且您并不超级关心性能(因此在此过程中进行一些字符串修改是可以的)。
你可以愚蠢地解组你的 JSON 并重新编组它,然后只是散列:
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
json "encoding/json"
)
// NB These docs are strictly-speaking the same.
const DOCA = "{ \"foo\": 1.23e1, \"bar\": { \"baz\": true, \"abc\": 12 } }"
const DOCB = "{ \"bar\": { \"abc\": 12, \"baz\": true }, \"foo\": 12.3 }"
func hash(doc string) string {
// Dumb af, but it's a cheap way to specific the most generic thing
// you can :-/
var v interface{}
json.Unmarshal([]byte(doc), &v) // NB: You should handle errors :-/
cdoc, _ := json.Marshal(v)
sum := sha256.Sum256(cdoc)
return hex.EncodeToString(sum[0:])
}
func main() {
fmt.Println(DOCA)
fmt.Printf("Hash: %s\n", hash(DOCA))
fmt.Println(DOCB)
fmt.Printf("Hash: %s\n", hash(DOCB))
}
Run Code Online (Sandbox Code Playgroud)
该程序的输出(至少在 golang docker 容器中)是:
{ "foo": 1.23e1, "bar": { "baz": true, "abc": 12 } }
Hash: d50756fbb830f8335187a3f427603944c566772365d8d8e6f6760cd2868c8a73
{ "bar": { "abc": 12, "baz": true }, "foo": 12.3 }
Hash: d50756fbb830f8335187a3f427603944c566772365d8d8e6f6760cd2868c8a73
Run Code Online (Sandbox Code Playgroud)
这种方法的好处在于,以牺牲一些性能为代价,您可以免受在首先编组 JSON 时所做的任何愚蠢垃圾的影响(因此,与其他建议不同,您不必考虑您要做什么可能正在使用自定义编组器之类的东西)。当您忘记一年后代码 3.8 版本中存在这个问题、实现一些与编组顺序混乱的内容并开始破坏某些内容时,这尤其是一件大事。
当然,您始终可以将哈希添加到结果结构中,并使用映射中的额外项目再次编组。显然,如果您担心性能并正确处理错误,您希望对性能进行一些优化,但无论如何,这是一个很好的原型:-)
哦,如果你非常担心边缘情况,你也可以使用规范的 JSON来编组,因为它是专门为这种类型的使用而设计的(不过,老实说,我无法在我的文档中举出一个例子)测试 c-json 工作但 go 的默认 json 不工作的地方)。
| 归档时间: |
|
| 查看次数: |
137 次 |
| 最近记录: |