-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
v0.3.1 Add MD5 and SHA2 family hashing
- Loading branch information
Showing
8 changed files
with
238 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Hashing | ||
|
||
`uniformity.hash` provides MD5, SHA1, SHA256, SHA384, and SHA512 hashes | ||
with binary, hex, base64, or URL-safe base64 encoding. | ||
|
||
It also provides a `hashes-equal?` function to check for hash equality. | ||
Note that encoding of its two inputs must be the same (i.e. both hex | ||
or both binary format). | ||
|
||
```clojure | ||
clj꞉uniformity.hash꞉> (def test-bytes (byte-array [1 2 3 4])) | ||
#'uniformity.hash/test-bytes | ||
|
||
;; defaults to hex encoding | ||
clj꞉uniformity.hash꞉> (md5 test-bytes) | ||
"08d6c05a21512a79a1dfeb9d2a8f262f" | ||
|
||
;; or you can specify format | ||
clj꞉uniformity.hash꞉> (sha1 test-bytes :format :hex) | ||
"12dada1fff4d4787ade3333147202c3b443e376f" | ||
|
||
clj꞉uniformity.hash꞉> (sha256 test-bytes :format :bytes) | ||
#object["[B" 0x528b135d "[B@528b135d"] | ||
|
||
clj꞉uniformity.hash꞉> (sha384 test-bytes :format :base64) | ||
"WmZ9YkMKjCU+uuQzMzkE3G4dQdzcR5cEdzFZuQWjrYLSutd2LYGjZsxG+7LiMn9c" | ||
|
||
clj꞉uniformity.hash꞉> (sha512 test-bytes :format :base64-urlsafe) | ||
"p8l22xcjrbQSdBeNyC6bd3lBqyAcad5h0PK8bSejWY9ZT6dI5Q2I08K_HiwucsPP73jDxtSvqQOR9-M6urykjg" | ||
|
||
;; equality comparison | ||
clj꞉uniformity.hash꞉> (hashes-equal? (md5 test-bytes) "08d6c05a21512a79a1dfeb9d2a8f262f") | ||
true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
(ns uniformity.hash | ||
(:require #?(:clj [uniformity.internals.java.hash :as internals] | ||
:cljs [uniformity.internals.js.hash :as internals]) | ||
[uniformity.util :as util])) | ||
|
||
(defn ^:private hash-format [hash format] | ||
(case format | ||
:bytes hash | ||
:hex (util/hex-encode hash) | ||
:base64 (util/base64-encode hash) | ||
:base64-urlsafe (util/base64-encode-urlsafe hash) | ||
(throw (ex-info "Unidentified hash format" | ||
{:format format})))) | ||
|
||
(defn md5 | ||
"Produces a MD5 hash of input bytes. | ||
Optional :format parameter determines output: | ||
:bytes | ||
:hex (default) | ||
:base64 | ||
:base64-urlsafe" | ||
[bytes | ||
& {:keys [format] :or {format :hex}}] | ||
(hash-format (internals/md5 bytes) | ||
format)) | ||
|
||
(defn sha1 | ||
"Produces a SHA-1 hash of input bytes. | ||
Optional :format parameter determines output: | ||
:bytes | ||
:hex (default) | ||
:base64 | ||
:base64-urlsafe" | ||
[bytes | ||
& {:keys [format] :or {format :hex}}] | ||
(hash-format (internals/sha1 bytes) | ||
format)) | ||
|
||
(defn sha256 | ||
"Produces a SHA-256 hash of input bytes. | ||
Optional :format parameter determines output: | ||
:bytes | ||
:hex (default) | ||
:base64 | ||
:base64-urlsafe" | ||
[bytes | ||
& {:keys [format] :or {format :hex}}] | ||
(hash-format (internals/sha256 bytes) | ||
format)) | ||
|
||
(defn sha384 | ||
"Produces a SHA-384 hash of input bytes. | ||
Optional :format parameter determines output: | ||
:bytes | ||
:hex (default) | ||
:base64 | ||
:base64-urlsafe" | ||
[bytes | ||
& {:keys [format] :or {format :hex}}] | ||
(hash-format (internals/sha384 bytes) | ||
format)) | ||
|
||
(defn sha512 | ||
"Produces a SHA-512 hash of input bytes. | ||
Optional :format parameter determines output: | ||
:bytes | ||
:hex (default) | ||
:base64 | ||
:base64-urlsafe" | ||
[bytes | ||
& {:keys [format] :or {format :hex}}] | ||
(hash-format (internals/sha512 bytes) | ||
format)) | ||
|
||
(defn hashes-equal? | ||
"Compares equality of two hashes by comparing every element | ||
to inhibit timing attacks." | ||
[hash1 hash2] | ||
(if (not= (count hash1) (count hash2)) | ||
false | ||
(reduce (fn [equals idx] | ||
(and equals | ||
(= (get hash1 idx) | ||
(get hash2 idx)))) | ||
true | ||
(range (count hash1))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
(ns uniformity.internals.java.hash | ||
;; (:require [clojure.core.async :refer [go]] | ||
;; [async-error.core :refer [go-try <?]]) | ||
(:import [java.security MessageDigest])) | ||
|
||
(defn ^:private java-hash [bytes type] | ||
(let [hasher (MessageDigest/getInstance type)] | ||
(.update hasher bytes) | ||
(.digest hasher))) | ||
|
||
(defn md5 [^bytes bytes] | ||
(java-hash bytes "MD5")) | ||
|
||
(defn sha1 [^bytes bytes] | ||
(java-hash bytes "SHA-1")) | ||
|
||
(defn sha256 [^bytes bytes] | ||
(java-hash bytes "SHA-256")) | ||
|
||
(defn sha384 [^bytes bytes] | ||
(java-hash bytes "SHA-384")) | ||
|
||
(defn sha512 [^bytes bytes] | ||
(java-hash bytes "SHA-512")) | ||
|
||
(comment | ||
(-> [1 2 3 4] | ||
byte-array | ||
md5 | ||
uniformity.internals.java.util/hex-encode)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
(ns uniformity.internals.js.hash | ||
(:require [goog.crypt.Md5] | ||
[goog.crypt.Sha1] | ||
[goog.crypt.Sha256] | ||
[goog.crypt.Sha384] | ||
[goog.crypt.Sha512])) | ||
|
||
(defn md5 [bytes] | ||
(let [hasher (goog.crypt.Md5.)] | ||
(.update hasher bytes) | ||
(js/Uint8Array. (.digest hasher)))) | ||
|
||
(defn sha1 [bytes] | ||
(let [hasher (goog.crypt.Sha1.)] | ||
(.update hasher bytes) | ||
(js/Uint8Array. (.digest hasher)))) | ||
|
||
(defn sha256 [bytes] | ||
(let [hasher (goog.crypt.Sha256.)] | ||
(.update hasher bytes) | ||
(js/Uint8Array. (.digest hasher)))) | ||
|
||
(defn sha384 [bytes] | ||
(let [hasher (goog.crypt.Sha384.)] | ||
(.update hasher bytes) | ||
(js/Uint8Array. (.digest hasher)))) | ||
|
||
(defn sha512 [bytes] | ||
(let [hasher (goog.crypt.Sha512.)] | ||
(.update hasher bytes) | ||
(js/Uint8Array. (.digest hasher)))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
(ns uniformity.hash-test | ||
(:require [uniformity.internals.validation :refer [compat-byte-array]] | ||
[uniformity.hash :as hash] | ||
#?(:clj [clojure.test :refer [deftest is]] | ||
:cljs [cljs.test :refer-macros [deftest is]]))) | ||
|
||
(def reference-bytes | ||
(compat-byte-array [1 2 3 4])) | ||
|
||
(def md5-reference-hash | ||
"08d6c05a21512a79a1dfeb9d2a8f262f") | ||
|
||
(deftest md5-test | ||
(is (hash/hashes-equal? (hash/md5 reference-bytes) | ||
md5-reference-hash))) | ||
|
||
|
||
(def sha1-reference-hash | ||
"12dada1fff4d4787ade3333147202c3b443e376f") | ||
|
||
(deftest sha1-test | ||
(is (hash/hashes-equal? (hash/sha1 reference-bytes) | ||
sha1-reference-hash))) | ||
|
||
|
||
(def sha256-reference-hash | ||
"9f64a747e1b97f131fabb6b447296c9b6f0201e79fb3c5356e6c77e89b6a806a") | ||
|
||
(deftest sha256-test | ||
(is (hash/hashes-equal? (hash/sha256 reference-bytes) | ||
sha256-reference-hash))) | ||
|
||
|
||
(def sha384-reference-hash | ||
"5a667d62430a8c253ebae433333904dc6e1d41dcdc479704773159b905a3ad82d2bad7762d81a366cc46fbb2e2327f5c") | ||
|
||
(deftest sha384-test | ||
(is (hash/hashes-equal? (hash/sha384 reference-bytes) | ||
sha384-reference-hash))) | ||
|
||
|
||
(def sha512-reference-hash | ||
"a7c976db1723adb41274178dc82e9b777941ab201c69de61d0f2bc6d27a3598f594fa748e50d88d3c2bf1e2c2e72c3cfef78c3c6d4afa90391f7e33ababca48e") | ||
|
||
(deftest sha512-test | ||
(is (hash/hashes-equal? (hash/sha512 reference-bytes) | ||
sha512-reference-hash))) |