Giter VIP home page Giter VIP logo

buddy-core's Introduction

buddy-core

Travis Badge

buddy-core module is dedicated to provide a Clojure friendly Cryptographic Api.

Clojars Project

See the documentation or api reference for more detailed information.

buddy-core's People

Contributors

artenator avatar brianedwards85 avatar coltnz avatar cryptox8 avatar dannc avatar dharrigan avatar dottedmag avatar eduardomrb avatar hagmonk avatar jorinvo avatar jruusu avatar juskrey avatar leppert avatar mcfunley avatar mjosefs avatar mkaschenko avatar niwinz avatar palfrey avatar rickmoynihan avatar ryfow avatar shilder avatar sundbry avatar tmcf avatar xzj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

buddy-core's Issues

java.security.NoSuchAlgorithmException: PBKDF-OpenSSL SecretKeyFactory not available

Hi, having an exception when calling buddy from oracle-java8 to decrypt a private key with a passphrase

2016-12-05 15:50:52,424 INFO [kixi.heimdall.handler:36] - {:msg "Something went wrong", :fn "wrap-catch-exception"}
2016-12-05 16:02:22,896 ERROR [kixi.heimdall.handler:160] - 
                                                                     java.lang.Thread.run              Thread.java:  745
                                     org.eclipse.jetty.util.thread.QueuedThreadPool$3.run    QueuedThreadPool.java:  555
                                    org.eclipse.jetty.util.thread.QueuedThreadPool.runJob    QueuedThreadPool.java:  635
                                            org.eclipse.jetty.io.AbstractConnection$2.run  AbstractConnection.java:  540
                                       org.eclipse.jetty.server.HttpConnection.onFillable      HttpConnection.java:  257
                                              org.eclipse.jetty.server.HttpChannel.handle         HttpChannel.java:  310
                                                   org.eclipse.jetty.server.Server.handle              Server.java:  497
                                   org.eclipse.jetty.server.handler.HandlerWrapper.handle      HandlerWrapper.java:   97
ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle                               
                                                      ring.adapter.jetty/proxy-handler/fn                jetty.clj:   24
                                      kixi.heimdall.components.jettyserver/wrap-config/fn          jettyserver.clj:   16
                                  kixi.heimdall.components.jettyserver/wrap-components/fn          jettyserver.clj:   10
                                                                                      ...                               
                                               ring.middleware.json/wrap-json-response/fn                 json.clj:   87
                                                 ring.middleware.json/wrap-json-params/fn                 json.clj:   72
                                    ring.middleware.keyword-params/wrap-keyword-params/fn       keyword_params.clj:   35
                                           kixi.heimdall.handler/wrap-catch-exceptions/fn              handler.clj:  158
                                              kixi.heimdall.handler/wrap-record-metric/fn              handler.clj:  133
                                           kixi.heimdall.handler/wrap-record-metric/fn/fn              handler.clj:  133
                                                kixi.heimdall.handler/wrap-escape-html/fn              handler.clj:  105
                                                                 compojure.core/routes/fn                 core.clj:  156
                                                                       clojure.core/apply                 core.clj:  659
                                                                                      ...                               
                                                                   compojure.core/routing                 core.clj:  148
                                                                   compojure.core/routing                 core.clj:  151
                                                                        clojure.core/some                 core.clj: 2674
                                                                compojure.core/routing/fn                 core.clj:  151
                                                                 compojure.core/routes/fn                 core.clj:  156
                                                                       clojure.core/apply                 core.clj:  659
                                                                                      ...                               
                                                                   compojure.core/routing                 core.clj:  148
                                                                   compojure.core/routing                 core.clj:  151
                                                                        clojure.core/some                 core.clj: 2674
                                                                compojure.core/routing/fn                 core.clj:  151
                                                              compojure.core/if-method/fn                 core.clj:   27
                                                               compojure.core/if-route/fn                 core.clj:   45
                                                        compojure.core/wrap-route-info/fn                 core.clj:  126
                                                  compojure.core/wrap-route-middleware/fn                 core.clj:  122
                                                             compojure.core/make-route/fn                 core.clj:  135
                                                                  compojure.response/fn/G             response.clj:    6
                                                                    compojure.response/fn             response.clj:   33
                                                         kixi.heimdall.handler/auth-token              handler.clj:   45
                                                  kixi.heimdall.service/create-auth-token              service.clj:   78
                                                   kixi.heimdall.service/make-token-pair!              service.clj:   58
                                                 kixi.heimdall.service/make-refresh-token              service.clj:   53
                                                        kixi.heimdall.service/private-key              service.clj:   31
                                           kixi.heimdall.service/absolute-or-resource-key              service.clj:   27
                                                     kixi.heimdall.service/private-key/fn              service.clj:   31
                                                              buddy.core.keys/private-key                 keys.clj:   96
                                                        buddy.core.keys/read-pem->privkey                 keys.clj:   60
                                                                                      ...                               
                              org.bouncycastle.openssl.PEMEncryptedKeyPair.decryptKeyPair                               
               org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder$1$1.decrypt                               
                                       org.bouncycastle.openssl.jcajce.PEMUtilities.crypt                               
                                      org.bouncycastle.openssl.jcajce.PEMUtilities.getKey                                (repeats 2 times)
                  org.bouncycastle.jcajce.util.DefaultJcaJceHelper.createSecretKeyFactory                               
                                                javax.crypto.SecretKeyFactory.getInstance    SecretKeyFactory.java:  160
                                                     javax.crypto.SecretKeyFactory.<init>    SecretKeyFactory.java:  122
java.security.NoSuchAlgorithmException: PBKDF-OpenSSL SecretKeyFactory not available
 org.bouncycastle.openssl.PEMException: Unable to create OpenSSL PBDKF: PBKDF-OpenSSL SecretKeyFactory not available

Code in question

(:require [buddy.core.keys :as ks])
...
(ks/private-key key-file (:passphrase auth-conf))

This started happening with the current build of Oracle java

$ java -version
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)

As far as I can tell, the exact same code with same dependencies (and buddy 1.0.0 or 1.2.0) worked on an older version of Hotspot, but stopped working recently.

Little Help Recreating This?

Hello,

First off, I want to say thank you for all of your hard work on buddy. It is much appreciated.

I have some code that I'd like to convert to buddy, and I was wondering if you (or one of the fine people reading this) could help me out:

(ns toy.crypto
  (:require [buddy.core.bytes :as bytes]
            [buddy.core.crypto :as crypto]
            [buddy.core.codecs :as codecs]
            [buddy.core.kdf :as kdf]
            [buddy.core.nonce :as nonce]
            [buddy.core.padding :as padding]
            [buddy.core.hash :as hash]
            [buddy.hashers :as hashers]
            [clojure.data.codec.base64 :as b64]
            [clojure.string :as str]
            [byte-streams]
            [byte-transforms]
            [outpace.config :refer (defconfig!)])
  (:import [java.io
            ByteArrayInputStream
            ByteArrayOutputStream]
           [javax.crypto Cipher
            SecretKeyFactory]
           [javax.crypto.spec
            IvParameterSpec
            PBEKeySpec
            SecretKeySpec]))

(def salt "this is some salt")
(def passcode "this is a passcode")

(defonce key-factory (SecretKeyFactory/getInstance "PBKDF2WithHmacSHA1"))

(defonce key-spec (PBEKeySpec. (.toCharArray passcode)
                               (.getBytes salt)
                               100000 ;; iterations
                               256)) ;; AES256

(defonce aes-key (-> key-factory
                     (.generateSecret key-spec)
                     (.getEncoded)
                     (SecretKeySpec. "AES")))

