-
Notifications
You must be signed in to change notification settings - Fork 2
/
aes.cljc
71 lines (66 loc) · 3.2 KB
/
aes.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
(ns fluree.crypto.aes
(:require [alphabase.core :as alphabase]
[fluree.crypto.util :as util]
#?@(:cljs [[goog.crypt.Aes]
[goog.crypt.Cbc]
[fluree.crypto.pkcs7 :as pkcs7]]))
#?(:clj (:import (java.security SecureRandom)
(javax.crypto KeyGenerator Cipher)
(javax.crypto.spec SecretKeySpec IvParameterSpec))))
#?(:clj (set! *warn-on-reflection* true))
(defn encrypt* [iv key-ba ba]
#?(:clj (let [iv (IvParameterSpec. (byte-array (mapv #(if (> % 127) (- % 256) %) iv)))
spec (SecretKeySpec. (byte-array 32 key-ba) "AES")
cipher (Cipher/getInstance "AES/CBC/PKCS5Padding")]
(.init cipher Cipher/ENCRYPT_MODE spec iv)
(.doFinal cipher ba))
:cljs (let [cipher (goog.crypt.Aes. key-ba)
cbc (goog.crypt.Cbc. cipher)
padded (pkcs7/encode 16 ba)]
(.encrypt cbc padded (clj->js iv)))))
(defn ^:export encrypt
"Encrypts with AES/CBC/PKCS{5/7}Padding by hashing a 256 bit key out
of key (requires Unlimited Strength crypto to be enabled).
You can provide an alternate initial vector of unsigned(!) bytes of size 16 for CBC."
[x key & [{:keys [iv output-format] :or {iv [6 224 71 170 241 204 115 21 30 8 46 223 106 207 55 42]
output-format :hex}}]]
(let [key-ba (if (string? key)
(util/hash-string-key key 32)
key)
ba (if (string? x)
(alphabase/string->bytes x)
x)
encrypted (encrypt* iv key-ba ba)]
(case (keyword output-format)
:none encrypted
:hex (alphabase/bytes->hex encrypted)
:base64 (alphabase/bytes->base64 encrypted))))
(defn decrypt* [iv key-ba x-ba]
#?(:clj (let [iv (IvParameterSpec. (byte-array (mapv #(if (> % 127) (- % 256) %) iv)))
spec (SecretKeySpec. (byte-array 32 key-ba) "AES")
cipher (Cipher/getInstance "AES/CBC/PKCS5Padding")]
(.init cipher Cipher/DECRYPT_MODE spec iv)
(.doFinal cipher x-ba))
:cljs (let [cipher (goog.crypt.Aes. key-ba)
cbc (goog.crypt.Cbc. cipher)]
(pkcs7/decode 16 (.decrypt cbc x-ba (clj->js iv))))))
(defn ^:export decrypt
"Decrypts with AES/CBC/PKCS{5/7}Padding by hashing a 256 bit key out of key.
You can provide an alternate initial vector of unsigned(!) bytes of size 16 for CBC."
[x key & [{:keys [iv input-format output-format]
:or {iv [6 224 71 170 241 204 115 21 30 8 46 223 106 207 55 42]
input-format :hex
output-format :string}}]]
(let [key-ba (if (string? key)
(util/hash-string-key key 32)
key)
x-ba (if (string? x)
(case (keyword input-format)
:hex (alphabase/hex->bytes x)
:base64 (alphabase/base64->bytes x))
x)
decrypt-ba (decrypt* iv key-ba x-ba)]
(case (keyword output-format)
:none decrypt-ba
:hex (alphabase/bytes->hex decrypt-ba)
:string (alphabase/bytes->string decrypt-ba))))