2015-07-12 76 views
1

我正在使用mgo保存在mongo中的結構。我希望用這個結構(和一個祕密)的散列來保存它們以確定它們是否被篡改(並且我不希望mongo db本身具有這個祕密)。mgo bson marshalling是否可以保證結構組件的順序?

目前我使用gob對結構進行序列化來散列結構,這些結構組件的排序是明確定義的。這很好,除了當我重新讀取芒果結構時,事情已經發生了變化 - 準確地說,與mongo相比,mongo中的時間值被截斷了 - 因此哈希值不匹配。

我計劃的工作圍繞這僅僅是爲了編組和解組從BSON的結構計算散列之前,即:

  • 元帥結構來BSON
  • 從BSON(從而失去對時間精度
  • 解組結構)
  • 馬歇爾結構來採空區和散列結果[]byte
  • 認沽散列結構
  • 保存結構來蒙戈

現在,這是多一點迂迴。

如果我能保證的是,BSON本身始終保留在結構部件的順序,我可以:

  • 元帥結構來BSON
  • 哈希結果byte[]
  • 認沽散列結構
  • 保存struct to mongo

哪一個會更不討厭(儘管它仍然會需要兩次轉換爲BSON)。

任何想法?

+0

我不知道任何保證兩個相同值的gob編碼會產生相同的字節。 –

+0

@BravadaZadada好吧,如果不是這將是另一個使用BSON的理由(假設它是真的,否則搜索會很難) – abligh

+0

Mgo按定義順序對結構字段進行編碼,但在文檔中沒有看到任何保證順序的東西。 Mgo自己的測試假定字段按定義順序編碼。我建議向mgo提出一個問題,要求將訂單記錄在案。 –

回答

1

回答你的實際問題,是的,你可以信任mgo/bson總是按照它們在代碼中觀察到的順序編組結構域。雖然尚未記錄(issue),但這是非常有意的行爲,甚至mgo本身也依賴於它。

現在,響應您的預期用法:不這樣做。事實字段保證順序並不意味着二進制格式作爲一個整體穩定。即使現在,也有已知的方法可以在不破壞現有客戶端的情況下改變輸出,但是這會破壞輸出的散列。

下面是一些建議閱讀理解好一點,你正在試圖解決(我是作者)問題的來龍去脈:

這正是解決了以穩定的方式編組具有任意字段和鍵的任意或映射的問題,從而爲簽名獲得穩定散列的問題。參考實現在Go中。

+0

謝謝 - 這正是我的問題。目前我通過使用'structs'包以定義順序遍歷字段來手動序列化。我注意到你的規範目前沒有包含明確的序列化時間的方法,這是需要考慮的事情('go'和'gob'保持時間比'bson'更高的精度]。 – abligh

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) 
} 

希望能幫助你。

+0

你如何保證BSON保持秩序? – abligh

+0

我不想多說一些BSON。真正的問題不是編組兩次,我的解決方案適用於它。 –

相關問題