Skip to content

Commit

Permalink
Add the KeyProvided abstraction for handle jws keys.
Browse files Browse the repository at this point in the history
This allows open extensions for user defined types that
works like a keys and pass a user defined function with
custom logic for key choice depending on some value on
the header.
  • Loading branch information
niwinz committed Feb 16, 2018
1 parent 332d2df commit 79c34bd
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 32 deletions.
35 changes: 17 additions & 18 deletions src/buddy/sign/jwe.clj
Expand Up @@ -49,15 +49,19 @@

(defn- parse-header
[^String data]
(let [{:keys [alg enc] :as header} (-> (b64/decode data)
(codecs/bytes->str)
(json/parse-string true))]
(when-not (map? header)
(try
(let [{:keys [alg enc] :as header} (-> (b64/decode data)
(codecs/bytes->str)
(json/parse-string true))]
(when-not (map? header)
(throw (ex-info "Message seems corrupt or manipulated."
{:type :validation :cause :header})))
(cond-> header
alg (assoc :alg (keyword (str/lower-case alg)))
enc (assoc :enc (keyword (str/lower-case enc)))))
(catch com.fasterxml.jackson.core.JsonParseException e
(throw (ex-info "Message seems corrupt or manipulated."
{:type :validation :cause :header})))
(cond-> header
alg (assoc :alg (keyword (str/lower-case alg)))
enc (assoc :enc (keyword (str/lower-case enc))))))
{:type :validation :cause :header})))))

(defn- generate-iv
[{:keys [enc]}]
Expand All @@ -76,9 +80,8 @@

(defn- decode-payload
[payload zip]
(if zip
(deflate/uncompress payload)
payload))
(cond-> payload
zip (deflate/uncompress payload)))

(defmulti aead-encrypt :alg)
(defmulti aead-decrypt :alg)
Expand Down Expand Up @@ -201,12 +204,8 @@
"Given a message, decode the header.
WARNING: This does not perform any signature validation."
[input]
(try
(let [[header] (split-jwe-message input)]
(parse-header header))
(catch com.fasterxml.jackson.core.JsonParseException e
(throw (ex-info "Message seems corrupt or manipulated."
{:type :validation :cause :header})))))
(let [[header] (split-jwe-message input)]
(parse-header header)))

(defn encrypt
"Encrypt then sign arbitrary length string/byte array using
Expand Down Expand Up @@ -241,7 +240,7 @@
(throw (ex-info "Message seems corrupt or manipulated."
{:type :validation :cause :signature})))
(try
(let [{:keys [zip] :as hdr} (parse-header header)
(let [{:keys [zip]} (parse-header header)
ecek (b64/decode ecek)
scek (cek/decrypt {:key key :ecek ecek :alg alg :enc enc})
iv (b64/decode iv)
Expand Down
29 changes: 15 additions & 14 deletions src/buddy/sign/jws.clj
Expand Up @@ -76,13 +76,17 @@

(defn- parse-header
[^String data]
(let [header (-> (b64/decode data)
(codecs/bytes->str)
(json/parse-string true))]
(when-not (map? header)
(try
(let [header (-> (b64/decode data)
(codecs/bytes->str)
(json/parse-string true))]
(when-not (map? header)
(throw (ex-info "Message seems corrupt or manipulated."
{:type :validation :cause :header})))
(update header :alg #(keyword (str/lower-case %))))
(catch com.fasterxml.jackson.core.JsonParseException e
(throw (ex-info "Message seems corrupt or manipulated."
{:type :validation :cause :header})))
(update header :alg #(keyword (str/lower-case %)))))
{:type :validation :cause :header})))))

(defn- encode-payload
[input]
Expand Down Expand Up @@ -123,12 +127,8 @@
"Given a message, decode the header.
WARNING: This does not perform any signature validation."
[input]
(try
(let [[header] (split-jws-message input)]
(parse-header header))
(catch com.fasterxml.jackson.core.JsonParseException e
(throw (ex-info "Message seems corrupt or manipulated."
{:type :validation :cause :header})))))
(let [[header] (split-jws-message input)]
(parse-header header)))

(defn sign
"Sign arbitrary length string/byte array using
Expand All @@ -149,10 +149,11 @@
the decoded payload."
([input pkey] (unsign input pkey nil))
([input pkey {:keys [alg] :or {alg :hs256}}]
(let [[header payload signature] (split-jws-message input)]
(let [[header payload signature] (split-jws-message input)
header-data (parse-header header)]
(when-not
(try
(verify-signature {:key pkey
(verify-signature {:key (util/resolve-key pkey header-data)
:signature signature
:alg alg
:header header
Expand Down
18 changes: 18 additions & 0 deletions src/buddy/sign/util.clj
Expand Up @@ -17,11 +17,29 @@
(:import java.lang.reflect.Method
clojure.lang.Reflector))

(defprotocol IKeyProvider
(resolve-key [key header] "Resolve a key"))

(defprotocol ITimestamp
"Default protocol for convert any type to
unix timestamp."
(to-timestamp [obj] "Covert to timestamp"))

;; Default impl for the key provider

(extend-protocol IKeyProvider
(Class/forName "[B")
(resolve-key [key header] key)

String
(resolve-key [key header] key)

clojure.lang.IFn
(resolve-key [key header] (key header))

java.security.Key
(resolve-key [key header] key))

(extend-protocol ITimestamp
java.util.Date
(to-timestamp [obj]
Expand Down

0 comments on commit 79c34bd

Please sign in to comment.