(defn decrypt [payload]
  (let [[iv msg] (str/split payload #"--")

        iv-spec (-> (byte-transforms/decode iv :base64)
                    IvParameterSpec.)

        cipher (Cipher/getInstance "AES/CBC/PKCS5Padding") ;; I think I read that PKCS5Padding is synonymous with PKCS7Padding when used in this context, but I am not 100% sure on that.
        _ (.init cipher Cipher/DECRYPT_MODE aes-key iv-spec)]

    (.doFinal cipher (byte-transforms/decode msg :base64))))

(defn encrypt [msg]
  (let [cipher (Cipher/getInstance "AES/CBC/PKCS5Padding")

        _ (.init cipher Cipher/ENCRYPT_MODE aes-key)

        params (.getParameters cipher)
        iv (.getIV (.getParameterSpec params IvParameterSpec))
        encrypted-msg (.doFinal cipher (.getBytes msg "UTF-8"))]

    (format "%s--%s"
            (String. (b64/encode iv) "UTF-8")
            (String. (b64/encode encrypted-msg) "UTF-8"))))

Any help would be much appreciated!

buddy creates EC keypairs when namespaces are required, slowing down startup

I was wondering why my clojure app is sometimes taking ~10min to start up on this virtual machine I'm using. Looking at jstack (see below) shows that it's stuck in org.bouncycastle.crypto.generators.ECKeyPairGenerator.generateKeyPair(), which gets run when buddy.core.jwk.keys.ec is required, which is required (transitively) by e.g. buddy.sign.jwt.

The key generation is probably slow because entropy is depleted, but I haven't been able to verify this yet.

I think a suitable fix would be to (delay ...) the curve creation until they're actually used. I can provide a PR if this sounds reasonable.

jstack output

Thread 23662: (state = IN_NATIVE)
 - java.io.FileInputStream.readBytes(byte[], int, int) @bci=0 (Interpreted frame)
 - java.io.FileInputStream.read(byte[], int, int) @bci=4, line=255 (Interpreted frame)
 - sun.security.provider.SeedGenerator$URLSeedGenerator.getSeedBytes(byte[]) @bci=19, line=539 (Interpreted frame)
 - sun.security.provider.SeedGenerator.generateSeed(byte[]) @bci=4, line=144 (Interpreted frame)
 - sun.security.provider.SecureRandom$SeederHolder.<clinit>() @bci=20, line=203 (Interpreted frame)
 - sun.security.provider.SecureRandom.engineNextBytes(byte[]) @bci=21, line=221 (Compiled frame)
 - java.security.SecureRandom.nextBytes(byte[]) @bci=5, line=468 (Compiled frame)
 - org.bouncycastle.util.BigIntegers.createRandom(int, java.security.SecureRandom) @bci=29 (Interpreted frame)
 - org.bouncycastle.util.BigIntegers.createRandomBigInteger(int, java.security.SecureRandom) @bci=7 (Interpreted frame)
 - org.bouncycastle.crypto.generators.ECKeyPairGenerator.generateKeyPair() @bci=22 (Interpreted frame)
 - org.bouncycastle.jcajce.provider.asymmetric.ec.KeyPairGeneratorSpi$EC.generateKeyPair() @bci=26 (Interpreted frame)
 - buddy.core.keys.jwk.ec$get_curve.invokeStatic(java.lang.Object) @bci=60, line=87 (Interpreted frame)
 - buddy.core.keys.jwk.ec$get_curve.invoke(java.lang.Object) @bci=3, line=83 (Interpreted frame)
 - buddy.core.keys.jwk.ec__init.load() @bci=386, line=91 (Interpreted frame)
 - buddy.core.keys.jwk.ec__init.<clinit>() @bci=15 (Interpreted frame)

certificates from auth0 for rs256 JWT signing don't seem to be able to be loaded as public keys

Here's a certificate that I pulled from auth0 and tried to load as a public key for use with JWT and rs256 using buddy.core.keys/public-key.

This is the error that I see:

java.lang.ClassCastException: org.bouncycastle.cert.X509CertificateHolder cannot be cast to org.bouncycastle.asn1.x509.SubjectPublicKeyInfo

-----BEGIN CERTIFICATE-----
MIIDADCCAeigAwIBAgIJXJPtHecVkezqMA0GCSqGSIb3DQEBBQUAMCcxJTAjBgNV
BAMTHGNvbnRhY3Qtc3VwcG9ydC5hdS5hdXRoMC5jb20wHhcNMTYwODMxMDgwNjIz
WhcNMzAwNTEwMDgwNjIzWjAnMSUwIwYDVQQDExxjb250YWN0LXN1cHBvcnQuYXUu
YXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp6er9vY8
Ud5FI6bMHLYWUQxFO4jGi8SBh4I3zhOyYgnY1QVLbcJcLhlAN1SpP0xYCcp6SI7e
gLsHRNgiLyFzmJ4FQ6yU8suuz7+kHfMMdRgBMVf0luzQ9sx2LcqBK2cUGJADtclT
RtOnIDYkz9hVB5EaZv2pIR7pM3HLLGj5mv6mJju1848aqb3W8/bbK9amhGvhF0zJ
lA2GBk/lQy7a0bRR8dA95rTu3c8SfwAF9aCPbVngsY/O1VuoWoTVcbL0bs+mWvF2
qDxAVFLpk8KU6X49W5IEDi2XKEG3ogDMTEzBprVb7DLhOnPL6Hd5oolsice6hGLn
by2hgU4AIutphQIDAQABoy8wLTAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBQkEEs+
j9VMN4JqxUu0l1ARs5BKOjANBgkqhkiG9w0BAQUFAAOCAQEADb/gA2sFQxbvRMqn
rwV88lB++NJ3Ck7QRw+7wDyeQGMjHQbtkF3xnID695R8j50Ie/Yz1SyzoT4+/Mw4
9RZWOAVGOvZ7ktewXkpHLK0cyCmaBd1J3LJRThH8mMBHoF3XnSKoYTXlUd12Ix+W
Tf+LiRKmJ7RkUkJMy5fi57iMyiFdpHq8/5+EZqwMecWFwkHosxOaM2jrYmvFQ/3I
ZONMj5NB/+fUA2n8JL31DiWEixNyRBjJJlUV8OdKhQYw4k7dMpbYSJ/SyzEFqHKv
MNIRWv8HBGMCeyQfNHhy3/pkeC5AVFVsHTJCwOhPwDdJJpuz66XqiXs7bWQ7hYst
FMj/iA==
-----END CERTIFICATE-----

SecretKey parsing

i recently tried to use buddy.sign together with buddy.core.keys to generate a JWT for google service account.

google service account you just get a JSON with a privatekey as string, passing it to buddy.core.keys/str->privatekey didnt work. using another lib did the job.

check out https://github.com/xsc/pem-reader for enhancing buddy.core.keys ;)

keys.clj: read-pem->pubkey fails if read object is of type X509CertificateHolder

Hi,
I'm using a public key signing certificate for with auth0 when the service is set to use public / private key pair. In this scenario the buddy.core.keys/read-pem->pubkey method fails as the object returned from the PEMParser readObject is of type: org.bouncycastle.cert X509CertificateHolder which the JcaPEMKeyConverter cannot use directly, getSubjectPublicKeyInfo must be called on the X509CertificateHolder first.

To support these X509 certificate public keys I use a modified read-pem->pubkey as follows:

;; buddy/core/keys.clj
;; also add import (org.bouncycastle.cert X509CertificateHolder)
(defn- read-pem->pubkey
  [path-or-reader]
  (with-open [reader (io/reader path-or-reader)]
    (let [parser    (PEMParser. reader)
          keyinfo   (.readObject parser)
          converter (doto (JcaPEMKeyConverter.)
                      (.setProvider "BC"))]
      (if (instance? X509CertificateHolder keyinfo)
        (.getPublicKey converter (.getSubjectPublicKeyInfo keyinfo))
        (.getPublicKey converter keyinfo)))))

This is similar to how the read-pem->privkey does instance? checked on the object returned by the PEMParser. I am happy to make a pull request for this if desired but as I am relatively unfamiliar with the buddy codebase I wanted to see if the proposed solution is stylistically compatible with buddy or the solution should be coded more like read-pem->privkey:

  • use a cond instead of if, particularly if there are other cases to consider
  • rename keyinfo to obj

Thanks. Buddy is working really well for us.

Error EncryptionException

This works ok on Linux but fails on Windows and I don't know why:

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

The privkey file is the same and it seems to be ok.

java.lang.ExceptionInInitializerError
        at clojure.main.<clinit>(main.java:20)
Caused by: org.bouncycastle.openssl.EncryptionException: exception using cipher
- please check password and data., compiling:(backend.clj:17:14)
        at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3628)
        at clojure.lang.Compiler$DefExpr.eval(Compiler.java:439)
        at clojure.lang.Compiler.eval(Compiler.java:6787)
        at clojure.lang.Compiler.load(Compiler.java:7227)
        at clojure.lang.RT.loadResourceScript(RT.java:371)
        at clojure.lang.RT.loadResourceScript(RT.java:362)
        at clojure.lang.RT.load(RT.java:446)
        at clojure.lang.RT.load(RT.java:412)
        at clojure.core$load$fn__5448.invoke(core.clj:5866)
        at clojure.core$load.doInvoke(core.clj:5865)
        at clojure.lang.RestFn.invoke(RestFn.java:408)
        at clojure.core$load_one.invoke(core.clj:5671)
        at clojure.core$load_lib$fn__5397.invoke(core.clj:5711)
        at clojure.core$load_lib.doInvoke(core.clj:5710)
        at clojure.lang.RestFn.applyTo(RestFn.java:142)
        at clojure.core$apply.invoke(core.clj:632)
        at clojure.core$load_libs.doInvoke(core.clj:5749)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.core$apply.invoke(core.clj:632)
        at clojure.core$require.doInvoke(core.clj:5832)
        at clojure.lang.RestFn.invoke(RestFn.java:436)
        at appweb_api.controllers.auth$eval20083$loading__5340__auto____2008
