Skip to content

Instantly share code, notes, and snippets.

@jizhang
Created December 18, 2012 07:14
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save jizhang/4325757 to your computer and use it in GitHub Desktop.
Save jizhang/4325757 to your computer and use it in GitHub Desktop.
Clojure - Calculate MD5 hash of a given string.
(import 'java.security.MessageDigest
'java.math.BigInteger)
(defn md5 [s]
(let [algorithm (MessageDigest/getInstance "MD5")
size (* 2 (.getDigestLength algorithm))
raw (.digest algorithm (.getBytes s))
sig (.toString (BigInteger. 1 raw) 16)
padding (apply str (repeat (- size (count sig)) "0"))]
(str padding sig)))
; for full digest support, use clj-digest: https://github.com/tebeka/clj-digest
@noisesmith
Copy link

noisesmith commented Feb 10, 2017

this can be simplified significantly

(defn md5 [s]
  (let [algorithm (MessageDigest/getInstance "MD5")
        raw (.digest algorithm (.getBytes s))]
    (format "%032x" (BigInteger. 1 raw)))))

@madstap
Copy link

madstap commented Sep 7, 2017

Can avoid reflection by typehinting s

(defn md5 [^String s]
  (let [algorithm (MessageDigest/getInstance "MD5")
        raw (.digest algorithm (.getBytes s))]
    (format "%032x" (BigInteger. 1 raw))))

@a613
Copy link

a613 commented Jun 29, 2018

Identical to version from madstap but threaded. Not sure if it's more or less readable.

(defn md5
  [^String s]
  (->> s
       .getBytes
       (.digest (MessageDigest/getInstance "MD5"))
       (BigInteger. 1)
       (format "%032x")))

@natesire
Copy link

natesire commented Apr 20, 2019

How do I import the MessageDigest library from Java?

Caused by: java.lang.RuntimeException: No such namespace: MessageDigest

(import 'java.security.MessageDigest
                'java.math.BigInteger)

(ns check-md5.core
  (:gen-class))

(defn md5 [^String s]
    (let [algorithm (MessageDigest/getInstance "MD5")
                  raw (.digest algorithm (.getBytes s))]
          (format "%032x" (BigInteger. 1 raw))))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println md5 "hello world")
  (println "Hello, World!"))```

@matthewdowney
Copy link

To import MessageDigest try the import without the quote:

(import java.security.MessageDigest)

@matthewdowney
Copy link

For a version that works on anything extended with clojure.java.io/IOFactory (like File):

(import java.security.MessageDigest)
(import java.io.ByteArrayOutputStream)
(require '[clojure.java.io :as io])

(defn md5 [io-factory]
  (let [bytes'
        (with-open [xin (io/input-stream io-factory)
                    xout (ByteArrayOutputStream.)]
          (io/copy xin xout)
          (.toByteArray xout))
        algorithm (MessageDigest/getInstance "MD5")
        raw (.digest algorithm bytes')]
    (format "%032x" (BigInteger. 1 raw))))

(spit "test.txt" "foo\nbar\n")
(md5 (io/file "test.txt"))
; => "f47c75614087a8dd938ba4acff252494"

Still has the disadvantage of reading the whole file into a byte array at once though. If that's a concern for anyone I think there are some pretty simple solutions here: https://stackoverflow.com/questions/304268/getting-a-files-md5-checksum-in-java

@aerdnag90
Copy link

Is it possible to get back the raw bytes from the md5 String "%032x" format?

Simply doing "f47c75614087a8dd938ba4acff252494".getBytes() does not produce the same result as the digested raw byte[].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment