SOAPUI digital Signature does not validate

@DChiesa @dchiesa1  I am working on SOAP digital Signature , and I am referring code which is given by you -https://github.com/DinoChiesa/Apigee-Java-WsSec-Signature-2. When I am signing through this Java code, the signature validation working fine but when I am signing through SOAPUI, validation signature is not working. I have attached the screenshot of SOAPUI configuration. Please suggest I am doing something wrong or issue with this Java code.

@amitsrikiet 

I have attached the screenshot of trace for both the cases pass and fail.

 

soapui.PNGTrace_ValidationFail.PNGTrace_ValidationPass.PNG

Solved Solved
0 12 2,565
1 ACCEPTED SOLUTION

So only problem with signing method, no issues with validation callout, right?

My analysis showed that the SignedInfo in the signed document did not include signatures for both the Timestamp and the Body. That's insecure.

  • If the document does not include a signature on the Timestamp, then it will be susceptible to a replay attack. A malicious "man in the middle" (MITM) could intercept the message, store it, and by simply modifying the Timestamp, could present the same SOAP message again and again. The receiver, if it is trusting the unsigned Timestamp, would have no way to know that the request is "stale" or being replayed.
  • If the document does not include a signature on the Body, then the same kind of malicious MITM could modify the BODY of the message, to be whatever he wants it to be, then replay it to the receiver. The receiver, if it trusts an unsigned Body, will surely be vulnerable to forged requests.

