Source

clj-digest / src / digest.clj

Miki Tebeka 0897b8c 



Miki Tebeka 3a1f949 

Miki Tebeka 173d072 
Miki Tebeka 0897b8c 
Miki Tebeka 173d072 
Miki Tebeka 14cb235 
Miki Tebeka 3a1f949 

Miki Tebeka 173d072 

...@daaku.org a91878e 
Miki Tebeka 173d072 




Miki Tebeka 3a1f949 

Miki Tebeka 173d072 




Miki Tebeka 0897b8c 
Miki Tebeka 54c19f1 







Miki Tebeka 1124d41 
Miki Tebeka 173d072 
Miki Tebeka 1124d41 
Miki Tebeka 0897b8c 

Miki Tebeka 173d072 
Miki Tebeka 0897b8c 
Miki Tebeka 173d072 
Miki Tebeka 3a1f949 
Miki Tebeka 173d072 






...@daaku.org a91878e 
Miki Tebeka 173d072 
...@daaku.org a91878e 
Miki Tebeka 173d072 
Miki Tebeka 0897b8c 

Miki Tebeka 3a1f949 
Miki Tebeka 54c19f1 
Miki Tebeka 0897b8c 

Miki Tebeka 6d82d5f 
Miki Tebeka 0897b8c 




Miki Tebeka 1124d41 
Miki Tebeka 6d82d5f 

Miki Tebeka 0897b8c 

Miki Tebeka 1124d41 

Miki Tebeka 0897b8c 
(ns digest
  #^{ :author "Miki Tebeka <miki.tebeka@gmail.com>"
      :doc "Message digest algorithms for Clojure"}
  (:use [clojure.string :only (split lower-case)])
  (:import java.util.Arrays
           (java.security MessageDigest Security)
           (java.io FileInputStream File InputStream)))

; Default buffer size for reading
(def ^:dynamic *buffer-size* 1024)

; Why on earth is java.io.byte-array-type private?
(def ByteArray (type (make-array Byte/TYPE 0)))

(defn- read-some
  "Read some data from reader. Return [data size] if there's more to read,
  otherwise nil."
  [reader]
  (let [buffer (make-array Byte/TYPE *buffer-size*)
        size (.read reader buffer)]
    (when (> size 0)
      (if (= size *buffer-size*) buffer (Arrays/copyOf buffer size)))))

(defn- byte-seq
  "Return a sequence of [data size] from reader."
  [reader]
  (take-while (complement nil?) (repeatedly (partial read-some reader))))

(defn- signature
  "Get signature (string) of digest."
  [algorithm]
  (let [size (* 2 (.getDigestLength algorithm))
        sig (.toString (BigInteger. 1 (.digest algorithm)) 16)
        padding (apply str (repeat (- size (count sig)) "0"))]
    (str padding sig)))

(defmulti digest
  "Returns digest for input with given algorithm."
  (fn [algorithm message] (class message)))

(defmethod digest String [algorithm message]
  (digest algorithm (.getBytes message)))

(defmethod digest ByteArray [algorithm message]
  (digest algorithm [message]))

(defmethod digest File [algorithm file]
  (digest algorithm (FileInputStream. file)))

(defmethod digest InputStream [algorithm reader]
  (digest algorithm (byte-seq reader)))

; Code "borrowed" from
; * http://www.holygoat.co.uk/blog/entry/2009-03-26-1
; * http://www.rgagnon.com/javadetails/java-0416.html
(defmethod digest :default [algorithm chunks]
  (let [algo (MessageDigest/getInstance algorithm)]
    (.reset algo)
    (dorun (map #(.update algo %) chunks))
    (signature algo)))

(defn algorithms []
  "List support digest algorithms."
  (let [providers (into [] (Security/getProviders))
        names (mapcat #(enumeration-seq (.keys %)) providers)
        digest-names (filter #(re-find #"MessageDigest\.[A-Z0-9-]+$" %) names)]
    (set (map #(last (split % #"\.")) digest-names))))

(defn- create-fns []
  "Create utility function for each digest algorithms.
   For example will create an md5 function for MD5 algorithm."
  (dorun (map #(intern 'digest (symbol (lower-case %)) (partial digest %))
              (algorithms))))

; Create utililty functions such as md5, sha-2 ...
(create-fns)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.