I am trying to sign a payload using Dino's java callout 2. When i try to validate the same message i signed by invoking validate endpoint using same cert, its failing. I see some special characters in the signed payload . not sure if its causing the issue. anyone ran into similar problem? Here are my validation and signing configurations.
Sign method:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JavaCallout name="Java-WSSEC-Sign-7">
<Properties>
<Property name="source">message.content</Property>
<Property name="expiry">50m</Property>
<Property name="signing-method">rsa-sha1</Property>
<Property name="digest-method">sha1</Property>
<Property name="private-key">{my_private_key}</Property>
<Property name="private-key-password">mypassword</Property>
<Property name="certificate">{my_certificate}</Property>
</Properties>
<ClassName>com.google.apigee.callouts.wssecdsig.Sign</ClassName>
<ResourceURL>java://apigee-wssecdsig-20240426.jar</ResourceURL>
</JavaCallout>
Validate:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JavaCallout name="Java-WSSEC-Validate-4" continueOnError="false">
<Properties>
<Property name="debug">true</Property>
<Property name="source">message.content</Property>
<Property name="require-expiry">false</Property>
<Property name="digest-method">sha1</Property>
<Property name="signing-method">rsa-sha1</Property>
<Property name="throw-fault-on-invalid">false</Property>
<Property name="certificate">{my_certificate}</Property>
</Properties>
<ClassName>com.google.apigee.callouts.wssecdsig.Validate</ClassName>
<ResourceURL>java://apigee-wssecdsig-20240426.jar</ResourceURL>
</JavaCallout>
signature elements looks like below with carriage return escape characters.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ns1="http://ws.example.com/">
<soapenv:Header>
<wssec:Security xmlns:wssec="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsu:Timestamp wsu:Id="TS-100">
<wsu:Created>2024-11-14T22:20:19Z</wsu:Created>
<wsu:Expires>2024-11-14T23:10:19Z</wsu:Expires>
</wsu:Timestamp>
<wssec:BinarySecurityToken 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" wsu:Id="ST-101">MIIGgDCCBWigAwIBAgIQC/aTObQ4Qc7czcFp/xTgJzANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMR0wGwYDVQQDExRHZW9UcnVzdCBSU0EgQ0EgMjAxODAeFw0yNDA1MjAwMDAwMDBaFw0yNTA2MTkyMzU5NTlaMGUxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIEwVUZXhhczEPMA0GA1UEBxMGRGFsbGFzMRYwFAYDVQQKEw1Db21lcmljYSBCYW5rMR0wGwYDVQQDExRhcGkuZGV2LmNvbWVyaWNhLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANThaeoNRbtMhK5gUxTONlRFktx+czbwms1Xce1SxKxCW8Vz7LrdJpYL02zQ5U0uFxhr9DgwuVN0e4vDLDHJR8T++lgMTSRCMpww+Ucd3U2YiUgcHBRnQdeNG8rqrJGTO0bXP18B12F0nQuYLztRKscPDkl8EsZQ0g2KPhUeK89HRrULGnl8uxeQi33tmjcgJ4cVhfuHNV48y9tv0IkmERX0dv3Gg5oTqUFojSL3HFNHGQEL/GM+9peUrye4oyBdjCwhFAKx/9juOizrBkKoXhlY+eiQpDJASYjIHa90d9aebQYarpYW/bxchwGL1sK3grXCAnV9yzRvmytd7lFvIJkCAwEAAaOCAzEwggMtMB8GA1UdIwQYMBaAFJBY/7CcdahRVHex7fKjQxY4nmzFMB0GA1UdDgQWBBQE6lf0mEDlhg/RZeuIN72fP+FBtTA1BgNVHREELjAsghRhcGkuZGV2LmNvbWVyaWNhLmNvbYIUYXBpLmJsZC5jb21lcmljYS5jb20wPgYDVR0gBDcwNTAzBgZngQwBAgIwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwPgYDVR0fBDcwNTAzoDGgL4YtaHR0cDovL2NkcC5nZW90cnVzdC5jb20vR2VvVHJ1c3RSU0FDQTIwMTguY3JsMHUGCCsGAQUFBwEBBGkwZzAmBggrBgEFBQcwAYYaaHR0cDovL3N0YXR1cy5nZW90cnVzdC5jb20wPQYIKwYBBQUHMAKGMWh0dHA6Ly9jYWNlcnRzLmdlb3RydXN0LmNvbS9HZW9UcnVzdFJTQUNBMjAxOC5jcnQwDAYDVR0TAQH/BAIwADCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHYAzxFW7tUufK/zh1vZaS6b6RpxZ0qwF+ysAdJbd87MOwgAAAGPljXYPQAABAMARzBFAiEAiVT0r8AkWnttcAO3l4Ju6tqslhPJcIi06PEQojmQhssCIADVFOpwYvWqehGiAs2TvtorYVTAKvHzfTYB1HLL2nFbAHUAfVkeEuF4KnscYWd8Xv340IdcFKBOlZ65Ay/ZDowuebgAAAGPljXYRQAABAMARjBEAiBe1Csv5IaTSNUcSFRD71xLCWrGffto6VhG78j/JA49UgIgCT7k32/gJNfFCr8WV0KGk3YcQrNv51UsMqK2VgzJ/E8AdwDm0jFjQHeMwRBBBtdxuc7B0kD2loSG+7qHMh39HjeOUAAAAY+WNdhRAAAEAwBIMEYCIQDtTFTYcjVvdNDXAqkJkmOf7XZXkluypPjoPGntBRAgiAIhAOLredI/auWiUGty6XY2rYJcz1RVBQhKGfDSmH7YtJmSMA0GCSqGSIb3DQEBCwUAA4IBAQB4jyskMnpr/W8atAVMlmuF9wLUcjzCeRAhqmZnVF7RFNYyUMyxQw8t3mW3wu+/rpUBJdZlRls3KkiptPaCYfa6EjXz2OG74ZtSdwjae+ApnZQsC7nkhYqIvPLpV9gfEpgtdwOp3vSBGk3UCe8MLKUZ6GvQCkgl98OWVbEVG5blPjYOhPbGfUaIXC3wrYA+QJ8cfEr0d67XOFND+4BEsIC5szFzAJeVBFSqxzHPp4P6WMcgEL/A1hWQktqYe9tAoFlHMvaiAJql5JTr85pRkFRTs0TA0Qj2y622J4/sIK5veLNzOVPSYyx5sXRqfstLKRbXJU/m9AJ+y9R9dg/xLZXs</wssec: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="#Body-102">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>lQIvfWFF4/I1s8TG7qYBtcbp3gA=</DigestValue>
</Reference>
<Reference URI="#TS-100">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>aS9BHAuFMsHTvRq736H2PO+E2gQ=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>myrMpAUf+CHYsE1mUxViYb8t9jlZhqP8o0AJC+QUHAY4Z/fZz1HXSwDQOmLFmwTDlf4PW2RVFEPP
ePttNJHfmYrKyWjSUxwR2VjgtluqcNfIMQPfOS6cjWD67t7xmwpBT7EdO525lNeU6y/fBmcDH0MM
tK9DSyR0hkxXlBowlum0bsm0TWOhV0AN69YI4sQfnBcLusOP6YKJ0NK387CUxN4l8DdUspVML77n
puJywTD/CW5J2MM6plWfeZm3TFv2fN2G4/a2TZ6POtSvava9z4niWH7uCFeoo9VbP4FCqLBYRBzK
7fgcu2i+GuIv+xZHHhs/KnizP1F6DsFw5zU9XQ==</SignatureValue>
<KeyInfo>
<wssec:SecurityTokenReference>
<wssec:Reference URI="#ST-101" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
</wssec:SecurityTokenReference>
</KeyInfo>
</Signature>
</wssec:Security>
</soapenv:Header>
<soapenv:Body wsu:Id="Body-102">
<ns1:sumResponse>
<ns1:return>9</ns1:return>
</ns1:sumResponse>
</soapenv:Body>
</soapenv:Envelope>
Solved! Go to Solution.
@ranne wrote:
my requirement is to keep following element intact and sign with wsse namespace prefixes.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:ser="http://webservices.cashedge.com/services" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <soapenv:Header> <ser:AuthHeader> <ser:HomeID>redacted</ser:HomeID> <oas:Security> <oas:UsernameToken> <oas:Username>redacted</oas:Username> <oas:Password>redacted</oas:Password> </oas:UsernameToken> </oas:Security> </ser:AuthHeader> ...
The callout will not help you do that.
According to the standard, the Security Header must be a child of the SOAP header. In your example, you have the Security Header as a child of... some other element. That opens the signed document to signature wrapping attacks. The callout won't allow that. It's not secure.
You need to use something like this structure:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:ser="http://webservices.cashedge.com/services"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soapenv:Header>
<ser:AuthHeader>
<ser:HomeID>redacted</ser:HomeID>
</ser:AuthHeader>
<oas:Security>
<oas:UsernameToken>
<oas:Username>redacted</oas:Username>
<oas:Password>redacted</oas:Password>
</oas:UsernameToken>
</oas:Security>
...
The problem you are seeing has nothing to do with the prefix. You can use oas, wsse, wssec, dpc, or anything else you please for the prefix. The important matter is the element hierarchy. It's Envelope/Header/Security. You cannot use Envelope/Header/AuthHeader/Security .
One could argue that the Signing callout should not accept your document, with that broken hierarchy. That's a fair point. The Validate callout though, is correctly rejecting the signed document.
If you change your requirements, it will work.
BTW, the error message from the Validate callout was... not ideal in the case where you had a mis-placed Security element. I've updated the callout to be more explicit about that now. You can pull the latest and get that update.
@ranne wrote:
When i try to validate the same message i signed by invoking validate endpoint using same cert, its failing.
thanks for the question. I guess you're talking about this callout: https://github.com/DinoChiesa/Apigee-Java-WsSec-Signature-2
You said "it is failing" but didn't specify exactly what you're observing. Did you see an error message, something that provides some detail behind "it is failing"?
If the problem is a signature validation error, that can happen if:
You can try specifying "accept-thumbprints" in place of the cert during the Validate step. Remember, the signed payload includes the cert - that is the BinarySecurityToken element you see in the signed output XML. The cert is there, you don't need to provide it at Validate time. You CAN provide it, but it would be redundant. The "thumbprints" option allows you to tell the validate callout to trust a cert with a thumbprint that matches what you provide. so it's a cleaner way of specifying how to validate.
Try these things and see if it works.
Does the out-of-the-box demonstration proxy work for you? If so, what did you change, to try YOUR scenario? did you change the cert + key? Double check that you're doing that properly. Did you change the payload? That will for sure cause a signature validation error.
EDIT: oops, reading the README again, it says about the certificate for Validation:
This is required (and used) only if the KeyInfo in the signed document does not explicitly provide the Certificate.
So you need to use the "accept-thumbprints" option, for a signed payload in the format you showed. Check the README for more information. I can explain the reasoning for this to you, if you like and if it is not clear. Let me know.
Thanks for responding back to my question Dino. I was able to go past the test payload signing and validity with my own cert and own proxy. However, i am running into a new problem. my payload i need to sign is in the following format. where oas is name space is declared with wsse xsd.
When i try to sign it my callout emits following output. i put in validation callout right after signing and it fails at validation step. I assume its due to namespace declaration as oas confusing the signer. it works fine when i remove oas name space declaration and associated elements from the payload before signing. the output validates fine.
@ranne wrote:
my requirement is to keep following element intact and sign with wsse namespace prefixes.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:ser="http://webservices.cashedge.com/services" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <soapenv:Header> <ser:AuthHeader> <ser:HomeID>redacted</ser:HomeID> <oas:Security> <oas:UsernameToken> <oas:Username>redacted</oas:Username> <oas:Password>redacted</oas:Password> </oas:UsernameToken> </oas:Security> </ser:AuthHeader> ...
The callout will not help you do that.
According to the standard, the Security Header must be a child of the SOAP header. In your example, you have the Security Header as a child of... some other element. That opens the signed document to signature wrapping attacks. The callout won't allow that. It's not secure.
You need to use something like this structure:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:ser="http://webservices.cashedge.com/services"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soapenv:Header>
<ser:AuthHeader>
<ser:HomeID>redacted</ser:HomeID>
</ser:AuthHeader>
<oas:Security>
<oas:UsernameToken>
<oas:Username>redacted</oas:Username>
<oas:Password>redacted</oas:Password>
</oas:UsernameToken>
</oas:Security>
...
The problem you are seeing has nothing to do with the prefix. You can use oas, wsse, wssec, dpc, or anything else you please for the prefix. The important matter is the element hierarchy. It's Envelope/Header/Security. You cannot use Envelope/Header/AuthHeader/Security .
One could argue that the Signing callout should not accept your document, with that broken hierarchy. That's a fair point. The Validate callout though, is correctly rejecting the signed document.
If you change your requirements, it will work.
BTW, the error message from the Validate callout was... not ideal in the case where you had a mis-placed Security element. I've updated the callout to be more explicit about that now. You can pull the latest and get that update.
Much appreciated. Thank you Dino. i see the issue now. Unfortunately my requirements cant be modified as we are trying to migrate from a legacy gateway to apigee where client and the target cant accommodate any changes to the payload. Do you think , If I rewrite the signing library using same bouncy castle where i would ignore existing defintion of known name spaces and just append wsse element under header it would work? i see in your source code you are first checking if there is a known element. i am hoping to use your code as a reference but rewrite whole thing from scratch. would it have any licensing issues?
One last question, the signature is generating XML escape characters, 
 as below