.invoke(auth.clj:1)

Uncaught exception in buddy.core.keys causes 500 internal error when a token is invalid

Exception is org.bouncycastle.crypto.InvalidCipherTextException: checksum failed

This can occur if the token passed in cannot be decrypted. I think the fix is probaly easy, but I'm not sure how this should be reported back to the application so that you can distinguish a bad token from a filed authenticaiton.

To reproduce this issue, you can use the jwe example.

  1. query the server and get a token
  2. Re-start the server. As the jwe token uses a random secret, it will generate a new secret key
  3. Attempt to authenticate using the previously obtained token. As the key is now different, decryption will fail and the exception is thrown. This ends up being a 500 Internal server error.

My setup is using immutant/undertow configuration rather than a basic ring/jetty setup, but I don't think this should make a difference.

A possible approach would be to issue a 498 token expired/invalid error?

498 Token expired/invalid (Esri)
Returned by ArcGIS for Server. A code of 498 indicates an expired or otherwise invalid token

Codecs/bytes->str does not produce correct utf8 strings according to PostgreSQL

Passing the output of

(buddy.core.codecs/bytes->str (nonce/random-nonce 16)

to a field of type text in PostgreSQL results in the following error:

org.postgresql.util.PSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0x00

Using bytes->hex works, but that seems like a non-optimal way to go about solving the issue.

It seems like every run of (buddy.core.codecs/bytes->hex (nonce/random-nonce 16)) starts with the same sequence 000001549b, or as emacs interprets (buddy.core.codecs/bytes->str (nonce/random-nonce 16)) "^@^@^A".

Decrypting a compressed JWT consistently fails

Hopefully I'm doing something wrong here :) I was having trouble decrypting a JWT that was encrypted via https://github.com/jwt/ruby-jwe ... however I managed to get the same error to occur directly with buddy:

;; openssl genrsa 2048 > private-foobar.pem
;; openssl rsa -in private.pem -out public.pem -outform PEM -pubout
(-> {:a "b"}
    (buddy.sign.jwt/encrypt (keys/public-key "public-foobar.pem") {:alg :rsa-oaep :enc :a128cbc-hs256})
    (buddy.sign.jwt/decrypt (keys/private-key "private-foobar.pem") {:alg :rsa-oaep :enc :a128cbc-hs256}))

This returns the hash back successfully.

Adding :zip true causes the following failure:

1. Unhandled java.lang.ClassCastException
   clojure.core$bytes cannot be cast to [B

                      REPL:   38  buddy.util.deflate/uncompress
                      REPL:   38  buddy.util.deflate/uncompress
                      REPL:   80  buddy.sign.jwe/decode-payload
                      REPL:   77  buddy.sign.jwe/decode-payload
                      REPL:  252  buddy.sign.jwe/decrypt
                      REPL:  232  buddy.sign.jwe/decrypt
                   jwt.clj:   97  buddy.sign.jwt/decrypt
                   jwt.clj:   93  buddy.sign.jwt/decrypt
                      REPL:   78  blip-api.authentication/eval25585
                      REPL:   76  blip-api.authentication/eval25585
             Compiler.java: 6927  clojure.lang.Compiler/eval
             Compiler.java: 6890  clojure.lang.Compiler/eval
                  core.clj: 3105  clojure.core/eval
                  core.clj: 3101  clojure.core/eval
                  main.clj:  240  clojure.main/repl/read-eval-print/fn
                  main.clj:  240  clojure.main/repl/read-eval-print
                  main.clj:  258  clojure.main/repl/fn
                  main.clj:  258  clojure.main/repl
                  main.clj:  174  clojure.main/repl
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  646  clojure.core/apply
                  core.clj:  641  clojure.core/apply
                regrow.clj:   18  refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   87  clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn
                  AFn.java:  152  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  core.clj:  646  clojure.core/apply
                  core.clj: 1881  clojure.core/with-bindings*
                  core.clj: 1881  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   85  clojure.tools.nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   55  clojure.tools.nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  222  clojure.tools.nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
    interruptible_eval.clj:  190  clojure.tools.nrepl.middleware.interruptible-eval/run-next/fn
                  AFn.java:   22  clojure.lang.AFn/run
   ThreadPoolExecutor.java: 1142  java.util.concurrent.ThreadPoolExecutor/runWorker
   ThreadPoolExecutor.java:  617  java.util.concurrent.ThreadPoolExecutor$Worker/run

This was in my REPL environment which is as follows:

;; Connected to nREPL server - nrepl://localhost:51290
;; CIDER 0.13.0snapshot (package: 20160602.809), nREPL 0.2.12
;; Clojure 1.8.0, Java 1.8.0_71

^:deprecated to mean function deprecation, not algorithm deprecation

^:deprecated attribute is set on some functions, such as buddy.core.hash/sha1, which constitute a part of public interface of this library.

While it is useful to discourage people from using deprecated cryptographical algorithms in new code, interoperability requirements with existing systems guarantee that these functions will be used for a long time, so ^:deprecated attribute, which ought to signify deprecation of the code, not of the algorithms, is not really warranted.

Can these attributes be removed? They get in a way when, say, eastwood is in use.

buddy-core issuing shadowing warnings with clojure 1.9

After updating to Clojure 1.9.0-alpha11, I've started seeing the following warning:

WARNING: bytes? already refers to: #'clojure.core/bytes? in namespace: buddy.core.bytes, being replaced by: #'buddy.core.bytes/bytes?

https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L5292-L5297

(defn bytes?
  "Return true if x is a byte array"
  {:added "1.9"}
  [x] (if (nil? x)
        false
        (-> x class .getComponentType (= Byte/TYPE))))

https://github.com/funcool/buddy-core/blob/master/src/buddy/core/bytes.clj#L22-L29

(defn bytes?
  "Test if a first parameter is a byte
  array or not."
  [x]
  (if (nil? x)
    false
    (= (Class/forName "[B")
       (.getClass x))))

Looks like the clojure.core/bytes? and buddy.core.bytes/bytes? are functionally equivalent.

[Bug] Illegal access in openjdk 12

Did a search on this repository and wasn't able to find anything matching "illegal access". Just tried updating a project to use openjdk 12, and it looks like bouncy castle isn't playing nice.

WARNING: Illegal reflective access by org.bouncycastle.jcajce.provider.drbg.DRBG (file:<path-to-my-project>) to constructor sun.security.provider.Sun()
	at org.bouncycastle.jcajce.provider.drbg.DRBG.findSource(Unknown Source)
	at org.bouncycastle.jcajce.provider.drbg.DRBG.<clinit>(Unknown Source)
	at org.bouncycastle.jcajce.provider.drbg.DRBG$Mappings.configure(Unknown Source)
	at org.bouncycastle.jce.provider.BouncyCastleProvider.loadAlgorithms(Unknown Source)
	at org.bouncycastle.jce.provider.BouncyCastleProvider.setup(Unknown Source)
	at org.bouncycastle.jce.provider.BouncyCastleProvider.access$000(Unknown Source)
	at org.bouncycastle.jce.provider.BouncyCastleProvider$1.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:310)
	at org.bouncycastle.jce.provider.BouncyCastleProvider.<init>(Unknown Source)
	at buddy.core.dsa__init.load(Unknown Source)
	at buddy.core.dsa__init.<clinit>(Unknown Source)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:415)
	at clojure.lang.RT.classForName(RT.java:2207)
	at clojure.lang.RT.classForName(RT.java:2216)
	at clojure.lang.RT.loadClassForName(RT.java:2235)
	at clojure.lang.RT.load(RT.java:453)
	at clojure.lang.RT.load(RT.java:428)
	at clojure.core$load$fn__6824.invoke(core.clj:6126)
	at clojure.core$load.invokeStatic(core.clj:6125)
	at clojure.core$load.doInvoke(core.clj:6109)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invokeStatic(core.clj:5908)
	at clojure.core$load_one.invoke(core.clj:5903)
	at clojure.core$load_lib$fn__6765.invoke(core.clj:5948)
	at clojure.core$load_lib.invokeStatic(core.clj:5947)
	at clojure.core$load_lib.doInvoke(core.clj:5928)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invokeStatic(core.clj:667)
	at clojure.core$load_libs.invokeStatic(core.clj:5985)
	at clojure.core$load_libs.doInvoke(core.clj:5969)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)

