I have a soap request in form of a Document (org.w3c.dom) which I want to sign according to this example that has been provided to me:
<soapenv:Envelope xmlns:mod="...." xmlns:cor="...." xmlns:soapenv="...." xmlns:sign=".....">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-security-secext-1.0.xsd">
<wsu:Timestamp xml:id="Timestamp-5293cc3c7-b69f-...22" xlmns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-security-utility-1.0.xsd">
<wsu:Created>2022-03-17T15:18:35.484Z</wsu:Created>
<wsu:Expires>2022-03-17T15:23:35.484Z</wsu:Expires>
</wsu:Timestamp>
<wsse:BinarySecurityToken xml:id="SecurityToken-192f1eb9..." EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">MIID....==</wsse:BinarySecurityToken>
<Signature xmlns="http://www.w3.org/2009/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#Timestamp-5293c3c7-b69f....22">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<DigestValue> DUOvvFgg...=</DigestValue>
</Reference>
<Reference URI="Body-89bd1994-b8b8-4b7b-a58b-593dcfd671a5">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<DigestValue>4Qd2BBAR...=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>HCRI..=</SignatureValue>
<KeyInfo>
<wsse:SecurityTokenReference xmlns="">
<wsse:Reference URI="#SecurityToken-192f1eb9-....e84" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x529-token-profile-1.0#X509v3"/>
</wsse:SecurityTokenReference>
</KeyInfo>
</Signature>
</wsse:Security>
</soapenv:Header>
<soapenv:Body xml:id="Body-89bd1994-b8b8-4b7b-a58b-593dcfd671a5">
<DownloadFileListIn>
...
</DownloadFileListIn>
</soapenv:Body>
</soapenv:Envelope>
I've created a class to sign my XML in which I use WSSecHeader to format my request as the example, but I can't accomplish what I need with just this code:
private Document signWsSec(Document doc) throws WSSecurityException {
PrivateKey privateKey = getCrypto().getPrivateKey("", null);
X509Certificate[] issuerCerts = getCrypto().getX509Certificates(null);
String id = "Ref" + UUID.randomUUID();
String referenceId = "#" + id;
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
timestamp.setTimeToLive(300);
timestamp.build();
WSSecSignature sign = new WSSecSignature(secHeader);
sign.setSignatureAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);
sign.setDigestAlgo(DigestMethod.SHA1);
return sign.build(crypto);
}
The problem is that I can't find ways to add the binary security token just right after the timestamp and i don't know how to add the information regarding Reference for timestamp and body.
My signed request with my version of the code looks like this:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="1">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-85d968e5-ec32-4fbe-8e0b-3e580d9948b8">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#id-f43b0de5-29f7-4351-83b8-b9006ab6c355">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>Yzygfp/4zjtsApPkbZKa20+mcMk=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>....=</ds:SignatureValue>
<ds:KeyInfo Id="KI-11e85606-8065-4b00-b9ba-ceb42ea6060a">
<wsse:SecurityTokenReference wsu:Id="STR-680cc1ef-5e79-4e4e-bc4f-f89c501db519">
<ds:X509Data>
<ds:X509IssuerSerial>
<ds:X509IssuerName>...</ds:X509IssuerName>
<ds:X509SerialNumber>...</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
<wsu:Timestamp wsu:Id="TS-f90d9bd3-5925-4ffd-8f28-1b51da306b4d">
<wsu:Created>2022-03-17T15:18:35.484Z</wsu:Created>
<wsu:Expires>2022-03-17T15:23:35.484Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soap:Header>
I don't know a way to make the request satisfy the specification that has been given to me and it seems like there is no documentation nor examples regarding java.
Hope you can help because I've been stuck for 2 weeks now. Thank you in advance!
I managed to solve the issue myself, the problem was with the "Encryption parts", I had to redefine the build method as follows to add them correctly to my signature:
private Document signWsSec(Document doc) throws WSSecurityException {
X509Certificate[] issuerCerts = getCrypto().getX509Certificates(null);
WSSecHeader secHeader = new WSSecHeader(doc);
secHeader.insertSecurityHeader();
WSSecTimestamp timestamp = new WSSecTimestamp(secHeader);
timestamp.setTimeToLive(300);
timestamp.build();
WSSecSignature sign = new WSSecSignature(secHeader);
sign.setX509Certificate(issuerCerts[0]);
sign.setUseSingleCertificate(true);
org.apache.xml.security.Init.init();
sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
sign.setSignatureAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);
sign.setAddInclusivePrefixes(false);
sign.setDigestAlgo(DigestMethod.SHA1);
timestamp.prependToHeader();
return build(crypto, sign, doc);
}
public Document build(Crypto cr, WSSecSignature sign, Document doc)
throws WSSecurityException {
sign.prepare(cr);
if (sign.getParts().isEmpty()) {
WSEncryptionPart timestampPart = new WSEncryptionPart("Timestamp", WSConstants.WSU_NS, "");
sign.getParts().add(timestampPart);
sign.getParts().add(WSSecurityUtil.getDefaultEncryptionPart(doc));
}
List<javax.xml.crypto.dsig.Reference> referenceList = sign.addReferencesToSign(sign.getParts());
sign.computeSignature(referenceList);
sign.appendBSTElementToHeader();
return doc;
}
PS: The order of the elements didn't matter at all.