This is why it's important to sign both the Timestamp and the Body on signed soap messages. That is what the Java callout enforces by default. You can disable that behavior (check the README for how), but in my opinion, it's a bad idea and you should not disable that behavior. You should accept the default behavior of the callout, which verifies that both the Timestamp and the Body are signed. And also verifies the currency of the Timestamp (it's not expired).

So the fix I recommend in your case is to modify your SOAPUI configuration so that both the Body and the Timestamp are signed. There is no bug in the Java callout.

View solution in original post

12 REPLIES 12

Hi, I'll see if I can help you out.

When I am signing through this Java code, the signature validation working fine but when I am signing through SOAPUI, validation signature is not working.

Are you saying that when you Sign a document through Java code and then try to validate ... through the same Java callout.... the validation works?

And ... when you sign through SOAPUI, and then try to validate through the Java callout , the validation does not work?

If that is the case, that's clear enough. Let me talk through the common reasons or causes for signature verificaiton failures.

  1. The most common reason I see for signature validation failing is a modification of the spacing in the signed document. If you "pretty print" the signed XML after the signature has been applied, adding spaces and indents into the XML document, and then try to verify the signature on that re-formatted document, the verification will fail. You must not change the document at all. (Specifically you must not change the SignedInfo element nor the referent of that element)
  2. The second most common cause of signature verification failures is that the Java policy is not configured in such a way to accept the signed document. You can configure the policy to accept rsa-sha256 or rsa-sha-1 for the signing method. You can configure the policy to accept sha1 or sha256 for the digest method. The canonicalization the callout uses is always "http://www.w3.org/2001/10/xml-exc-c14n#". In the SOAPUI configuration, You have it set to default. I don't know what that means, not sure what SOAPUI's default is here. The key identifier type can take many options (Issuer Name and Serial is but one option). And so on. Lots of other possibilities. You did not show the policy configuration you used. Check it and see. Maybe post it here and we can examine it together. Also you did not show the signed document that SOAPUI generated. If you post THAT here, that would help also.
  3. The third most common cause of problems is key disagreement. Make sure you are configuring the Java policy to accept and trust the cert that is present in the signed document. And that the cert actually holds the public key, corresponding to the private key that was used to sign the document. If you are using SOAPUI to sign, then you probably have that part right.

Good luck!

EDIT Just as a sanity check, I used this as my outgoing WS-Security config in SOAPUI

screenshot-20221010-171153.png

And I configured the parts-to-sign to include Timestamp and Body - be sure to use the right namespaces there. They are

...respectively. The resulting signed document looks like this:

 

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:whatever.url">
   <soapenv: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"><wsu:Timestamp wsu:Id="TS-A5BD634E3E4A991EC116654468547491"><wsu:Created>2022-10-11T00:07:34Z</wsu:Created><wsu:Expires>2022-10-11T00:17:34Z</wsu:Expires></wsu:Timestamp><ds:Signature Id="SIG-A5BD634E3E4A991EC116654468547926" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="soapenv urn" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#id-A5BD634E3E4A991EC116654468547825"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="urn" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>sJh0DJZZ+PuHDYq2zxBlcmO2oOE=</ds:DigestValue></ds:Reference><ds:Reference URI="#TS-A5BD634E3E4A991EC116654468547491"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="wsse soapenv urn" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>SMz/tlJQzW/aezde4xXem0ei3is=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>aXAXl/bnQmUw4IkGUhXZ7GC/ckNd92XMSHJuTm51d30AUevGdYmRRIABwewabpQ1khtDdFRRHs8zgnZ71NWWsEensMiviQvW0DFBlY8XlfcvJR+nAUNdNRhoYULNiA2uVpRhghf92TBUbwrpIwoTx9XYge6nFIGEEC9plMVEIicnXqSe8p0r6Q+eYidgM8qQkjTE2BqTquEz9+IdZ8WDyFIMrc2OCITegJqo29VOhLZGP/iuR23tZ6cb9S4JgJkdzBHZA9ch+tYoUBUju7nLQHnMtc3N1iHWDYFoNMR2B0XHnfqFrWTql9HpUif7u+CI98b6grPcsHVm+M8B7Mre8Q==</ds:SignatureValue><ds:KeyInfo Id="KI-A5BD634E3E4A991EC116654468547763"><wsse:SecurityTokenReference wsu:Id="STR-A5BD634E3E4A991EC116654468547794"><wsse:KeyIdentifier 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">MIIDczCCAlugAwIBAgIEelQdkTANBgkqhkiG9w0BAQsFADBqMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExETAPBgNVBAcTCEtpcmtsYW5kMRQwEgYDVQQKEwtHb29nbGUsIExMQzEPMA0GA1UECxMGQXBpZ2VlMRQwEgYDVQQDEwtEaW5vIENoaWVzYTAeFw0yMjEwMTAyMzU3MTlaFw0yMzAxMDgyMzU3MTlaMGoxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJXQTERMA8GA1UEBxMIS2lya2xhbmQxFDASBgNVBAoTC0dvb2dsZSwgTExDMQ8wDQYDVQQLEwZBcGlnZWUxFDASBgNVBAMTC0Rpbm8gQ2hpZXNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl8uWhbIFcPLOboKhZl/46czFMgYFJ9/VivBmb/+IAiTr1SWvzILjz0UTEmQz+hE+ySkIklfExHtTNREsgqqq+wHrV/g9/JaQa0s+bmgfIV/MyDMZUefh5cQZFiOUjsYiP660/83ZD3vaeL5+kLE5V3ZDXY4WX4UucEZbOoXQkkBtOYCjfuM1EtfQtv5LA6KpJC9l5E6NysMa7MxQ+Y7FhS1nIb+Dcp9LMFdOojqmxNkTHi540sH0VwLsi+O4tjaY41Ol93J7lkdpuTTezeBSc328u7GGXtn6f6Lx3WYfhCcCAzdfPtD+8MsOWS7rkQ8Z9A+Q9xFpJjb2Z7wFpmfcUQIDAQABoyEwHzAdBgNVHQ4EFgQUUM073/CWdR3SPVZDycaBzzIVCc0wDQYJKoZIhvcNAQELBQADggEBAAP87O+0++wu5AMNFXm/fdXzSyI0oS97Wwf3BhGxiyeC539kQuPLLp7rduyrnUBfrg+oU250X8qt2duOFX2JmbIwXb0DUuG4YGJHtAo7/EK/R38lNVqTj+UqmhVXk767uAIJZq6FRIxHnZPX9TDDt+nkd0YbwouTxYHIT18S8hcPouJucYK4fHeSJW3AdlaGNgIHhNLFBMIEoZw7kWE++ZuncUKNq2lSVoutUJdUiFvEPALwBea0u6/Gd2OXWf4pmkIgRfVqyWjiklsNmIbrRfzWJLKMsM4UTpblLoD0YbH7LojL7CX6UE/lmC+N66mChjneZLPv9UmKzXpunDJzf8E=</wsse:KeyIdentifier></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature></wsse:Security></soapenv:Header>
   <soapenv:Body wsu:Id="id-A5BD634E3E4A991EC116654468547825" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <urn:ApplicationUpdateRequest>
         <urn:SessionID>hello</urn:SessionID>
         <urn:ApplicationID>28728</urn:ApplicationID>
         <urn:ProductCode>123</urn:ProductCode>
      </urn:ApplicationUpdateRequest>
   </soapenv:Body>
</soapenv:Envelope>

 

Notice I have not inserted newlines into the Header element, nor have I pretty-printed any of that. This is important! Signatures are sensitive to spaces and newlines in the XML, specifically in the SignedInfo element and in the elements that are being signed - Timestamp and Body in this case.

The corresponding configuration for the WS-Security Signature validation policy is like this:

 

<JavaCallout name='Java-WSSEC-Validate-4' continueOnError='true'>
  <Properties>
    <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='accept-thumbprints'>0542c43794bd41375ae2abde5f390049900ff889</Property>
  </Properties>
  <ClassName>com.google.apigee.callouts.wssecdsig.Validate</ClassName>
  <ResourceURL>java://apigee-wssecdsig-20220916.jar</ResourceURL>
</JavaCallout>

 

That "accept-thumbprints" is the SHA1 thumbprint of the cert in the soapui keystore.

If I do all of this, then... it works. The Apigee policy successfully validates the signature on the signed document that has been generated by SOAPUI.

Thanks for your quick reply.

I think I am also trying to sign same way in SOAPUI as you are doing but still the error is same. Please find the below code snippet , so you can get more insight.

Keys-

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage name="AM-KeyAndCert">
    <AssignVariable>
        <Name>my_certificate</Name>
        <Value>
     -----BEGIN CERTIFICATE-----
MIIDSzCCAjOgAwIBAgIISbqp4r2sAMMwDQYJKoZIhvcNAQELBQAwHjELMAkGA1UE
BhMCSU4xDzANBgNVBAMMBkFQSUdFRTAeFw0yMjA5MjYxMTIzMTlaFw0yMzA5MjYx
MTIzMTlaMB4xCzAJBgNVBAYTAklOMQ8wDQYDVQQDDAZBUElHRUUwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDELeWIJjJmJtMknjrRslIqgaamSp9I1Uop
e8wgyN2xBsXiE+emp1e4yH6wz/fTFbW9t3Md9mxEDdKWT0D1TXi53+YnVPOEE50w
POeRYR6mBxwR1y4+JmOUnvi2lZwQFC09bqQ4RSCIaYBGPaG/g81/XnN8E/3c26EH
BPtbEdApwiUmXqlNu9T6qvoDjlN1jOr80mun5EqG3d17o6EzD/yL6nSmRKe5YqMC
cpQDjByqN+wuuQatO2XgGbkeQDxxknW9kP6dv1JZtLKojoPpJDqa+2+MBvJZcuLA
6BJ2v/ReAE7kfnh2juVDxiHo51c5beKNddZQXPQamDGeCh3bvov7AgMBAAGjgYww
gYkwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUI3X73I3SKY/pR8qrFvaqXqRLfz4w
TQYDVR0jBEYwRIAUI3X73I3SKY/pR8qrFvaqXqRLfz6hIqQgMB4xCzAJBgNVBAYT
AklOMQ8wDQYDVQQDDAZBUElHRUWCCEm6qeK9rADDMAsGA1UdDwQEAwICvDANBgkq
hkiG9w0BAQsFAAOCAQEAGZa7JvKuqgZtLOY83TVpLXc609/3ePjET2X7tmYDh4YT
41SaYZnNbLgvihkHmvZNsqYBdB4oKUQm0+LaGd1EYEzEIq7WZ6WM2XhuFDnZrItS
Y+AKDquoUhEaSGQphHPTPm1TPAspkcpH/c9mWNhvA1q0xfPih27Rz+ujD+lNqVUM
u5wWMEt2e+HELv2b01D7VDT7+g4lzj3TdVIW5rMzOAmA+fCz13Wu7KvAj5B8iGcz
pijIDUevusUjuC8NjmTIwrmmyKiMh28/Iic3jVrViP37aVtk/lYZ2qSRlP/q+JIY
9ojz3O/brF3xa2q7flJa8SAQMv834W3pA+1nYMJc1g==
-----END CERTIFICATE-----
    </Value>
    </AssignVariable>
    <AssignVariable>
        <Name>my_private_key</Name>
        <Value>
        -----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDELeWIJjJmJtMk
njrRslIqgaamSp9I1Uope8wgyN2xBsXiE+emp1e4yH6wz/fTFbW9t3Md9mxEDdKW
T0D1TXi53+YnVPOEE50wPOeRYR6mBxwR1y4+JmOUnvi2lZwQFC09bqQ4RSCIaYBG
PaG/g81/XnN8E/3c26EHBPtbEdApwiUmXqlNu9T6qvoDjlN1jOr80mun5EqG3d17
o6EzD/yL6nSmRKe5YqMCcpQDjByqN+wuuQatO2XgGbkeQDxxknW9kP6dv1JZtLKo
joPpJDqa+2+MBvJZcuLA6BJ2v/ReAE7kfnh2juVDxiHo51c5beKNddZQXPQamDGe
Ch3bvov7AgMBAAECggEBAK/7lBoMWc21KleA8bbGxlqHL52g9z54xyxrd3Q5fFWf
g8gInxeqqlCC2tN13BSpNv1XIZdRRVHPLIfV1Km4s4HaTjYeSMzEY4+wMvMBMmMx
oYaHh14NRes+qFHx56uszeB77ijkKgj0yzM3em+4ppGJgwNdU6/Z/Zu0Zl8NnbS2
eBvEdHXS9NbNsdgCuLotxfhy6ZU5fi+0z08xrG9RiRApHZJ2QnK4tnRBAK7kBwlW
DFIfMp8KNmfgtOWo6bw7+ByGt+ROckTJPvgcGfN556H/ps4Adqj4AoH0R83GnGos
/lWu2g5+YdQDCmgB5t2eFVR6BAYxh7PeZGxYTScQygECgYEA59ycVtI0u5MouR2C
3EG4q2nfAZfcF1Xsh/YTo4jANIfzEK804QPca6Xahpt5Hh2tBujbQLRQy1OExEhg
RNvjjA1F4g15m5PChjMhfOWzqxxHRKqzJWFDy54S159STbGBV5dlnx1XgPnCQ9Vn
kY23l8dWE/Tj15RPHtX8Y2Pzq3sCgYEA2JpOSqtcIpE0esnTRa3q+mOYqrD11dfh
aN9+41nm4433xCGdRoa52LnTZl57h0GhzToKp/XP+V84geJdRjr40waYeu3vjb1s
Cg1o+jsDIKgH6wlJieMEq9m5+MrgfJR4cxHsVrDV2ZakOUxJ9uDkwk1Q78GYqhmf
j5Gpub04eYECgYAzeeEjzWtzsYo6/vhMmjK7q7edDPAKJkNrNBDMH9I8V2p5a8yb
oFXReHL5q47KRuBhRlVXGjFN0u8I/OCSqRbtwwye0UsMZVOso7FtnzmyZYbVEejQ
BbYdgKzCPlbxdNU4cx5WoxcIRWsB0GE8CXCXO+Q6bgYfmIewWuW70zcH/QKBgQCd
VwmEKBIXcg8DGtSDiyBjnjFp3H3XRqgQvDi6AbY8mgXezOQoNPmPOv0bIYrt53kX
URAojeDzLn4nqz1CJNhWwjXFJk2bUnvGmZMmIfPVpvmJfAeVR/k+tDvpQ8Xp+Re9
zsk09+N/2XOVw5r+4MKLegpO/vxco5xKd+8oYxFBAQKBgBRxC/nJY2xGRd9IDDwt
ZcZPYptQEZ7cHuhzeH63f38QxBEhyRRFh49nhjXr09lxmzrfcuOnZDd3NVF+tVHl
ATbD0m+C9gScxIdkf+sRQQv859hE53GuD4U0n9nR/MTzgypaDMG2qXFBXVdarWom
EKtPWW49IsOUQQdXUUZN3UF3
-----END PRIVATE KEY----- 
    </Value>
    </AssignVariable>
</AssignMessage>

Sign Signature-

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JavaCallout name="Java-XMLDSIG-Sign">
    <Properties>
        <Property name="source">message.content</Property>
        <Property name="output-variable">message.content</Property>
        <Property name="private-key">{my_private_key}</Property>
        <Property name="certificate">{my_certificate}</Property>
        <Property name="key-identifier-type">issuer_serial</Property>
        <Property name="private-key-password">pankaj</Property>
    </Properties>
    <ClassName>com.google.apigee.callouts.wssecdsig.Sign</ClassName>
    <ResourceURL>java://apigee-wssecdsig-20220916.jar</ResourceURL>
</JavaCallout>

Verify Signature-

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JavaCallout name="Java-WSSEC-Validate">
    <Properties>
        <Property name="source">message.content</Property>
        <Property name="certificate">{my_certificate}</Property>
        <Property name="require-expiry">false</Property>
        <Property name="accept-thumbprints">4feade38f5e3849a3284e093070ff59cbcc5aaff</Property>
        <Property name="throw-fault-on-invalid">false</Property>
        <Property name="digest-method">sha1</Property>
        <Property name="signing-method">rsa-sha1</Property>
        <Property name="key-identifier-type">issuer_serial</Property>
    </Properties>
    <ClassName>com.google.apigee.callouts.wssecdsig.Validate</ClassName>
    <ResourceURL>java://apigee-wssecdsig-20220916.jar</ResourceURL>
</JavaCallout>

 

Thanks

Pankaj

Hi Pankaj

still the error is same.

I am not clear. What are you specifically observing? You showed 2 policies, one for signing, one for verifying. Which one is causing an error? What is the error you see? What do you expect to see?

Are you saying that when you generate a signed Document with the Sign callout, you cannot verify that signed document with the Verify callout?  Have you followed the examples given in the repo?  There are working examples of documents you can sign, and signed documents you can verify. Are you able to run those examples, with the given example proxy bundle?  Do the scenarios as described in the README work? 

Hi,

Verify one is causing error. When

Case-1

I am signing through the Java code both the policies are working means sign and validation.

Case-2

When I am signing document in SOAPUI and then doing validation through Java, then its causing issue.

ok great - 

First thing I see: you are using rsa-sha256 and sha256 in SOAPUI for the signing method and digest method. In the configuration for the Validate callout in Apigee, you are using rsa-sha1 and sha1 for those values.  The Validate will not work. you need those values to be what the SOAPUI has generated. 

Second, are you sure that the certificate you have specified in the Apigee AssignMessage policy is the same one that is being used by SOAPUI ?

Can you show the signed Document that SOAPUI generates?

Here is the new SOAPUI config, the previous one is the old one. I tried with this new one but didn't work.

 

Sign Message-

<soapenv:Envelope xml
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:examples:helloservice" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv: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"><wsu:Timestamp wsu:Id="TS-0B942919A14B5D54561665503681653152"><wsu:Created>2022-10-11T15:54:41.653Z</wsu:Created><wsu:Expires>2022-10-11T16:54:41.653Z</wsu:Expires></wsu:Timestamp><ds:Signature Id="SIG-0B942919A14B5D54561665503681646151" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="soapenv urn xsd xsi" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#id-0B942919A14B5D54561665503681640150"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="urn xsd xsi" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>UEyEqfj6BKUjeFk65poDCZwblXs=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>L9rNNEYmklXmV+FLtK1OT+j7Mj82i4iwvaOmDLxwqe1PxH1yrWK/uHoPGxpHXDB/7rsXhmi6IwhYWWWE2MVWnguo4DWAy2a3MIwrtZ5oWDOsPHUyB5h0xnGUwPBYjx2fHDRBgGNmf1I+dga4vtcOfGjJLdJbwX84N+5Z4B0H7Vuhq8y6+3WJgGb/ifNgrfNj2RBDNfIBtjLZimXcVJWNU5knLP/MZjRk/W0AAaWmvgzn3uua3RJoNLkK8FdCAEaQsBKL5rIkieANILTZ2Z3SWv6Gd5i/bT8NGj5I9UW6ChDK6YMsZHHYEtAHzTuX+E4lta2bYPF1+0nStKLR+XAHqA==</ds:SignatureValue><ds:KeyInfo Id="KI-0B942919A14B5D54561665503681640148"><wsse:SecurityTokenReference wsu:Id="STR-0B942919A14B5D54561665503681640149"><wsse:KeyIdentifier 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">MIIDSzCCAjOgAwIBAgIISbqp4r2sAMMwDQYJKoZIhvcNAQELBQAwHjELMAkGA1UEBhMCSU4xDzANBgNVBAMMBkFQSUdFRTAeFw0yMjA5MjYxMTIzMTlaFw0yMzA5MjYxMTIzMTlaMB4xCzAJBgNVBAYTAklOMQ8wDQYDVQQDDAZBUElHRUUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDELeWIJjJmJtMknjrRslIqgaamSp9I1Uope8wgyN2xBsXiE+emp1e4yH6wz/fTFbW9t3Md9mxEDdKWT0D1TXi53+YnVPOEE50wPOeRYR6mBxwR1y4+JmOUnvi2lZwQFC09bqQ4RSCIaYBGPaG/g81/XnN8E/3c26EHBPtbEdApwiUmXqlNu9T6qvoDjlN1jOr80mun5EqG3d17o6EzD/yL6nSmRKe5YqMCcpQDjByqN+wuuQatO2XgGbkeQDxxknW9kP6dv1JZtLKojoPpJDqa+2+MBvJZcuLA6BJ2v/ReAE7kfnh2juVDxiHo51c5beKNddZQXPQamDGeCh3bvov7AgMBAAGjgYwwgYkwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUI3X73I3SKY/pR8qrFvaqXqRLfz4wTQYDVR0jBEYwRIAUI3X73I3SKY/pR8qrFvaqXqRLfz6hIqQgMB4xCzAJBgNVBAYTAklOMQ8wDQYDVQQDDAZBUElHRUWCCEm6qeK9rADDMAsGA1UdDwQEAwICvDANBgkqhkiG9w0BAQsFAAOCAQEAGZa7JvKuqgZtLOY83TVpLXc609/3ePjET2X7tmYDh4YT41SaYZnNbLgvihkHmvZNsqYBdB4oKUQm0+LaGd1EYEzEIq7WZ6WM2XhuFDnZrItSY+AKDquoUhEaSGQphHPTPm1TPAspkcpH/c9mWNhvA1q0xfPih27Rz+ujD+lNqVUMu5wWMEt2e+HELv2b01D7VDT7+g4lzj3TdVIW5rMzOAmA+fCz13Wu7KvAj5B8iGczpijIDUevusUjuC8NjmTIwrmmyKiMh28/Iic3jVrViP37aVtk/lYZ2qSRlP/q+JIY9ojz3O/brF3xa2q7flJa8SAQMv834W3pA+1nYMJc1g==</wsse:KeyIdentifier></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature></wsse:Security></soapenv:Header>
   <soapenv:Body wsu:Id="id-0B942919A14B5D54561665503681640150" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <urn:sayHello soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <firstName xsi:type="xsd:string">Pankaj</firstName>
      </urn:sayHello>
   </soapenv:Body>
</soapenv:Envelope>
ns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:examples:helloservice" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv: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"><wsu:Timestamp wsu:Id="TS-0B942919A14B5D54561665503681653152"><wsu:Created>2022-10-11T15:54:41.653Z</wsu:Created><wsu:Expires>2022-10-11T16:54:41.653Z</wsu:Expires></wsu:Timestamp><ds:Signature Id="SIG-0B942919A14B5D54561665503681646151" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="soapenv urn xsd xsi" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#id-0B942919A14B5D54561665503681640150"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="urn xsd xsi" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>UEyEqfj6BKUjeFk65poDCZwblXs=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>L9rNNEYmklXmV+FLtK1OT+j7Mj82i4iwvaOmDLxwqe1PxH1yrWK/uHoPGxpHXDB/7rsXhmi6IwhYWWWE2MVWnguo4DWAy2a3MIwrtZ5oWDOsPHUyB5h0xnGUwPBYjx2fHDRBgGNmf1I+dga4vtcOfGjJLdJbwX84N+5Z4B0H7Vuhq8y6+3WJgGb/ifNgrfNj2RBDNfIBtjLZimXcVJWNU5knLP/MZjRk/W0AAaWmvgzn3uua3RJoNLkK8FdCAEaQsBKL5rIkieANILTZ2Z3SWv6Gd5i/bT8NGj5I9UW6ChDK6YMsZHHYEtAHzTuX+E4lta2bYPF1+0nStKLR+XAHqA==</ds:SignatureValue><ds:KeyInfo Id="KI-0B942919A14B5D54561665503681640148"><wsse:SecurityTokenReference wsu:Id="STR-0B942919A14B5D54561665503681640149"><wsse:KeyIdentifier 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">MIIDSzCCAjOgAwIBAgIISbqp4r2sAMMwDQYJKoZIhvcNAQELBQAwHjELMAkGA1UEBhMCSU4xDzANBgNVBAMMBkFQSUdFRTAeFw0yMjA5MjYxMTIzMTlaFw0yMzA5MjYxMTIzMTlaMB4xCzAJBgNVBAYTAklOMQ8wDQYDVQQDDAZBUElHRUUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDELeWIJjJmJtMknjrRslIqgaamSp9I1Uope8wgyN2xBsXiE+emp1e4yH6wz/fTFbW9t3Md9mxEDdKWT0D1TXi53+YnVPOEE50wPOeRYR6mBxwR1y4+JmOUnvi2lZwQFC09bqQ4RSCIaYBGPaG/g81/XnN8E/3c26EHBPtbEdApwiUmXqlNu9T6qvoDjlN1jOr80mun5EqG3d17o6EzD/yL6nSmRKe5YqMCcpQDjByqN+wuuQatO2XgGbkeQDxxknW9kP6dv1JZtLKojoPpJDqa+2+MBvJZcuLA6BJ2v/ReAE7kfnh2juVDxiHo51c5beKNddZQXPQamDGeCh3bvov7AgMBAAGjgYwwgYkwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUI3X73I3SKY/pR8qrFvaqXqRLfz4wTQYDVR0jBEYwRIAUI3X73I3SKY/pR8qrFvaqXqRLfz6hIqQgMB4xCzAJBgNVBAYTAklOMQ8wDQYDVQQDDAZBUElHRUWCCEm6qeK9rADDMAsGA1UdDwQEAwICvDANBgkqhkiG9w0BAQsFAAOCAQEAGZa7JvKuqgZtLOY83TVpLXc609/3ePjET2X7tmYDh4YT41SaYZnNbLgvihkHmvZNsqYBdB4oKUQm0+LaGd1EYEzEIq7WZ6WM2XhuFDnZrItSY+AKDquoUhEaSGQphHPTPm1TPAspkcpH/c9mWNhvA1q0xfPih27Rz+ujD+lNqVUMu5wWMEt2e+HELv2b01D7VDT7+g4lzj3TdVIW5rMzOAmA+fCz13Wu7KvAj5B8iGczpijIDUevusUjuC8NjmTIwrmmyKiMh28/Iic3jVrViP37aVtk/lYZ2qSRlP/q+JIY9ojz3O/brF3xa2q7flJa8SAQMv834W3pA+1nYMJc1g==</wsse:KeyIdentifier></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature></wsse:Security></soapenv:Header> <soapenv:Body wsu:Id="id-0B942919A14B5D54561665503681640150" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <urn:sayHello soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <firstName xsi:type="xsd:string">Pankaj</firstName> </urn:sayHello> </soapenv:Body> </soapenv:Envelope>

 

SOAPUI Config-

NewSoapUIConfig.PNG

ok thanks, that's helpful.

I see from that signed document that there is a wsu:Timestamp in the header, with "Created" and "Expires" child elements. Here is the pretty-printed version that allows you to see it clearly:

 

<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:urn="urn:examples:helloservice"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv: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">
      <wsu:Timestamp wsu:Id="TS-0B942919A14B5D54561665503681653152">
        <wsu:Created>2022-10-11T15:54:41.653Z</wsu:Created>
        <wsu:Expires>2022-10-11T16:54:41.653Z</wsu:Expires>
      </wsu:Timestamp>
      <ds:Signature Id="SIG-0B942919A14B5D54561665503681646151"
                    xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      ...

 

But the signature does not sign that Timestamp. I can determine that by examining the SignedInfo element from the signed document. Again, pretty-printed:

 

...
      <ds:Signature Id="SIG-0B942919A14B5D54561665503681646151"
                    xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
            <ec:InclusiveNamespaces PrefixList="soapenv urn xsd xsi"
                                    xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
          </ds:CanonicalizationMethod>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <ds:Reference URI="#id-0B942919A14B5D54561665503681640150">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                <ec:InclusiveNamespaces PrefixList="urn xsd xsi"
                                        xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
              </ds:Transform>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>UEyEqfj6BKUjeFk65poDCZwblXs=</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
   ...

 

The list of ds:Reference elements indicates WHAT is signed within a signed document. In your document there is a single ds:Reference element, and the URI attribute refers to the Body element.

By default the WS-Security signature validation callout requires that both Body and Timestamp are signed. The signed document would show two ds:Reference elements , with different URI attributes, pointing to the Timestamp and the Body elements, respectively. This is a best practice, as described by this WS-Attacks.org article . Requiring a signed timestamp at signature-verification time is important because it prevents replay attacks. All crypto is vulnerable to attack, given enough time and compute resources. The timestamp in a WS-Security header is specifically intended to prevent attacks that take a long time. The timestamp element in your document says that it's good for 1 hour. (That seems like an overly-long time, in my opinion. It should not need to have a lifetime of more than a few minutes, unless you're storing that XML in a queue for later processing.) So the callout is telling you "signature did not verify" because the timestamp is not signed.

