nagylzs
nagylzs

Reputation: 4178

Howto generate ECDSA SignatureValue for XML with python and cryptography (wsse)

I have a canonicalized XML with wsse (http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd) headers, ds:Signature and ds:SignedInfo elements (xmlns:ds="http://www.w3.org/2000/09/xmldsig#"). This XML is a SOAP request, and it needs to be signed.

I have already calculated the ECDSA digital signature of the signedinfo element, something like this:

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding, ec, rsa
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature


assert isinstance(private_key, ec.EllipticCurvePrivateKey)
bin_signature = private_key.sign(signedinfo_c14n_xml_data, ec.ECDSA(hashes.SHA256()))
r, s = decode_dss_signature(bin_signature)

I need to put this into a SignatureValue element. I think that https://datatracker.ietf.org/doc/rfc4050/ describes how it should be calculated:

The input to the ECDSA algorithm is the canonicalized representation of the dsig:SignedInfo element as specified in Section 3 of [XMLDSIG].

The output of the ECDSA algorithm consists of a pair of integers usually referred by the pair (r, s). The signature value (text value of element dsig:SignatureValue - see section 4.2 of [XMLDSIG]) consists of the base64 encoding of the concatenation of two octet-streams that respectively result from the octet-encoding of the values r and s. This concatenation is described in section E3.1 of [IEEE1363].

I'm unable to figure out how it is done. I could not find section E3.1 of [IEEE1363].

How to convert these (r, s) values (which are simple integer numbers) into a base64 encoded SignatureValue?

I have a working example XML (generated by another program) and it generates something like this:

<ds:SignatureValue>I2K/43Hf1dPNnhWKy28dHftysnrqA8n9DG0Yzmafvr8vwHfV6lHt0MNC/JD77BkjMqdyr71p+ti4 u06c8va1CA==</ds:SignatureValue>

That program is written in Java, and it uses org.apache.wss4j. It actually works (the SOAP server accepts the signature.) The signature value seems to be a base64 value, but there is a space character inside. According to base64 specs, any characters outside of the base64 alphabet are to be ignored in base64-encoded data. So it is not an error to have a space there, but it is really strange.

Upvotes: 0

Views: 90

Answers (0)

Related Questions