I’m trying to sign a simple soap message. The message looks like this:
<?xml version="1.0" encoding="utf-8"?>
<e:Envelope xmlns:e="http://schemas.xmlsoap.org/soap/envelope/">
<e:Header />
<e:Body>
<Data>someData</Data>
</e:Body>
</e:Envelope>
By no means I’m an expert in network and security stuff. As far as I understand, the result should look something like:
<?xml version="1.0" encoding="utf-8"?>
<e:Envelope xmlns:e="http://schemas.xmlsoap.org/soap/envelope/">
<e:Header>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
....
<Reference URI="#signedContent">
....
</Signature>
</e:Header>
<e:Body id="signedContent">
<Data>someData</Data>
</e:Body>
</e:Envelope>
So to my understanding the signature goes into the header, and the signature reference points to the body. I’ve put the signature node into the header by calling
xmlAddChild(xmlDocGetRootElement(doc)->children, signNode);
However I don’t know how to tell the library to sign the body. Do I have to place the id attribute in the body by myself, or should I let the library do it? The library isn’t very well documented (or maybe the functions make sense, but not for someone like me). Which functions do I need to call next (I’m using the x509 example as a basis: https://www.aleksey.com/xmlsec/api/xmlsec-examples-sign-x509.html#xmlsec-example-sign3). Probably I should create the reference node like this:
xmlNodePtr refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha256Id,
NULL, (const xmlChar*)"signedContent”, NULL);
…but I’m not very sure at all. I see that there are other functions like xmlSecTmplReferenceAddTransform. The examples on the xmlsec webpage call this with xmlSecTransformEnvelopedId, but I don’t need enveloped, perhaps I should call it with something else?.
This is exactly what happens, when you don't read the FAQ of the library. First of all - no need to dynamically create a signature template. If you build your SOAP manually like I do, it's more than enough to make it a literal like this:
The next step is to pass it to xmlsec. As you can see, digestValue, signedValue and x509 are left empty. I use C++, so I pass it as string, with my x509 certificate and private key from the HSM (I access it using libp11):
The error handling shouldn't be done with return strings, but again - that's just an example.