There are two ways to avoid this "signature did not verify" problem:

  1. RECOMMENDED. Add the Timestamp to the parts-to-sign when you specify the WS-Security Outgoing configuration in SOAPUI. It should use Element name Timestamp and namespace URI http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd

    soapui-config-parts.png

  2. configure the Java callout to NOT require that the timestamp be signed. This is not recommended as it weakens your security protections. So I strongly advise against it. But you can do so by specifying the required-signed-elements property to be "body" in the policy configuration. This is also described in the README.

There IS a bug in the callout, in that it does not TELL YOU that the reason the signature was rejected was because of the unsigned Timestamp element. I will fix that so that the callout sets the wssec_error context variable indicating the reason for the failure. I've updated the callout to version 202210112 with this fix. Thanks for your patience and assistance in working through this.

Hi,

Let me try with this configuration, I will update you soon. So only problem with signing method, no issues with validation callout, right? Means the java code will work out for all scenarios. 

So only problem with signing method, no issues with validation callout, right?

My analysis showed that the SignedInfo in the signed document did not include signatures for both the Timestamp and the Body. That's insecure.

  • If the document does not include a signature on the Timestamp, then it will be susceptible to a replay attack. A malicious "man in the middle" (MITM) could intercept the message, store it, and by simply modifying the Timestamp, could present the same SOAP message again and again. The receiver, if it is trusting the unsigned Timestamp, would have no way to know that the request is "stale" or being replayed.
  • If the document does not include a signature on the Body, then the same kind of malicious MITM could modify the BODY of the message, to be whatever he wants it to be, then replay it to the receiver. The receiver, if it trusts an unsigned Body, will surely be vulnerable to forged requests.

