Search code examples
hashxml-dsig

SignatureValue calculation for XML-DSIG


I am trying to write a method that returns a signature of an XML element for XMLDSIG using NET framework components (RSACryptoServiceProvider) in C++/CLI. Could please someone explain this excerpt from XMLDSIG specs ( http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/ ) in simpler words, for I am have very little programming and maths background and therefore have trouble undrestanding this - Or provide an excerpt form a real code as an example where this is implemented?

The SignatureValue content for an RSA signature is the base64 [MIME] encoding of the octet string computed as per RFC 2437 [PKCS1, section 8.1.1: Signature generation for the RSASSA-PKCS1-v1_5 signature scheme]. As specified in the EMSA-PKCS1-V1_5-ENCODE function RFC 2437 [PKCS1, section 9.2.1], the value input to the signature function MUST contain a pre-pended algorithm object identifier for the hash function, but the availability of an ASN.1 parser and recognition of OIDs is not required of a signature verifier. The PKCS#1 v1.5 representation appears as: CRYPT (PAD (ASN.1 (OID, DIGEST (data)))) Note that the padded ASN.1 will be of the following form: 01 | FF* | 00 | prefix | hash where "|" is concatenation, "01", "FF", and "00" are fixed octets of the corresponding hexadecimal value, "hash" is the SHA1 digest of the data, and "prefix" is the ASN.1 BER SHA1 algorithm designator prefix required in PKCS1 [RFC 2437], that is, hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14 This prefix is included to make it easier to use standard cryptographic libraries. The FF octet MUST be repeated the maximum number of times such that the value of the quantity being CRYPTed is one octet shorter than the RSA modulus.

In other words, if I am have the hash value for a certain XML element (not encoded in base64, is that right?), what do I do with it before sending it to the SignHash (in RSACryptoServiceProvider) function? I know it's in the text, but I have troubles understanding it. I don't understand "CRYPT (PAD (ASN.1 (OID, DIGEST (data))))" at all, although I understand parts of it... I don't understand the way to get the OID and then ASN and how to pad it...


Solution

  • Let me try to explain the components, and see if this gets you any closer:

    • DIGEST(data) is the hash-value you already computed
    • OID is a globally unique identifier representing the hash-algorithm used. For SHA1 this is 1.3.14.3.2.26
    • ANS.1 means ANS.1-encoding of the OID and the hash-value as an ASN.1-sequence. This means the hex-values listed in the reference, followed by the actual hash.
    • PAD means concatenating 01 FF* 01 with the ASN.1-encoded prefix and the hash to get the desired length (FF* means repeat FF an appropriate number of times, the RFC gives details)
    • CRYPT is the RSA-encryption-function

    However, I believe the signHash-function does all of this for you, you just provide the OID and the hash-value.