2009-10-26 51 views
2

我需要爲使用.NET框架中找到的XMLSerializer序列化的對象生成一個HMAC。每個對象將包含一個名爲「HMAC」的屬性,該屬性將包含該對象的值本身的散列,但不包括「HMAC」字段。我發現this question提到了CLR中的內置解決方案,但沒有詳細說明它的名稱或使用方法。在.NET中爲XMLSerialized對象生成哈希簽名(HMAC)的最佳方法?

樣本對象會是這個樣子:

[Serializable] 
[XmlRoot("request", IsNullable = false)] 
public class Request 
{ 

    [XmlElement(ElementName = "hmac")] 
    public string Hmac { get; set; } 

    [XmlElement(ElementName = "nonce")] 
    public string Nonce { get; set; } 

    [XmlElement(ElementName = "expiration")] 
    public DateTime Expiration { get; set; } 

    /* A bunch of other properties to be serialized */ 

    private Request() { } 

    public Request(string hmac, string nonce, DateTime expiration) 
    { 
     Hmac = hmac; 
     Nonce = nonce; 
     Expiration = expiration; 
    } 
} 

的HMAC屬性將需要設置爲整個對象的序列化,排除了HMAC對象本身。我的第一個想法是設立某種形式的雙通道串行化,其中涉及:

  1. 第一遍
  2. 序列化整個對象
  3. 哈希結果設定一個xmlignore屬性設置爲HMAC對象,設置HMAC屬性的值
  4. 重新序列化整個事情,準備傳輸。

這是最好的方法嗎?有沒有人做過這樣的事情,你發現什麼是最乾淨的方式?

回答

2

我想你將不得不連續兩次得到你描述的確切效果。

[XmlIgnore] 
public bool HmacSpecified 
{ 
    get { return !String.IsNullOrEmpty(this.Hmac); } 
    set { } 
} 

這將完成:爲了更輕鬆地將不使用XmlIgnore而是將一個公共的指定屬性(.NET XML序列化對待專門編程控制是否發出類似命名的特性)的一種方法僅存在hmac XML節點(如果存在)。 DefaultValueAttribute也可以達到類似的效果,但我發現它有一些不一致之處(例如null在編譯過程中有時被替換爲"")。此外,如果您的邏輯比單個定位標記值更復雜,您可以在屬性中處理它,但不能處理靜態屬性。

get { return !this.IsCalculatingHmac(); } 

這將是我會這樣做,如果格式必須完全符合你所描述的方式。


如果您在輸出格式的靈活性,你可以考慮在具有包含郵件正文的消息容器(當前的XML文檔)和HMAC簽名值的另一種方法。這樣你只需要序列化一次文檔。

即使信封是較大的序列化文檔的一部分,也可以在信封上實現一個IXmlSerializable.WriteXml接口。這將允許您仔細地將消息序列化爲一個字符串,然後執行散列,然後通過XmlWriter.WriteRaw將HMAC和消息元素一一寫入。

如果表現很重要,我會這樣做。

+0

「信封」方法是更好的方法。當然,信封想法在SOAP中很重要。 – Cheeso 2009-11-26 16:03:22