Created
January 1, 2014 12:27
-
-
Save aristotle9/8207686 to your computer and use it in GitHub Desktop.
Clojure Server of Google Authenticator; Java version: https://github.com/wstrange/GoogleAuth
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
(ns xxx.totp | |
(:import org.apache.commons.codec.binary.Base32)) | |
(def ^:const seed "QPA2GEXU3NNZUFKJL3NLZMC5YCA6UGSVDA3TFBJDXCZTQXYGYCYNKKWNU3IQG657CRWNUKNZGA3I2CLBUZYD3K55YZYQ====") | |
(def ^:const secret-size 10) | |
(def ^:const random-number-algorithm "SHA1PRNG") | |
(def ^:const window-size 3) | |
(defn new-secret | |
[] | |
(let [sr (doto | |
(java.security.SecureRandom/getInstance random-number-algorithm) | |
(.setSeed (.decode (Base32.) seed))) | |
sec (.generateSeed sr secret-size)] | |
(java.lang.String. (.encode (Base32.) sec)))) | |
(defn qrbarcode-url | |
[user host secret] | |
(format | |
"https://www.google.com/chart?chs=200x200&chld=M%%7C0&cht=qr&chl=otpauth://totp/%s@%s%%3Fsecret%%3D%s" | |
user | |
host | |
secret)) | |
(defn verify-code | |
"raw-key byte[] timestamp-of-ms-div-30000 当前时间戳/ms除以30000" | |
[raw-key timestamp-of-ms-div-30000] | |
(let [data (byte-array 8) | |
value timestamp-of-ms-div-30000 | |
data (loop [i 7 | |
value value] | |
(if (>= i 0) | |
(do | |
(aset-byte data i (let [b (bit-and 0xff value)] | |
(if (> b 127) | |
(byte (- b 256)) | |
(byte b))));;cast long to signed byte | |
(recur (dec i) (bit-shift-right value 8))) | |
data)) | |
key-spec (javax.crypto.spec.SecretKeySpec. raw-key "HmacSHA1") | |
mac (javax.crypto.Mac/getInstance "HmacSHA1") | |
hash-bytes (do | |
(.init mac key-spec) | |
(.doFinal mac data)) | |
offset (bit-and 0xf | |
(aget hash-bytes (dec 20))) | |
truncated-hash | |
(loop [truncated-hash 0 | |
i 0] | |
(if (< i 4) | |
(let [truncated-hash (bit-shift-left truncated-hash 8) | |
truncated-hash (bit-or truncated-hash | |
(bit-and 0xff | |
(aget hash-bytes (+ offset i))))] | |
(recur truncated-hash (inc i))) | |
truncated-hash)) | |
truncated-hash (bit-and truncated-hash 0x7fffffff) | |
truncated-hash (rem truncated-hash 1000000)] | |
(int truncated-hash))) | |
(defn check-code | |
"timestamp/ms" | |
([^String secret ^String code timestamp] | |
(let [code (Integer. code);;convert to int, in clojure zero-leading numeric literal is octal | |
raw-key (.decode (Base32.) secret) | |
t (long (/ timestamp 30000)) | |
delta (reduce #(into %1 [(- %2) %2]) [0] (range 1 (inc window-size)))] | |
(loop [[i & xs] delta] | |
(if (nil? i) | |
false | |
(if (= code (verify-code raw-key (+ i t))) | |
true | |
(recur xs)))))) | |
([^String secret ^String code] | |
(check-code secret code (.getTime (java.util.Date.))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment