Compare commits
7 Commits
main
...
3a6fd107c0
| Author | SHA1 | Date | |
|---|---|---|---|
| 3a6fd107c0 | |||
| 4c31950a88 | |||
| aa71cb1d76 | |||
| c746675045 | |||
| 4052995ba8 | |||
| 44f48fced8 | |||
| c78e89a94b |
122
build.clj
122
build.clj
@@ -1,37 +1,101 @@
|
||||
(ns build
|
||||
(:require [clojure.tools.build.api :as b]))
|
||||
(:refer-clojure :exclude [test])
|
||||
(:require [clojure.tools.build.api :as b]
|
||||
[clojure.java.io :as io]))
|
||||
|
||||
(def lib 'es.rcorral/clj-totp)
|
||||
(def version (format "1.2.%s" (b/git-count-revs nil)))
|
||||
(def target-dir "target")
|
||||
(def class-dir (str target-dir "/classes"))
|
||||
(def uber-file (format "target/%s-%s-standalone.jar" (name lib) version))
|
||||
(def lib-group "es.rcorral")
|
||||
(def artifact-prefix "clj-totp")
|
||||
(def curr-version (format "2.0.%s" (b/git-count-revs nil)))
|
||||
|
||||
;; delay to defer side effects (artifact downloads)
|
||||
(def basis (delay (b/create-basis {:project "deps.edn"})))
|
||||
;; Builds artifact's full descriptor for each subproject
|
||||
(defn lib [subproj]
|
||||
(symbol (str lib-group "/" artifact-prefix "-" subproj )))
|
||||
|
||||
(defn clean [_]
|
||||
(b/delete {:path "target"}))
|
||||
;; Basis for each subproject, using their own deps.edn
|
||||
(defn basis [subproj]
|
||||
;(b/create-basis {:project (str subproj "/deps.edn")}))
|
||||
(delay (b/create-basis {:project (str "projects/" subproj "/deps.edn")})))
|
||||
|
||||
(defn compile-java [_]
|
||||
(b/javac {:src-dirs ["java"]
|
||||
:class-dir class-dir
|
||||
;; Target dir for each subproject
|
||||
(defn target-dir [subproj]
|
||||
(str "target/" subproj))
|
||||
|
||||
;; Path for compiled classes
|
||||
(defn class-dir [subproj]
|
||||
(str (target-dir subproj) "/" "classes"))
|
||||
|
||||
;; Jar file for each subproject. :uber type adds -standalone suffix
|
||||
(defn jar-file [subproj version type]
|
||||
(format "target/%s-%s-%s%s.jar" artifact-prefix subproj version
|
||||
(if (= type :uber) "-standalone" "")))
|
||||
|
||||
;; Clean target dir for subproject
|
||||
(defn clean [{:keys [subproj]}]
|
||||
(b/delete {:path (target-dir subproj)})
|
||||
(println "Project" subproj "cleaned"))
|
||||
|
||||
;; Compile java classes, only if java subdir exists
|
||||
(defn compile-java [subproj]
|
||||
(let [java-dir (str "projects/" subproj "/java")]
|
||||
(if (.exists (io/file java-dir))
|
||||
(do
|
||||
(println "Compiling java code for" subproj)
|
||||
(b/javac {:src-dirs [java-dir]
|
||||
:class-dir (class-dir subproj)
|
||||
:basis @(basis subproj)
|
||||
:javac-opts ["-source" "11" "--target" "11" "-proc:none"]}))
|
||||
(println "No java code for" subproj ", skipping compilation"))))
|
||||
|
||||
;; Create a jar file
|
||||
(defn jar
|
||||
"Build a simple jar file, with no dependencies included."
|
||||
[{:keys [subproj version]}]
|
||||
(let [real-version (if version version curr-version)
|
||||
target-dir (target-dir subproj)
|
||||
class-dir (class-dir subproj)
|
||||
src-dir (str "projects/" subproj "/src")
|
||||
resources-dir (str "projects/" subproj "/resources")
|
||||
basis (basis subproj)
|
||||
jar-file (jar-file subproj real-version :plain)]
|
||||
;; Clean only class dir
|
||||
(b/delete {:path class-dir})
|
||||
;; Copy code
|
||||
(b/copy-dir {:src-dirs [src-dir]
|
||||
:target-dir class-dir})
|
||||
;; Copy resources
|
||||
(b/copy-dir {:src-dirs [resources-dir]
|
||||
:target-dir target-dir})
|
||||
;; Compile java code, if exists
|
||||
(compile-java subproj)
|
||||
;; Build jar
|
||||
(b/jar {:class-dir class-dir
|
||||
:basis @basis
|
||||
:javac-opts ["-source" "11" "--target" "11" "-proc:none"]}))
|
||||
:jar-file jar-file
|
||||
:lib (lib subproj)
|
||||
:version real-version})
|
||||
(println "Generated jar file:" jar-file)))
|
||||
|
||||
;; Create an uber jar, with all dependencies inside
|
||||
(defn uber
|
||||
"Build a uberjar with all dependencies included"
|
||||
[{:keys [subproj version main-ns]}]
|
||||
(let [real-version (if version version curr-version)target-dir (target-dir subproj)
|
||||
basis (basis subproj)
|
||||
class-dir (class-dir subproj)
|
||||
src-dir (str "projects/" subproj "/src")
|
||||
resources-dir (str "projects/" subproj "/resources")
|
||||
uber-file (jar-file subproj real-version :uber)]
|
||||
(b/delete {:path class-dir})
|
||||
(b/copy-dir {:src-dirs [src-dir]
|
||||
:target-dir class-dir})
|
||||
(b/copy-dir {:src-dirs [resources-dir]
|
||||
:target-dir target-dir})
|
||||
(compile-java subproj)
|
||||
(b/compile-clj {:basis @basis
|
||||
:src-dirs [src-dir] :class-dir class-dir})
|
||||
(b/uber {:class-dir class-dir
|
||||
:uber-file uber-file
|
||||
:basis @basis
|
||||
:main main-ns})
|
||||
(println "Generated uberjar executable:" uber-file)))
|
||||
|
||||
#_{:clojure-lsp/ignore [:clojure-lsp/unused-public-var]}
|
||||
(defn uber [_]
|
||||
(clean nil)
|
||||
(b/copy-dir {:src-dirs ["src"]
|
||||
:target-dir class-dir})
|
||||
(b/copy-file {:src "resources/clj-totp.sh"
|
||||
:target "target/clj-totp.sh"})
|
||||
(compile-java nil)
|
||||
(b/compile-clj {:basis @basis
|
||||
:ns-compile '[totp.app]
|
||||
:class-dir class-dir})
|
||||
(b/uber {:class-dir class-dir
|
||||
:uber-file uber-file
|
||||
:basis @basis
|
||||
:main 'totp.app}))
|
||||
|
||||
56
deps.edn
56
deps.edn
@@ -1,16 +1,9 @@
|
||||
{:paths ["src" "resources" "target/classes"]
|
||||
:deps {org.clojure/clojure {:mvn/version "1.12.1"}
|
||||
io.github.clojure/tools.build {:mvn/version "0.10.10"}
|
||||
mvxcvi/alphabase {:mvn/version "3.0.185"} ;; https://github.com/greglook/alphabase
|
||||
cli-matic/cli-matic {:mvn/version "0.5.4"} ;; https://github.com/l3nz/cli-matic
|
||||
com.github.clj-easy/graal-build-time {:mvn/version "1.0.5"} ;; Tutorial: https://shagunagrawal.me/posts/setup-clojure-with-graalvm-for-native-image/
|
||||
;; Protobuf for java
|
||||
com.google.protobuf/protobuf-java {:mvn/version "3.25.8"}
|
||||
;; Progress bar
|
||||
com.github.pmonks/spinner {:mvn/version "2.0.284"}
|
||||
}
|
||||
;; Native image (GraalVM)
|
||||
com.github.clj-easy/graal-build-time {:mvn/version "1.0.5"}}
|
||||
|
||||
:aliases {;; Execute the app
|
||||
:aliases {;; Execute the app. Tutorial: https://shagunagrawal.me/posts/setup-clojure-with-graalvm-for-native-image/
|
||||
:run {:main-opts ["-m" "totp.app"]}
|
||||
|
||||
;; Kaocha runner. You can use the 'kaocha' wrapper located in ~/bin/kaocha
|
||||
@@ -20,5 +13,46 @@
|
||||
|
||||
;; Run with clj -T:build function-in-build
|
||||
:build {:deps {io.github.clojure/tools.build {:mvn/version "0.10.10"}}
|
||||
:ns-default build}}}
|
||||
:ns-default build}
|
||||
|
||||
|
||||
;; COMMON ALIASES FOR ALL PROJECTS
|
||||
:root/run-x {:exec-fn -main}
|
||||
:root/extra-paths [:totp.core/extra-paths
|
||||
:totp.cli/extra-paths
|
||||
:totp.web/extra-paths]
|
||||
|
||||
:root/all {:extra-paths ["src" "resources"
|
||||
:root/extra-paths]}
|
||||
|
||||
:root/test {:extra-paths ["test"]
|
||||
:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
||||
:main-opts ["-m" "kaocha.runner"]}
|
||||
|
||||
:boot/build {:extra-paths ["build"]
|
||||
:deps {io.github.clojure/tools.build {:mvn/version "0.10.10"}}
|
||||
:ns-default build
|
||||
;:exec-fn ci
|
||||
;:exec-args {:app-alias :com.example.core}
|
||||
}
|
||||
|
||||
:totp.core/extra-paths ["projects/core/src"
|
||||
"projects/core/test"
|
||||
"projects/core/java"
|
||||
"projects/core/resources"]
|
||||
:totp.core {:ns-default totp.core
|
||||
:main-opts ["-m" "totp.core"]
|
||||
:extra-deps {projects/core {:local/root "projects/core"}}
|
||||
:exec-args {:dirs ["projects/core"]}}
|
||||
|
||||
|
||||
:totp.cli/extra-paths ["projects/app/src"]
|
||||
:totp.cli {:ns-default totp.cli
|
||||
:main-opts ["-m" "totp.cli"]
|
||||
:extra-deps {;; does not use parts/grugstack {:local/root "parts"}
|
||||
projects/cli {:local/root "projects/cli"}}
|
||||
:exec-args {:dirs ["projects/cli"]}}
|
||||
|
||||
:totp.web/extra-paths ["projects/web/src"]
|
||||
}}
|
||||
|
||||
|
||||
34
doc/db.plantuml
Normal file
34
doc/db.plantuml
Normal file
@@ -0,0 +1,34 @@
|
||||
@startuml
|
||||
' configuration
|
||||
skinparam linetype ortho
|
||||
|
||||
entity "user" as user {
|
||||
id: number
|
||||
--
|
||||
login: varchar(64)
|
||||
passw: varchar(512)
|
||||
active: shortint
|
||||
desc: varchar(512)
|
||||
config: varchar(512)
|
||||
}
|
||||
|
||||
entity "app" as app {
|
||||
id: number
|
||||
--
|
||||
name: varchar(32)
|
||||
desc: varchar(512)
|
||||
secret: varchar(512)
|
||||
period: int
|
||||
config: varchar(512)
|
||||
}
|
||||
|
||||
entity "user_app" as user_app {
|
||||
user_id: number
|
||||
app_id: number
|
||||
--
|
||||
}
|
||||
|
||||
user ||--o{ user_app
|
||||
app ||--o{ user_app
|
||||
|
||||
@enduml
|
||||
BIN
doc/db.png
Normal file
BIN
doc/db.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.9 KiB |
@@ -4,7 +4,7 @@ NATIVE=~/.sdkman/candidates/java/21.0.2-graalce/bin/native-image
|
||||
BIN_FILE=totp
|
||||
|
||||
echo "Creating uberjar"
|
||||
#clojure -T:build uber
|
||||
clojure -T:build uber
|
||||
UBERJAR=$(realpath --relative-to=target target/clj-totp-*-standalone.jar)
|
||||
|
||||
echo "Creating native image"
|
||||
@@ -27,4 +27,4 @@ cp target/$BIN_FILE ~/bin
|
||||
echo "Copied to ~/bin/$BIN_FILE"
|
||||
|
||||
echo "Compress executable for distribution"
|
||||
xz target/$BIN_FILE
|
||||
xz -fv target/$BIN_FILE
|
||||
|
||||
16
projects/cli/deps.edn
Executable file
16
projects/cli/deps.edn
Executable file
@@ -0,0 +1,16 @@
|
||||
{:paths ["src" "resources" "target/classes"]
|
||||
:deps {clj-totp/core {:local/root "projects/core"}
|
||||
org.clojure/clojure {:mvn/version "1.12.1"}
|
||||
io.github.clojure/tools.build {:mvn/version "0.10.10"}
|
||||
cli-matic/cli-matic {:mvn/version "0.5.4"} ;; https://github.com/l3nz/cli-matic
|
||||
;; Progress bar
|
||||
com.github.pmonks/spinner {:mvn/version "2.0.284"}}
|
||||
|
||||
:aliases {;; Execute the app
|
||||
:run {:main-opts ["-m" "totp.app"]}
|
||||
|
||||
;; Kaocha runner. You can use the 'kaocha' wrapper located in ~/bin/kaocha
|
||||
:test {:extra-paths ["test"]
|
||||
:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
||||
:main-opts ["-m" "kaocha.runner"]}}}
|
||||
|
||||
1
projects/cli/tests.edn
Normal file
1
projects/cli/tests.edn
Normal file
@@ -0,0 +1 @@
|
||||
#kaocha/v1 {}
|
||||
1
projects/core/.cpcache/4091673994.basis
Normal file
1
projects/core/.cpcache/4091673994.basis
Normal file
File diff suppressed because one or more lines are too long
1
projects/core/.cpcache/4091673994.cp
Normal file
1
projects/core/.cpcache/4091673994.cp
Normal file
File diff suppressed because one or more lines are too long
1
projects/core/.cpcache/425892293.basis
Normal file
1
projects/core/.cpcache/425892293.basis
Normal file
File diff suppressed because one or more lines are too long
1
projects/core/.cpcache/425892293.cp
Normal file
1
projects/core/.cpcache/425892293.cp
Normal file
File diff suppressed because one or more lines are too long
2
projects/core/.cpcache/425892293.main
Normal file
2
projects/core/.cpcache/425892293.main
Normal file
@@ -0,0 +1,2 @@
|
||||
-m
|
||||
kaocha.runner
|
||||
14
projects/core/deps.edn
Executable file
14
projects/core/deps.edn
Executable file
@@ -0,0 +1,14 @@
|
||||
{:paths ["src" "resources" "target/classes"]
|
||||
:deps {org.clojure/clojure {:mvn/version "1.12.1"}
|
||||
io.github.clojure/tools.build {:mvn/version "0.10.10"}
|
||||
mvxcvi/alphabase {:mvn/version "3.0.185"} ;; https://github.com/greglook/alphabase
|
||||
cli-matic/cli-matic {:mvn/version "0.5.4"} ;; https://github.com/l3nz/cli-matic
|
||||
;; Protobuf for java
|
||||
com.google.protobuf/protobuf-java {:mvn/version "3.25.8"}
|
||||
}
|
||||
|
||||
:aliases {;; Kaocha runner. You can use the 'kaocha' wrapper located in ~/bin/kaocha
|
||||
:test {:extra-paths ["test"]
|
||||
:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}}
|
||||
:main-opts ["-m" "kaocha.runner"]}}}
|
||||
|
||||
BIN
projects/core/target/classes/alphabase/base32$decode.class
Normal file
BIN
projects/core/target/classes/alphabase/base32$decode.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
projects/core/target/classes/alphabase/base32$decode_STAR_.class
Normal file
BIN
projects/core/target/classes/alphabase/base32$decode_STAR_.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/base32$encode.class
Normal file
BIN
projects/core/target/classes/alphabase/base32$encode.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
projects/core/target/classes/alphabase/base32$encode_STAR_.class
Normal file
BIN
projects/core/target/classes/alphabase/base32$encode_STAR_.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/base32$fn__170.class
Normal file
BIN
projects/core/target/classes/alphabase/base32$fn__170.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
projects/core/target/classes/alphabase/base32__init.class
Normal file
BIN
projects/core/target/classes/alphabase/base32__init.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/base64$decode.class
Normal file
BIN
projects/core/target/classes/alphabase/base64$decode.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/base64$encode.class
Normal file
BIN
projects/core/target/classes/alphabase/base64$encode.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/base64$fn__230.class
Normal file
BIN
projects/core/target/classes/alphabase/base64$fn__230.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
projects/core/target/classes/alphabase/base64__init.class
Normal file
BIN
projects/core/target/classes/alphabase/base64__init.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$byte_array.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$byte_array.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$byte_seq.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$byte_seq.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$bytes_EQ_.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$bytes_EQ_.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$bytes_QMARK_.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$bytes_QMARK_.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$compare.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$compare.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$concat.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$concat.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$copy.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$copy.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$copy_slice.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$copy_slice.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$fn__144.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$fn__144.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$from_byte.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$from_byte.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$from_string.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$from_string.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$get_byte.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$get_byte.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$init_bytes.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$init_bytes.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$random_bytes.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$random_bytes.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$set_byte.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$set_byte.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$to_byte.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$to_byte.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes$to_string.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes$to_string.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/alphabase/bytes__init.class
Normal file
BIN
projects/core/target/classes/alphabase/bytes__init.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/core$bytes__GT_int.class
Normal file
BIN
projects/core/target/classes/totp/core$bytes__GT_int.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/core$bytes_array_QMARK_.class
Normal file
BIN
projects/core/target/classes/totp/core$bytes_array_QMARK_.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/core$fn__195.class
Normal file
BIN
projects/core/target/classes/totp/core$fn__195.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/core$fn__203$fn__204.class
Normal file
BIN
projects/core/target/classes/totp/core$fn__203$fn__204.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/core$fn__203.class
Normal file
BIN
projects/core/target/classes/totp/core$fn__203.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/core$fn__213.class
Normal file
BIN
projects/core/target/classes/totp/core$fn__213.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/core$fn__215.class
Normal file
BIN
projects/core/target/classes/totp/core$fn__215.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/core$fn__219.class
Normal file
BIN
projects/core/target/classes/totp/core$fn__219.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/core$get_alg.class
Normal file
BIN
projects/core/target/classes/totp/core$get_alg.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/core$get_otp.class
Normal file
BIN
projects/core/target/classes/totp/core$get_otp.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
projects/core/target/classes/totp/core$long__GT_bytes.class
Normal file
BIN
projects/core/target/classes/totp/core$long__GT_bytes.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/core$timestamp__GT_steps.class
Normal file
BIN
projects/core/target/classes/totp/core$timestamp__GT_steps.class
Normal file
Binary file not shown.
101
projects/core/target/classes/totp/core.clj
Normal file
101
projects/core/target/classes/totp/core.clj
Normal file
@@ -0,0 +1,101 @@
|
||||
(ns totp.core
|
||||
(:require [alphabase.base32 :as b32]
|
||||
[clojure.math :as m])
|
||||
(:import (javax.crypto Mac)
|
||||
(javax.crypto.spec SecretKeySpec)
|
||||
(java.util Base64 Arrays)
|
||||
(java.nio ByteBuffer)))
|
||||
|
||||
(def ^:private byte-array-type (type (.getBytes "")))
|
||||
|
||||
(defn timestamp->steps
|
||||
"Converts from UNIX timestamp in milliseconds to a number os steps of 's' seconds of duration"
|
||||
[time, step-size]
|
||||
(if (or (nil? time) (nil? step-size) (zero? step-size))
|
||||
0
|
||||
(int (quot time (* 1000 step-size)))))
|
||||
|
||||
|
||||
(defn bytes-array?
|
||||
"Return true if x is a byte[]"
|
||||
[x]
|
||||
(= byte-array-type (type x)))
|
||||
|
||||
|
||||
(defn get-alg
|
||||
[alg]
|
||||
(case alg
|
||||
"sha1" "HmacSHA1"
|
||||
"sha256" "HmacSHA256"
|
||||
"sha512" "HmacSHA512"
|
||||
""))
|
||||
|
||||
|
||||
(defmulti hmac
|
||||
"Generates an HMAC. Algorithms supported: sha1, sha256, sha512.
|
||||
The key and the message can be (both) string or array of bytes, nil otherwise"
|
||||
(fn [algorithm key message]
|
||||
(cond
|
||||
(and (string? key) (string? message) (some? (get-alg algorithm))) :string
|
||||
(and (bytes-array? key) (bytes-array? message) (some? (get-alg algorithm))) :byte
|
||||
:else :nil)))
|
||||
|
||||
;; By default
|
||||
(defmethod hmac :nil [_ _ _]
|
||||
nil)
|
||||
|
||||
;; When key and message are strings
|
||||
(defmethod hmac :string [algorithm key message]
|
||||
(if (or (empty? key) (empty? message))
|
||||
""
|
||||
(let [mac (doto (Mac/getInstance (get-alg algorithm)) (.init (SecretKeySpec. (.getBytes key) (get-alg algorithm))))
|
||||
hmac-bytes (.doFinal mac (.getBytes message))]
|
||||
;; Return the Base64 encoded HMAC
|
||||
(.encodeToString (Base64/getEncoder) hmac-bytes))))
|
||||
|
||||
;; When key and message are arrays of bytes
|
||||
(defmethod hmac :byte [algorithm key message]
|
||||
(if (nil? message)
|
||||
(bytes (byte-array 0))
|
||||
(let [mac (doto (Mac/getInstance (get-alg algorithm)) (.init (SecretKeySpec. key (get-alg algorithm))))
|
||||
hmac-bytes (.doFinal mac message)]
|
||||
;; Return the Base64 encoded HMAC
|
||||
(Base64/getEncoder) hmac-bytes)))
|
||||
|
||||
|
||||
(defn long->bytes
|
||||
"Converts a long to an array of 8 bytes"
|
||||
[l]
|
||||
;;Java equivalent: ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(someLong).array();
|
||||
(when (integer? l)
|
||||
(-> (ByteBuffer/allocate (/ Long/SIZE Byte/SIZE))
|
||||
(.putLong l)
|
||||
(.array))))
|
||||
|
||||
|
||||
(defn bytes->int
|
||||
"Converts an array of 4 bytes to an integer"
|
||||
[bytes]
|
||||
;;Java equivalent: ByteBuffer.wrap(data).getInt()
|
||||
(when (some? bytes)
|
||||
(.getInt (ByteBuffer/wrap bytes))))
|
||||
|
||||
|
||||
(defn get-otp
|
||||
"Generate an OTP with the given secret (in base32) for the specified timestep"
|
||||
([secret algorithm digits period] ;;algorithm digits period
|
||||
(when (and secret period)
|
||||
(let [step (timestamp->steps (System/currentTimeMillis) period)
|
||||
k (b32/decode secret)
|
||||
c (long->bytes step)
|
||||
hs (hmac algorithm k c)
|
||||
offset (bit-and (get hs (dec (count hs))) 0x0f) ;; int offset = hs[hs.length-1] & 0xf;
|
||||
chunk (Arrays/copyOfRange hs offset (+ offset 4)) ;(take 4 (drop offset hs)) ;; byte[] chunk = Arrays.copyOfRange(hs, offset, offset+4)
|
||||
]
|
||||
(format (str "%0" digits "d")
|
||||
(-> chunk
|
||||
(bytes->int)
|
||||
(bit-and 0x7fffffff)
|
||||
(rem (int (m/pow 10 digits))))))))
|
||||
([secret]
|
||||
(get-otp secret "sha1" 6 30)))
|
||||
BIN
projects/core/target/classes/totp/core__init.class
Normal file
BIN
projects/core/target/classes/totp/core__init.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$add_app.class
Normal file
BIN
projects/core/target/classes/totp/data$add_app.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$create_app.class
Normal file
BIN
projects/core/target/classes/totp/data$create_app.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$create_cfg_QMARK_.class
Normal file
BIN
projects/core/target/classes/totp/data$create_cfg_QMARK_.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$create_cfg_file.class
Normal file
BIN
projects/core/target/classes/totp/data$create_cfg_file.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$delete_app$fn__250.class
Normal file
BIN
projects/core/target/classes/totp/data$delete_app$fn__250.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$delete_app.class
Normal file
BIN
projects/core/target/classes/totp/data$delete_app.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$exists_config.class
Normal file
BIN
projects/core/target/classes/totp/data$exists_config.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$fn__235.class
Normal file
BIN
projects/core/target/classes/totp/data$fn__235.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$get_app$fn__260.class
Normal file
BIN
projects/core/target/classes/totp/data$get_app$fn__260.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$get_app.class
Normal file
BIN
projects/core/target/classes/totp/data$get_app.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
projects/core/target/classes/totp/data$join_path.class
Normal file
BIN
projects/core/target/classes/totp/data$join_path.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$list_apps$fn__256.class
Normal file
BIN
projects/core/target/classes/totp/data$list_apps$fn__256.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$list_apps.class
Normal file
BIN
projects/core/target/classes/totp/data$list_apps.class
Normal file
Binary file not shown.
BIN
projects/core/target/classes/totp/data$load_config.class
Normal file
BIN
projects/core/target/classes/totp/data$load_config.class
Normal file
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user