This is when building the project using lein uberjar. I'm using the following dependencies in the file that is invoking buddy functions:

[buddy.sign.jwt :as jwt]
[buddy.hashers :as bh]

Security vulnerability: CVE-2023-33201

The Bouncy Castle dependency in buddy-core has the vulnerability CVE-2023-33201. As explained in the description here, Bouncy Castle did not properly check X.500 names for wildcards, leading to potential LDAP injection attacks by including special characters in these names.

Fixing the vulnerability would require updating Bouncy Castle to 1.7.4.

How to encrypt/decrypt strings with block ciphers

Hi,

I can't really seem to figure out how to encrypt and decrypt strings using buddy-core.

(defn test []
  (let [eng   (crypto/block-cipher :twofish :cbc)
        iv16  (nonce/random-nonce 16)
        key32 (nonce/random-nonce 32)
        data  (codecs/str->bytes "00000000000000000000000000000000")]
    (crypto/initialize! eng {:key key32 :iv iv16 :op :encrypt})
    (let [r (crypto/process-bytes! eng data)]
      (crypto/initialize! eng {:key key32 :iv iv16 :op :decrypt})
      (codecs/bytes->str (crypto/process-bytes! eng data)))))

Doesn't actually return the string of zeroes, but some value that looks binary.

What am I doing wrong?

