Best way to generate hash signature (HMAC) for XMLSerialized objects in .NET?

I need to create an HMAC for objects that I am serializing using the XMLSerializer found in the .NET framework. Each object will contain an "HMAC" property, which will contain a hash of the object values ​​themselves, but excluding the "HMAC" field. I found this question that mentions an inline solution in the CLR but doesn't elaborate on what exactly is called or how I use it?

A sample object will look something like this:

[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;
    }
}

      

The HMAC property will need to be set to serialize the entire object except the HMAC object itself. My first thoughts are creating a two-pass serialization that includes:

  • Setting xmlignore property to HMAC object in first pass
  • Serializing the entire object
  • Hashing the result and setting the value of the HMAC property
  • Re-serialization of the entire object, ready for transmission.

Is this the best way to do it? Has anyone done anything like this before and what have you found in the cleanest way of doing this?

+2


source to share


1 answer


I think you will have to serialize it twice to get the exact effect you described. One way to make this easier is to not use XmlIgnore, but instead add a public preset property (which .NET XML serialization considers specifically to programmatically control whether a similarly named property should be emitted):

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

      

What it will do is release an hmac

XML node, if one exists. A similar effect can be achieved with DefaultValueAttribute

, but I found some inconsistencies with it (e.g. null

sometimes replaced with ""

at compile time). Plus if your logic was more complex than a single breakpoint value you could handle in a property but not a static attribute.

get { return !this.IsCalculatingHmac(); }

      

This would be how I would do it if the format was to exactly match what you described.




If you have some flexibility in the output format, another approach you might want to consider is a message container that contains the message body (your current XML document) and the HMAC signature value. This way you only need to serialize the document once.

Even if the envelope was part of a large serialization document, you could implement the interface IXmlSerializable.WriteXml

on the envelope. This will allow you to carefully serialize the message to a string, then perform a hash and then write out the HMAC and message elements all in one through XmlWriter.WriteRaw

.

This would be how I would do it if performance was important.

+2


source







All Articles