WSS4j element order when signing a SOAP message

I am implementing a Java web service client that uses wss4j 1.6.8 for WS-Security (to be more certain, I need to sign a SOAP message). The server side requires that the requests have the following structure:

<Envelope> <Header> <wsse:Security mustUnderstand="1"> **<wsu:Timestamp wsu:Id="Timestamp-913ca68e-05ed-44e1-9d6c-b2f293da5a1d"> <wsu:Created>2012-12-21T11:37:31Z</wsu:Created> <wsu:Expires>2012-12-21T11:42:31Z</wsu:Expires> </wsu:Timestamp>** <wsse:BinarySecurityToken> MIID2jCCAsKg... </wsse:BinarySecurityToken> <Signature xmlns="http://www.w3.org/2000/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-913ca68e-05ed-44e1-9d6c-b2f293da5a1d"> <Transforms> <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestValue>jdVY1HaDLusqO9UcxASE/GQHxyo=</DigestValue> </Reference> <Reference URI="#Body-e344eef1-2d8a-42d0-8a30-361ee61a8617"> <Transforms> <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestValue>L60mQelZERvXgLEgWlW50uJNqEA=</DigestValue> </Reference> </SignedInfo> <SignatureValue> NmgACUqrYYc/Kp/F... </SignatureValue> <KeyInfo> <wsse:SecurityTokenReference xmlns=""> <wsse:Reference URI="#SecurityToken-3f054298-711c-4090-95c3-105e1093f3ba" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/> </wsse:SecurityTokenReference> </KeyInfo> </Signature> </wsse:Security> </S:Header> <S:Body> Body content... </S:Body> </Envelope> 

My solution signs the document (both body elements and timestamps), but for some reason wss4j places the timestamp element at the bottom of the section, after <wsse:BinarySecurityToken> and <Signature> elements, which is not the case. Please check the sources that signed the contract:

  public static SOAPMessage signSoapMessage(SOAPMessage message, PrivateKey signingKey, X509Certificate signingCert, char[] passphrase) throws WSSecurityException { final String alias = "signingKey"; final int signatureValidityTime = 3600; // 1hour in seconds WSSConfig config = new WSSConfig(); config.setWsiBSPCompliant(false); WSSecSignature builder = new WSSecSignature(config); builder.setX509Certificate(signingCert); builder.setUserInfo(alias, new String(passphrase)); builder.setUseSingleCertificate(true); builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE); try { Document document = DanskeUtils.toDocument(message); WSSecHeader secHeader = new WSSecHeader(); secHeader.setMustUnderstand(true); secHeader.insertSecurityHeader(document); WSSecTimestamp timestamp = new WSSecTimestamp(); timestamp.setTimeToLive(signatureValidityTime); document = timestamp.build(document, secHeader); List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>(); WSEncryptionPart timestampPart = new WSEncryptionPart("Timestamp", WSConstants.WSU_NS, ""); WSEncryptionPart bodyPart = new WSEncryptionPart(WSConstants.ELEM_BODY, WSConstants.URI_SOAP11_ENV, ""); parts.add(timestampPart); parts.add(bodyPart); builder.setParts(parts); Properties properties = new Properties(); properties.setProperty("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin"); Crypto crypto = CryptoFactory.getInstance(properties); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(null, passphrase); keystore.setKeyEntry(alias, signingKey, passphrase, new Certificate[]{signingCert}); ((Merlin) crypto).setKeyStore(keystore); crypto.loadCertificate(new ByteArrayInputStream(signingCert.getEncoded())); document = builder.build(document, crypto, secHeader); return Utils.updateSoapMessage(document, message); } catch (Exception e) { throw new WSSecurityException(WSSecurityException.Reason.SIGNING_ISSUE, e); } } 

Could you help me clarify how to reorder the elements before the document is familiar? Thanks!

+6
source share
2 answers

The WS-SEC specification states: "When elements are added to the header block, they MUST be added to existing elements."

So, if you add the timestamp first, it will be higher than any existing children in the ws header. Since you sign the message after adding the timestamp, the subscription information will be added to the header again, so it will appear above the timestamp element.

If you want the timestamp element to appear at the very top, add it to the header as the final process

+1
source

After creating the signature, you can add this line:

 timestamp.prependToHeader(secHeader); 

it will place the timestamp element above your BinarySecurityToken element.

0
source

All Articles