我使用mgo在mongo中保存结构。我希望用这个结构(和一个秘密)的散列来保存它们以确定它们是否被篡改(我不希望mongo db本身有秘密)。
目前,我通过使用gob
对结构进行序列化来对结构进行哈希处理,结构组件的排序是明确定义的。这很有效,除非我从芒果重新读取结构,事情已经发生了变化 - 确切地说,mongo中的时间值与go相比具有截断的准确性 - 因此散列不匹配。
我计划的工作就是在计算哈希值之前简单地从BSON编组和解组结构,即:
[]byte
现在,这有点迂回。
如果我能保证BSON本身始终保留结构中组件的顺序,我可以:
byte[]
哪个不那么讨厌(虽然它仍然需要两次转换为BSON)。
有什么想法吗?
答案 0 :(得分:1)
回答您的实际问题,是的,您可以信任mgo/bson
始终按照在代码中观察到的顺序封送结构字段。虽然尚未记录(issue),但这是非常有意的行为,甚至mgo本身也依赖于它。
现在,回应您的预期用法:不要这样做。事实字段处于保证顺序并不意味着二进制格式整体上是稳定的。即使是现在,已知的方法可以在不破坏现有客户端的情况下更改输出,但这会破坏其输出的哈希值。
以下是一些建议阅读,以便更好地了解您要解决的问题的来龙去脉(我是作者):
这正是解决了以任意字段和键以稳定的方式封送任意或映射的问题,以便从签名中获取稳定的散列。参考实现在Go中。
答案 1 :(得分:0)
BSON保持秩序。我会在一些简单的包装函数中做所有秘密:
type StructWrap struct{
Value bson.Raw
Hash []byte
}
func save2mgo(in interface{}){
str := StructWrap{}
orig,_err := bson.Marshal(in)
str.Value = bson.Raw{0, orig}
str.Hash = <do hash based on orig bytes>
//to save str to mgo. because Value already in bson.Raw, it will not do marshal again.
}
func unmarshal(inType interface{}){
//read from mgo
//check str.Hash here
str.Value.Unmarshal(inType)
}
希望可以帮到你。