summaryrefslogtreecommitdiff
path: root/compojure-3.2/src/compojure/crypto.clj
diff options
context:
space:
mode:
Diffstat (limited to 'compojure-3.2/src/compojure/crypto.clj')
-rwxr-xr-xcompojure-3.2/src/compojure/crypto.clj129
1 files changed, 129 insertions, 0 deletions
diff --git a/compojure-3.2/src/compojure/crypto.clj b/compojure-3.2/src/compojure/crypto.clj
new file mode 100755
index 0000000..937bad5
--- /dev/null
+++ b/compojure-3.2/src/compojure/crypto.clj
@@ -0,0 +1,129 @@
+;; Copyright (c) James Reeves. All rights reserved.
+;; The use and distribution terms for this software are covered by the Eclipse
+;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which
+;; can be found in the file epl-v10.html at the root of this distribution. By
+;; using this software in any fashion, you are agreeing to be bound by the
+;; terms of this license. You must not remove this notice, or any other, from
+;; this software.
+
+(ns compojure.crypto
+ "Functions for cryptographically signing, verifying and encrypting data."
+ (:use compojure.encodings
+ clojure.contrib.def
+ clojure.contrib.java-utils)
+ (:import java.security.SecureRandom
+ [javax.crypto Cipher KeyGenerator Mac]
+ [javax.crypto.spec SecretKeySpec IvParameterSpec]
+ java.util.UUID))
+
+(defvar hmac-defaults
+ {:algorithm "HmacSHA256"}
+ "Default options for HMACs.")
+
+(defvar encrypt-defaults
+ {:algorithm "AES"
+ :key-size 128
+ :mode "CBC"
+ :padding "PKCS5Padding"}
+ "Default options for symmetric encryption.")
+
+(defn secure-random-bytes
+ "Returns a random byte array of the specified size. Can optionally supply
+ an PRNG algorithm (defaults is SHA1PRNG)."
+ ([size]
+ (secure-random-bytes size "SHA1PRNG"))
+ ([size algorithm]
+ (let [seed (make-array Byte/TYPE size)]
+ (.nextBytes (SecureRandom/getInstance algorithm) seed)
+ seed)))
+
+(defn gen-secret-key
+ "Generate a random secret key from a map of encryption options."
+ ([]
+ (gen-secret-key {}))
+ ([options]
+ (secure-random-bytes (/ (options :key-size) 8))))
+
+(defn gen-uuid
+ "Generate a random UUID."
+ []
+ (str (UUID/randomUUID)))
+
+(defn- to-bytes
+ "Converts its argument into an array of bytes."
+ [x]
+ (cond
+ (string? x) (.getBytes x)
+ (sequential? x) (into-array Byte/TYPE x)
+ :else x))
+
+(defn hmac-bytes
+ "Generate a HMAC byte array with the supplied key on a byte array of data.
+ Takes an optional map of cryptography options."
+ [options key data]
+ (let [options (merge hmac-defaults options)
+ algorithm (options :algorithm)
+ hmac (doto (Mac/getInstance algorithm)
+ (.init (SecretKeySpec. key algorithm)))]
+ (.doFinal hmac data)))
+
+(defn hmac
+ "Generate a Basc64-encoded HMAC with the supplied key on a byte array or
+ string of data. Takes an optional map of cryptography options."
+ [options key data]
+ (base64-encode-bytes (hmac-bytes options key (to-bytes data))))
+
+(defn- make-algorithm
+ "Return an algorithm string suitable for JCE from a map of options."
+ [options]
+ (str "AES/" (options :mode) "/" (options :padding)))
+
+(defn- make-cipher
+ "Create an AES Cipher instance."
+ [options]
+ (Cipher/getInstance (make-algorithm options)))
+
+(defn encrypt-bytes
+ "Encrypts a byte array with the given key and encryption options."
+ [options key data]
+ (let [options (merge encrypt-defaults options)
+ cipher (make-cipher options)
+ secret-key (SecretKeySpec. key (options :algorithm))
+ iv (secure-random-bytes (.getBlockSize cipher))]
+ (.init cipher Cipher/ENCRYPT_MODE secret-key (IvParameterSpec. iv))
+ (to-bytes (concat iv (.doFinal cipher data)))))
+
+(defn decrypt-bytes
+ "Decrypts a byte array with the given key and encryption options."
+ [options key data]
+ (let [options (merge encrypt-defaults options)
+ cipher (make-cipher options)
+ [iv data] (split-at (.getBlockSize cipher) data)
+ iv-spec (IvParameterSpec. (to-bytes iv))
+ secret-key (SecretKeySpec. key (options :algorithm))]
+ (.init cipher Cipher/DECRYPT_MODE secret-key iv-spec)
+ (.doFinal cipher (to-bytes data))))
+
+(defn encrypt
+ "Encrypts a string or byte array with the given key and encryption options."
+ [options key data]
+ (base64-encode-bytes (encrypt-bytes options key (to-bytes data))))
+
+(defn decrypt
+ "Base64 encodes and encrypts a string with the given key and algorithm."
+ [options key data]
+ (String. (decrypt-bytes options key (base64-decode-bytes data))))
+
+(defn seal
+ "Seal a data structure into a cryptographically secure string. Ensures no-one
+ looks at or tampers with the data inside."
+ [key data]
+ (let [data (encrypt {} key (marshal data))]
+ (str data "--" (hmac {} key data))))
+
+(defn unseal
+ "Read a cryptographically sealed data structure."
+ [key data]
+ (let [[data mac] (.split data "--")]
+ (if (= mac (hmac {} key data))
+ (unmarshal (decrypt {} key data)))))