Search code examples
xmlsoapclojure

Soap Signing in Clojure


I am working with an API that requires all SOAP calls to be signed. I have looked into the documentation from Java on how to sign SOAP calls using Programming With the Java XML Digital Signature API.

I am consistently running into the following error java.lang.IllegalArgumentException: No matching method found: newCanonicalizationMethod for class org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.

I know that the issue is with sending the parameters to the newCanonocalizationMethod. I am following the flow per Java, but I am still running into this issue.

Here is my code.

(let [fac (XMLSignatureFactory/getInstance "DOM") 
      dm (doto (.. fac (newDigestMethod (DigestMethod/SHA1) nil))) 
      bk "" 
      ref (.. fac (newReference bk dm)) 
      cm (CanonicalizationMethod/INCLUSIVE) 
      c14 C14NMethodParameterSpec 
      in (.. fac (newCanonicalizationMethod cm c14))])

Here is the full function code: I have just started the process of creating the signature section per this site: http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html

(defn create-signature
  []
  (let [fac (XMLSignatureFactory/getInstance "DOM")
        dm (doto (.. fac (newDigestMethod (DigestMethod/SHA1) nil)))
        bk ""
        ref (.. fac (newReference bk dm))
        cm CanonicalizationMethod/INCLUSIVE
        c14 C14NMethodParameterSpec
        si (..
             fac
             (newSignedInfo
               (..
                 fac
                 (newCanonicalizationMethod
                   cm
                   C14NMethodParameterSpec))
               (..
                 fac
                 (newSignatureMethod
                   (SignatureMethod/RSA_SHA1) nil))
               (.. java.util.Collections (singletonList ref))))
        ]
        ))

If you run reflect on the factory, you get this as a response:

{:name newCanonicalizationMethod,
 :return-type javax.xml.crypto.dsig.CanonicalizationMethod,
 :declaring-class
 org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory,
 :parameter-types
 [java.lang.String
  javax.xml.crypto.dsig.spec.C14NMethodParameterSpec],
 :exception-types
 [java.security.NoSuchAlgorithmException
  java.security.InvalidAlgorithmParameterException],
 :flags #{:public}}

Solution

  • The solution to this issue was to generate all of the java methods in a custom Java class. The issue was the Java method was looking for a certain type of parameter. The code says to generate it using (Java type)null, which doesn't compile in Clojure.

    I was using this website to generate the XML signing link.

    After creating the custom class, I compiled and imported into the Clojure project.

    Lesson Learned: When working with certain java classes, it is best to use pure Java instead of Java Interop.