funcool / buddy

Security library for Clojure
Apache License 2.0
827 stars 38 forks source link

Issue when compiling to uberjar #36

Closed freckletonj closed 8 years ago

freckletonj commented 8 years ago

When I run the following

lein ring uberjar java -cp target/fb-backend.jar clojure.main -m fb-backend.handler

I get this

Exception in thread "main" org.bouncycastle.openssl.PEMException: Unable to create OpenSSL PBDKF: PBKDF-OpenSSL SecretKeyFactory not available, compiling:(handler.clj:193:14)

Caused by: org.bouncycastle.openssl.PEMException: Unable to create OpenSSL PBDKF: PBKDF-OpenSSL SecretKeyFactory not available

This occurs on a line that uses:

(def privkey (keys/private-key "keys/privkey.pem" "XXXXXX"))

I would like to deploy a backend to heroku that uses buddy, and compojure-api, and I need to compile it down to an uberjar, or else heroku's lein takes too long grabbing libraries and booting up.

I found this "lead" but I'm not sure what to make of it: https://clojurians-log.clojureverse.org/clojure/2016-04-27.html https://github.com/middlesphere/jwt-auth-service/blob/210e797802b4bf53bfd03aa639ede54a73154f4d/src/jwt_auth_service/core.clj

Thoughts?

niwinz commented 8 years ago

The uberjar task AOT compies all the think by default and AOT is known by its issues, this is one of its. You have here two options:

(def privkey (delay (keys/private-key "keys/privkey.pem" "XXXXXX")))
;; and later when you need acces to it, just use @privkey

Defining a function that returns a privkey when it is called is also an option, but delay is more efficient because it caches it result for subsequent invocations.

niwinz commented 8 years ago

My general suggestion is not use AOT at all (only for main ns) or avoid toplevel declarations that can execute code that can not be executed at compile time...

freckletonj commented 8 years ago

the delay suggestion didn't work,

No matching method found: init for class javax.crypto.Cipher

but not using AOT did work.

Thanks, I think I'm good now! And thank you for the insanely fast response!

mpereira commented 8 years ago

@freckletonj if you'd still like to run an uberjar, you can exclude the Bouncy Castle jars from the buddy-core dependency and provide them yourself when running the uberjar.

;; project.clj
(...
  :dependencies [...
                 [buddy "1.1.0" :exclusions [buddy/buddy-core]]
                 [buddy/buddy-core "1.0.0"
                  :exclusions [org.clojure/clojure
                               org.bouncycastle/bcpkix-jdk15on
                               org.bouncycastle/bcprov-jdk15on]]
                 ...
 ...)

and then build your uberjar and run it like

java -cp $path_to_bouncy_castle_jars/bcpkix-jdk15on-1.55.jar:$path_to_bouncy_castle_jars/bcprov-jdk15on-1.55.jar:$your_uberjar $your_uberjar_main
leourbina commented 8 years ago

I'm running into the same issue. I get my private key from a function like this:

(defn pkey [auth-conf]
  (let [key-file (io/resource (:privkey auth-conf))
        passphrase (:passphrase auth-conf)]
    (keys/private-key key-file passphrase)))

I'm avoiding aot compilation by specifying

:main ^{:skip-aot true} my-project.handler

I can verify that aot compilation is not taking place from the output when I compile to an uberjar:

Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method, or the namespace has not been AOT-compiled.
Created /Users/leourbina/code/projects/my-project/target/my-project-0.1.0-SNAPSHOT.jar
Created /Users/leourbina/code/projects/my-project/target/my-project-0.1.0-SNAPSHOT-standalone.jar

I'm running the jar like this:

java -cp target/my-project-0.1.0-SNAPSHOT.jar clojure.main -m my-project.handler

When the pkey function executes I get the following trace:

Caused by: java.security.NoSuchAlgorithmException: PBKDF-OpenSSL SecretKeyFactory not available
    at javax.crypto.SecretKeyFactory.<init>(SecretKeyFactory.java:122)
    at javax.crypto.SecretKeyFactory.getInstance(SecretKeyFactory.java:160)
    at org.bouncycastle.jcajce.util.DefaultJcaJceHelper.createSecretKeyFactory(Unknown Source)
    ... 56 more

I've tried all the resources mentioned above with no luck. Any suggestions?