This is why it's important to sign both the Timestamp and the Body on signed soap messages. That is what the Java callout enforces by default. You can disable that behavior (check the README for how), but in my opinion, it's a bad idea and you should not disable that behavior. You should accept the default behavior of the callout, which verifies that both the Timestamp and the Body are signed. And also verifies the currency of the Timestamp (it's not expired).

So the fix I recommend in your case is to modify your SOAPUI configuration so that both the Body and the Timestamp are signed. There is no bug in the Java callout.

Thanks @dchiesa1 , its working with "required-signed-elements" property correctly. Thank you so much for your support.

@dchiesa1 

Update-

The signature element can come in two ways in request 

1) Envelop-Header-Security-Signature

2)Envelop-Header-Signature

but this java callout for validation only looking for signature element inside security but as per standard signature element directly come in header part as well.

Is this possible you can modify java code that looks for both ways. Please suggest.


@pankajrai9026 wrote:

but as per standard signature element directly come in header part as well.


To which standard do you refer? I reviewed  the WS-Security specification in some detail. This is what it says in relation to signatures: 

This document defines syntax and semantics of signatures within a <wsse:Security> element.  This document does not constrain any signature appearing outside of a <wsse:Security> element.

Ok, so that says that in the context of a Signature that is compliant with the WS-Security standard, the Signature element is ALWAYS a child of the wsse:Security element.  This is contrary to what you stated. 

Also in that document,  I could not find a specific explicit statement saying that the wsse:Security header must always be a child of the soap:Header element. But, I did find repeated informal statements referring to the wsse:Security header block .

ws-security-header-block.png

Also, every example shows the wsse:Security element as a child of the soap:Header.

ws-sec-header-block-2.png

All of this implies that the wsse:Security element is always a child of soap:Header.

Now, if you have a document that has soap:Envelope/soap:Header/Signature , that is perfectly fine.  XML is extensible, any application can organize the elements in the way it sees fit.  But such a signature is not compliant with the WS-Security standard.  The Java callout we are discussing here is used for Signatures that comply with the WS-Security standard. 

If you have a Signature that complies with XMLDSIG on a document, this WS-Security Java callout is probably not the right thing to use. There is a separate callout for Apigee that can generate and validate signatures that conform to XMLDSIG.  Look here.  But this latter callout has some restrictions - it works by generating or validating signatures that apply to the entire document.  And the Signature element is always a child of root.  If you have Envelope/Header/Signature, then you may need to create your own callout that works with that non-standard scheme. 

If I am overlooking a standard, please inform me.