Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

WS Security Digital Signature - Failed to instantiate error

Hi @dchiesa1

Good day! 

Requesting your advise and assistance regarding this JAR for WS Security Digital Signature Verify and Sign https://github.com/DinoChiesa/Apigee-Java-WsSec-Signature-2 

I've been using it and have noticed the error "Failed to instantiate the JavaCallout Class com.google.apigee.callouts.wssecdsig.Validate" started to appear after recent update releases. 

Before and after release 1-14-0-apigee-2 the main branch dated 20241129 is working

after release 1-14-0-apigee-3 the main branch dated 20241129 is not working

due to this I stared to use the suggested branch dated 20250104 and it was working 

then after 1-14-0-apigee-4 was released all branches dated 20241129, 20240104, and 20250106 is not working. 

Requesting your advise of what could be causing the error, and kindly advise a way to resolve. 

Thank you!

0 4 197
4 REPLIES 4

OK thanks for posting a new question. It keeps the threads clean and clear.

My first suggestion is to try this branch:

https://github.com/DinoChiesa/Apigee-Java-WsSec-Signature-2/tree/remove-str-transform

This branch removes a bit of code that registers a Java Security Provider to handle STR Transforms in the signature. An STR in this case is a Security Token Reference. What Is a Security Token Reference?

from https://www.w3.org/2008/xmlsec/Drafts/transform-note/Overview-diff.html#WSS-STR-Transform

The STR Transform [WSS_STRTransform] is a way to sign tokens that are not part of the message. or, are part of the message, but are referred indirectly.

In the first case, Suppose a signature is signed with a X509 certificate, and the KeyInfo contains only the IssuerSerial of the certificate. If the signature includes a Reference to the KeyInfo, it is only signing the IssueSerial of the certificate, not the actual certificate. This is where an STR-Transform comes in - it is a transform that "resolves" token references and replaces them with actual tokens, i.e. it will replace the IssuerSerial with the actual certificate. So if this signature contains an STR-Transform, it will sign the actual certificate even though the actual certificate is not in the message.

In the second case, indirect reference, there is a ds:Reference that points to a SecurityTokenReference, which itself points to a SAML Assertion, which is in the XML document. Just WHY a signer would want to sign this way, with two hops, is a little unclear to me. Why not have the ds:Reference point directly to the SAML Assertion, which is an XML element in the document after all? But anyway, thank you, over-enthusiastic XML spec writers of the mid-2000's, that's possible in XML DSIG and WSSE. And in fact, the only examples I have that use STR-Transform show this scenario.

STR-Transform can be viewed as a combination of two transforms, because it

  • at first replaces token references by actual tokens in the nodeset
  • then canonicalizes this nodeset with the replaced references

it looks like this in the signed WS-Security document:

 

    <wsse:Security xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
           xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
           SOAP-ENV:mustUnderstand="1">

      <!-- The actual security token -->
      <wsse: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="X509-ABCD">****</wsse:BinarySecurityToken>

      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-206">
        <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-ENV"/>
          </ds:CanonicalizationMethod>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <ds:Reference URI="#id-205">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                <ec:InclusiveNamespaces
                    xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList=""/>
              </ds:Transform>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>***</ds:DigestValue>
          </ds:Reference>

          <ds:Reference URI="#STR-XYZ">
            <ds:Transforms>
              <!-- The STR Transform -->
              <ds:Transform Algorithm="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#STR-Transform">
                <wsse:TransformationParameters>
                  <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </wsse:TransformationParameters>
              </ds:Transform>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>****</ds:DigestValue>
          </ds:Reference>

        </ds:SignedInfo>
        <ds:SignatureValue>****</ds:SignatureValue>
        <ds:KeyInfo Id="KI-ABCXYZ">

          <!-- The Security Token REFERENCE -->
          <!-- This could just as easily be the actual Security Token! -->
          <wsse:SecurityTokenReference wsu:Id="STR-XYZ">
            <wsse:Reference URI="#X509-ABCD" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>

 

 

Correctly validating a signature that uses an STR-Transform requires that the validator (in this case, this Java callout) has access to the original cert, to de-reference it when validating the signature.

The one set of examples I have that use STR-Transform, apply them to SAML Assertions. As a result, the STR are not external. They are included in the XML document.

In the main branch, there is code that registers a Security Provider, specifically so it can handle the STR-Transforms. But that code isn't a general solution. It does not "resolve an external token". It is able only to resolve to a token that is present in the XML document. It's not able to fulfill an "extra hop" reference to a Security Token , by, for example, looking in an Apigee TrustStore.

This means ... the STR-Transform code that is present in the main branch is not very useful. There doesn't seem to be a need to create a signed document this way. Putting the Security Token in one place vs another, but in the same XML document. But anyway it's possible. Some oddball generators of WS-Security do it this way.  I don't know why they would. The spec allows it. 

As of Saturday, 4 January 2025, 05:52, I learned that 1-14-0-apigee-3 was rejecting the use of the the code I have in the main branch, which registers the Security provider to allow the callout to perform this less-than-generally-useful STR-Transform. There are some new permission restrictions that the engineering team added to Apigee, which caused this.

The avoidance here is to use the other branch, as I stated at the top.

If that does not work for you, Unfortunately I don't have further suggestions, other than: contact Apigee support.

Good luck!

Thank you for the info detailing the update done from the main branch. However, the current error I'm facing with both the main branch and the suggested branch https://github.com/DinoChiesa/Apigee-Java-WsSec-Signature-2/tree/remove-str-transform is that the error message received in the debug session logs +  response suggests that the Class element is not detected. I'm curious on what could be affecting the situation as prior to 1-14-0-apigee-4 the JARs are working. 

For reference of my proxy, here's what it has: 

pauljosh_1-1739332529604.png

I have decompiled the JAR and confirmed that it contains the "Validate.Class" file being used for this scenario. Curious on what's preventing on proxy level to access the validate class.

Error in debug session logs:

pauljosh_0-1739332310682.png

 

Are you using Apigee Edge (managed) or Apigee X?  If so, You need to raise a ticket with Apigee Support. 

There may be some log messages that they can show to you, to help diagnose the problem. 

If you are using OPDK or hybrid, then, check your MP logs for more diagnostic information. 

The "Failed to instantiate" problem can occur if the class in question is not available or loadable or any dependency of that class is not available or loadable.  Therefore, just because you have Validate.class in the jar, does not mean it will succeed. 

If you are interested in pursuing this on your own, you can try some things.  As I have advised others in similar threads, make sure to include the dependencies for the Callout in the API Proxy. In my build environment, those dependencies include:

xmlsec-3.0.5.jar
commons-codec-1.17.1.jar
jakarta.xml.bind-api-4.0.2.jar
jakarta.activation-api-2.1.3.jar
woodstox-core-6.5.1.jar
bcpkix-jdk15on-1.70.jar
bcutil-jdk15on-1.70.jar
bcprov-jdk15on-1.70.jar
stax2-api-4.2.1.jar
slf4j-api-1.7.14.jar

I would start by providing all the bc*.jar files as environment-scoped resources, or ... as API proxy scoped resources. 

A callout class may yet fail to load if the class static constructor throws or fails a permissions check. If this is the problem you need to change your code. 

 

Yes, I'm using APIGEE X.

Thank you for the support and advise @dchiesa1 . Let me try the suggestion above and retest again.