<SignatureValue>qye5wAIQ4hj65M3FBsYgKQm6TE66xJMk+pvLk8aGNmOC8R919KLZKJ+Ch3o93i2WghlwlWah2/7S
 LXecwut809kbk0M/ZiaSd+VoH1E9PfE6kN6leQzYZE6TylvHiG5qMtkHV8PTRrnIb3YyIWIjh+Sl
 /OdCfVU49gou/gMIGxw0Zak9QC5HMhTj1ZN4Luy2FyliNGb6VaKYySbSFkQhuoj6X0O7N9m8Gaxf
 qHm+8HdkntKfXR4SjZDAteZTIfC/PZ3Ivv+aHMbnjyGQSFJ6WEMHGrEpa+ENmJKRuYei2lCbAwtq
 CuizOjoZq72iNi9/9zgnglaNmE9bmTVIBkVdcQ==</SignatureValue>
my target server team is complaining it may be also causing issues. i communicated to them it should not be an issue. can you please confirm ?
Great. Thanks again for your quick response and help !
Hi @ranne
I introduced a new flag to the signature Validate callout - ignore-security-header-placement
. If you set it to true in the policy config, it will allow the structure you described earlier, in which the WS-Sec Security header is not a child of the SOAP header.
Get version 20241120 of the callout for this feature. The configuration looks like this:
<JavaCallout name='Java-WSSEC-Validate-Example' continueOnError='true'>
<Properties>
<Property name='source'>message.content</Property>
<Property name='digest-method'>sha1</Property>
<Property name='signing-method'>rsa-sha1</Property>
<!-- this property is new -->
<Property name='ignore-security-header-placement'>true</Property>
<Property name='accept-thumbprints'>...whatever...</Property>
</Properties>
<ClassName>com.google.apigee.callouts.wssecdsig.Validate</ClassName>
<ResourceURL>java://apigee-wssecdsig-20241120.jar</ResourceURL>
</JavaCallout>
Great. Thank you for your help. This worked like charm and it passes validation 🙂