Decrypting a compressed JWT from ruby-jwe fails

I was attempting to decode a JWT from ruby-jwe that had been zipped.

This library falls through to Zlib::Deflate to handle compression. This creates a problem for buddy.util.deflate/uncompress, which gets an exception:

CompilerException java.util.zip.ZipException: invalid stored block lengths

The root cause is creating the Inflater with nowrap set to true. Setting this value to false results in correct decompression. But I spent more time looking at this than I should have :)

Reading the docs it's kind of confusing because it states:

If the parameter 'nowrap' is true then the ZLIB header and checksum fields will not be used.

This makes it sound like they're harmless to have left in there, but it clearly fails if set to true.

Then it goes on to say

Note: When using the 'nowrap' option it is also necessary to provide an extra "dummy" byte as input. This is required by the ZLIB native library in order to support certain optimizations.

You're using the nowrap option but you're not passing in any dummy bytes (that I saw). Yet this apparently doesn't break unwrapped input.

I spent some time fiddling but can't afford to go too far down the bit twiddling rabbit hole. So instead I have a "just try it again" patch that you might be ok with, or you might want to root cause further. Of course if there's anything I can do to help just let me know. Pull request incoming.

str<->bytes codecs adding bytes

(nonce/random-nonce 8)
=> [0, 0, 1, 88, 4, -48, 62, -60]

(-> (nonce/random-nonce 8)
    (codecs/bytes->str)
    (codecs/str->bytes))
=> [0, 0, 1, 88, 4, -17, -65, -67, -17, -65, -67, -17, -65, -67]

This can't be right can it?

AES-128 requires 32 byte key?

AES-128 requires a 16-byte key - why is the assertion forcing the key to be 32 bytes? The encryption part of the codebase I'm working with is using Java and I want to port it to Clojure. There are already existing encryption keys that were generated to be 128-bit and are stored in a database as base64. I decoded it to a byte array and got a 16-byte key as required, but I get the following error calling crypto/decrypt:

AssertionError Assert failed: (keylength? key 32) buddy.core.crypto/eval43723/fn--43725 (crypto.clj:415)

I used codecs/base64->str to do the decoding.

following exception when doing (require '[buddy.hashers :as hashers]) in lein repl:

CompilerException java.io.FileNotFoundException: Could not locate clojurewerkz/scrypt/core__init.class or clojurewerkz/scrypt/core.clj on classpath., compiling:(buddy/hashers.clj:1:1)

Here is my lein deps ๐ŸŒด

Possibly confusing dependencies found:
[lein-droid "0.4.4"] -> [org.clojure/data.zip "0.1.1"] -> [org.clojure/clojure "1.3.0-beta1"]
overrides
[lein-droid "0.4.4"] -> [de.ubercode.clostache/clostache "1.4.0"] -> [org.clojure/core.incubator "0.1.2"] -> [org.clojure/clojure "1.4.0"]
and
[lein-droid "0.4.4"] -> [de.ubercode.clostache/clostache "1.4.0"] -> [org.clojure/clojure "1.3.0"]

Consider using these exclusions:
[lein-droid "0.4.4" :exclusions [org.clojure/clojure]]
[lein-droid "0.4.4" :exclusions [org.clojure/clojure]]

[buddy/buddy-hashers "1.0.0"]
[cider/cider-nrepl "0.13.0"]
[clojure-complete "0.2.4" :exclusions [[org.clojure/clojure]]]
[com.lambdaworks/scrypt "1.4.0"]
[org.clojure/clojure "1.7.0"]
[org.clojure/tools.nrepl "0.2.12" :exclusions [[org.clojure/clojure]]]

Spongycastle

Bouncycastle does not work on Android. Spongycastle fixes this. "The Android platform unfortunately ships with a cut-down version of Bouncy Castle - as well as being crippled, it also makes installing an updated version of the libraries difficult due to classloader conflicts."

Should work the same way. Its widely used in production software (bitcoinJ), so should be safe to switch.

https://rtyley.github.io/spongycastle/

Missing base64 encoding

The buddy.core.codecs imports the org.apache.commons.codec.binary.Base64 class but doesn't use it at all.
It would be convenient if there were base64->bytes and bytes->base64 functions doing conversion from/to base65 encoded string.

Can submit a patch if there's any interest in this.

jwe auth token not compatible with other java libraries

I am trying out jwe with {:alg :rsa-oaep-256 :enc :a256cbc-hs512}. It works only if the client and server both use buddy to perform encryption. But if I am using some other library, it does not. I tried with
https://bitbucket.org/connect2id/nimbus-jose-jwt/wiki/Home and https://bitbucket.org/b_c/jose4j/wiki/Home. In both the cases, the cipher is fine, but the auth tag is not compatible. On the other hand, the token generated by jose4j works with nimbus-jose-jwt.

On digging further, the auth token generator seems to be culprit

buddy code

(defn- generate-authtag
  [{:keys [algorithm input authkey iv aad] :as params}]
  (let [al (if aad
             (aad->bytes aad)
             (byte-array 0))
        data (bytes/concat aad iv input al)
        fulltag (mac/hash data {:key authkey :alg :hmac :digest algorithm})
        truncatesize (quot (count fulltag) 2)]
    (bytes/slice fulltag 0 truncatesize)))

nimbus code

    byte[] al = AAD.computeLength(aad);

        // Do MAC
        int hmacInputLength = aad.length + iv.length + cipherText.length + al.length;
        byte[] hmacInput = ByteBuffer.allocate(hmacInputLength).put(aad).put(iv).put(cipherText).put(al).array();
        byte[] hmac = HMAC.compute(compositeKey.getMACKey(), hmacInput, macProvider);
        byte[] authTag = Arrays.copyOf(hmac, compositeKey.getTruncatedMACByteLength());

jose4j code

Mac mac = MacUtil.getInitializedMac(this.getHmacJavaAlgorithm(), hmacKey, macProvider);
        byte[] al = this.getAdditionalAuthenticatedDataLengthBytes(aad);
        byte[] authenticationTagInput = ByteUtil.concat(new byte[][]{aad, iv, cipherText, al});
        byte[] authenticationTag = mac.doFinal(authenticationTagInput);
        authenticationTag = ByteUtil.subArray(authenticationTag, 0, this.getTagTruncationLength());

`str->base64` and `encode` do not produce the same results

Using buddy version 0.11.0 buddy.core.codecs the function (str->base64 "example") would yield the result that I expected ZXhhbXBsZQ==

Now using version 0.12.1 buddy.core.codecs.base64 the function (encode "example") which I assume is intended to be a comparable function returns #object[[B 0x26159658 [B@26159658]

Revisit the codecs namespace.

I think that some base64 codecs are doing double work because apache commons codecs already encodes doing all the things.

Bouncy Castle on the latest released version has a CVE of critical severity

I ran dependency-check-maven on the pom.xml generated by a tools.deps project using clj -Spom. The report attached contains the results showing evidence that several pedestal dependencies related to jetty contains high/critical severity. The report is zipped because github do not accept html attachments.
dependency-check-report.html.zip

Current master should be fine but there is no releases after bouncy castle was updated.

warning with clojure 1.7.0alpha5

Warning: protocol #'buddy.core.mac.proto/IMac is overwriting function update
WARNING: update already refers to: #'clojure.core/update in namespace: buddy.core.mac.proto, being replaced by: #'buddy.core.mac.proto/update
Warning: protocol #'buddy.core.hash/IHash is overwriting function update
WARNING: update already refers to: #'clojure.core/update in namespace: buddy.core.hash, being replaced by: #'buddy.core.hash/update

SecurityException on startup

I just switch from 0.13.0 to 1.0.0 and see now the following exception when doing lein repl:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at clojure.main.<clinit>(main.java:20)
Caused by: java.lang.SecurityException: class "org.bouncycastle.crypto.digests.SHA3Digest"'s signer information does not match signer information of other classes in the same package, compiling:(buddy/core/hash.clj:1:1)

Here's the list of buddy libraries I'm using:

  • [buddy/buddy-core "1.0.0"]
  • [buddy/buddy-sign "1.2.0"]
  • [buddy/buddy-hashers "1.0.0"]
  • [buddy/buddy-auth "1.2.0"]

My clojure version is 1.8.0. Reverting buddy-core to 0.13.0 solves the problem.

PS: Thanks for the great work you're doing!

certificates/not-before date is not correct.

certificates/not-before returns incorrect value.

actual result:
not-before = not after date.

expected result:
not-before = not before date.

See the issue in source code (certificates.clj):

(defn not-before
"Returns the first date this certificate is valid."
[cert]
(.getNotAfter cert))

Quote relevant RFC's

In buddy-sign there are the relevant RFC's and drafts quoted for JWS/JWT . In terms of buddy-core the following RFC's are relevant. Not entirely sure, perhaps could make sense to quote some of them in the documentation.

https://www.rfc-editor.org/rfc/rfc2104.txt (HMAC)
https://www.rfc-editor.org/rfc/rfc3174.txt (SHA1)
https://www.rfc-editor.org/rfc/rfc3537.txt (HMAC + DES)
https://www.rfc-editor.org/rfc/rfc4634.txt (SHA and HMAC-SHA)
https://www.rfc-editor.org/rfc/rfc4635.txt (HMAC SHA TSIG Algorithm Identifiers)
https://www.rfc-editor.org/rfc/rfc7519.txt (JWT)
https://www.rfc-editor.org/rfc/rfc7677.txt (SASL)

Feature Request - Support :hmac-sha1

I tried running the following but it appears there is no method implementation for :hmac-sha1. Will this be added?

(mac/hash payload {:key my-secret :alg :hmac+sha1})

I get an exception:

No method in multimethod 'engine' for dispatch value: :hmac+sha1

And I see that the method does not exist in the source.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.