Data security framework for Clojure. See the GitHub page (esp. Wiki) for info on motivation and design: <https://github.com/taoensso/tempel> See `df.clj` for data formats. All formats intended to support non-breaking future updates. Abbreviations: External: pbkdf - Password Based Key Derivation Function aad - Additional Associated Aata (see `aad-help`) akm - Additional Keying Material (see `akm-help`) kek - Key encryption key (key used to encrypt another key) cnt - Unencrypted content ecnt - Encrypted content kc - KeyChain ck - ChainKey Internal: key0 - Rand/user/password key (pre AKM, etc.) key1 - Key with AKM, etc. key2 - Final key ready for encryption/decryption key1b - Backup key ekeyX - Encrypted key
Tempel's behaviour is controlled by: 1. Call options, as provided to API functions. 2. Config options, as provided in this dynamic map. Config options (2) act as the default over which call options (1) will be merged. So these are equivalent: (binding [*config* <your-opts>)] (encrypt-with-password ba-content password {})) (encrypt-with-password ba-content password <your-opts>) Config options: Default values (*) should be sensible for most common use cases. `:hash-algo` ∈ #{:md5 :sha-1 *:sha-256 :sha-512} Hash algorithm used for internal HMACs, etc. Default: `:sha-256`, there's usually no good reason to change this. `:pbkdf-algo` ∈ #{*:scrypt-r8p1-v1 :pbkdf2-hmac-sha-256-v1} Algorithm to use for password-based key stretching. Default: `:scrypt-r8p1-v1` when `com.lambdaworks.crypto.SCrypt` is available, or `:pbkdf2-hmac-sha-256-v1` otherwise. `:pbkdf-nwf` ∈ #{:ref-10-msecs :ref-50-msecs *:ref-100-msecs :ref-200-msecs :ref-500-msecs :ref-1000-msecs :ref-2000-msecs :ref-5000-msecs <unsigned-short>} Normalized work factor (nwf) that describes how much computational effort should be used for password stretching. More effort means more resistance to brute-force attacks, but also more time and resources spent during normal operation. The `:ref-<num>-msecs` keywords take approximately the described amount of time on a 2020 M1 Macbook Pro. See `pbkdf-nwf-estimate`. Default: `:ref-100-msecs`, a reasonable value for many logins. `:sym-cipher-algo` ∈ #{*:aes-gcm-128-v1 :aes-gcm-256-v1 :chacha20-poly1305-v1} The symmetric cipher algorithm to use. A cipher that supports "AEAD" (Authenticated Encryption with Associated Data) must generally be provided in order to use `:ba-aad` options (see `aad-help`). Default: `:aes-gcm-128-v1`, a good general-purpose symmetric cipher with AEAD support. Note that the 256 bit AES cipher is not necessarily stronger than the 128 bit, and may even be weaker due to possible unique attack vectors (Ref. <https://goo.gl/qU4CCV>). `:keypair-creator` ∈ #{<function> <delay>} The function to use when generating asymmetric keypairs. See `keypair-create`, `keypair-creator` for details. Default: `default-keypair-creator_`, which uses up to 10% of threads to buffer up to 16 keypairs per type. This is often something you'll want to customize. `:symmetric-keys` Symmetric keys to add to new `KeyChain`s. See `keychain` for details. Default: a single random symmetric key. `:asymmetric-keypairs` Asymmetric keypairs to add to new `KeyChain`s. See `keychain` for details. Default: - A single new `:rsa-3072` keypair, and - A single new `:dh-3072` keypair Together these support all common Tempel functionality, and are a reasonable choice in most cases. `:embed-key-ids?` (relevant only when encrypting) Should key ids be embedded in encrypted output when using `KeyChain`s? This will allow the automatic selection of relevant keys during decryption, in exchange for leaking (making public) the ids used for encryption. This is often convenient, and *usually* safe unless you have custom key ids that contain private information and/or if it's important that you not leak information about which public `KeyChain`s might contain the necessary keys. Default: true. You may want to disable this for maximum security, but note that doing so may complicate decryption. See the Tempel Wiki for details. `:embed-hmac?` (relevant only when encrypting) Should an HMAC be embedded in encrypted output? When present, embedded HMACs can be checked on decryption to help verify data integrity and decryption key. Default: true. You'll generally want to keep this enabled unless you're trying to minimize the size of your encrypted output. Adds ~32 bytes to output when using the default `:sha-256` hash algorithm. `:ignore-hmac?` (relevant only when decrypting) Should embedded HMAC be ignored when decrypting? Default: false. Keep this disabled unless you're sure you understand the implications. `:backup-key` When encrypting: Encrypt data so that decryption will be possible with either the primary key/password, *OR* with this optional secondary (backup) `KeyChain` (see `keychain`) or `KeyPair` (see `keypair-create`). NB: this backup key will be able to decrypt *without* AKM (see `akm-help`). When decrypting: When data was encrypted with support for a backup key, use this `KeyChain` (see `keychain`) or `KeyPair` (see `keypair-create`) to decrypt. Key algorithm must support use as an asymmetric cipher. Suitable algorithms: `:rsa-<nbits>`. `:backup-opts` When encrypting: encryption opts map used with `:backup-key`. When decrypting: decryption opts map used with `:backup-key`.
"Additional Authenticated Data" (AAD) is optional arbitrary byte[] data that may be provided to many of Tempel's API functions (e.g. `encrypt-with-X` when using an AEAD cipher). When so provided, AAD will be embedded *UNENCRYPTED* with the API function's output byte[]. It may then later be retrieved: - Without verification: using `public-data` (see its docstring for details). - With verification: using the appropriate complementary API function (e.g. `decrypt-with-X`). Verification in this context means confirmation of: 1. Data integrity (the data is intact, and unmodified) 2. Authenticity (the data was indeed created/signed/etc. by the expected key). Examples of common AAD content: - Metadata like the sender, receiver, timestamp, etc. - Routing information - A description of the encrypted content - File or data integrity checks (hashes, etc.) - Cryptographic signatures - Arbitrary Clojure data via Nippy, Ref. <https://github.com/taoensso/nippy>
"Additional Keying Material" (AKM) is optional arbitrary byte[] data that may be provided to many of Tempel's API functions (e.g. `encrypt-with-X`). When so provided, AKM will act as additional secret material to supplement any main cryptographic keys, and so enhance security through increased resistance to certain types of attacks, etc. When an AKM is provided to an API function (e.g. `encrypt-with-X`), the same AKM *must* be provided to the function's complement (e.g. `decrypt-with-X`). In some contexts, an AKM may also be known as "Shared Keying Material" (SKM). Examples of common AKM content: - Metadata like the sender and receiver of an encrypted message - Random numbers or Nonces stored or transmitted separately - Key derivation parameters - Protocol-specific values - Security credentials or certificates - Arbitrary Clojure data via Nippy, Ref. <https://github.com/taoensso/nippy>
(as-ba x)
(as-ba target-len x)
Returns a byte[] from given input: byte[] -> byte[] string[] -> corresponding UTF-8 byte[] char[] -> corresponding UTF-8 byte[] int -> (byte-array <int>) seqable -> (byte-array <seq>) When `target-len` is provided, trim or zero-pad the returned array as necessary.
(decrypt-with-1-keypair ba-encrypted
receiver-key-prv
&
[:keys
[return ba-akm backup-key backup-opts ignore-hmac?] :or
{return :ba-content}])
Complement of `encrypt-with-1-keypair`. Uses a hybrid (symmetric + asymmetric) scheme to decrypt the given byte[]. Return value depends on `:return` option: `:ba-content` - Returns decrypted byte[] content (default) `:ba-aad` - Returns verified unencrypted embedded ?byte[] AAD `:map` - Returns {:keys [ba-aad ba-content]} map Takes a `KeyChain` (see `keychain`) or `KeyPair` (see `keypair-create`). Key algorithm must support use as an asymmetric cipher. Suitable algorithms: `:rsa-<nbits>`. Encryption uses receiver's asymmetric public key. Decryption uses receiver's asymmetric private key. Will throw on decryption failure (bad key, etc.).
(decrypt-with-2-keypairs ba-encrypted
receiver-key-prv
sender-key-pub
&
[{:keys [return ba-akm backup-key backup-opts
ignore-hmac?]
:or {return :ba-content}}])
Complement of `encrypt-with-2-keypairs`. Uses a hybrid (symmetric + asymmetric) scheme to decrypt the given byte[]. Return value depends on `:return` option: `:ba-content` - Returns decrypted byte[] content (default) `:ba-aad` - Returns verified unencrypted embedded ?byte[] AAD `:map` - Returns {:keys [ba-aad ba-content]} map Takes `KeyChain`s (see `keychain`) and/or `KeyPair`s (see `keypair-create`). Key algorithm must support key agreement. Suitable algorithms: `:dh-<nbits>`, `:ec-<curve>`. Encryption uses: - Receiver's asymmetric public key - Sender's asymmetric private key Decryption uses: - Receiver's asymmetric private key - Sender's asymmetric public key Will throw on decryption failure (bad key, etc.).
(decrypt-with-password ba-encrypted
password
&
[{:keys [return ba-akm backup-key backup-opts
ignore-hmac?]
:or {return :ba-content}}])
Complement of `encrypt-with-password`. Uses a symmetric cipher to decrypt the given byte[]. Return value depends on `:return` option: `:ba-content` - Returns decrypted byte[] content (default) `:ba-aad` - Returns verified unencrypted embedded ?byte[] AAD `:map` - Returns {:keys [ba-aad ba-content]} map Takes a password (string, byte[], or char[]). Password will be "stretched" using an appropriate "Password-Based Key Derivation Function" (PBKDF). Will throw on decryption failure (bad password, etc.).
(decrypt-with-symmetric-key ba-encrypted
key-sym
&
[{:keys [return ba-akm backup-key backup-opts
ignore-hmac?]
:or {return :ba-content}}])
Complement of `encrypt-with-symmetric-key`. Uses a symmetric cipher to decrypt the given byte[]. Return value depends on `:return` option: `:ba-content` - Returns decrypted byte[] content (default) `:ba-aad` - Returns verified unencrypted embedded ?byte[] AAD `:map` - Returns {:keys [ba-aad ba-content]} map Takes a `KeyChain` (see `keychain`) or byte[] key. Will throw on decryption failure (bad key, etc.).
Default stateful `KeyPair` generator with options: {:buffer-len 16, :n-threads [:perc 10]}
(encrypt-with-1-keypair ba-content
receiver-key-pub
&
[{:keys [ba-aad ba-akm hash-algo sym-cipher-algo
asym-cipher-algo embed-key-ids? embed-hmac?
backup-key backup-opts]}])
Uses a symmetric or hybrid (symmetric + asymmetric) scheme to encrypt the given content byte[] and return a byte[] that includes: - The encrypted content - Optional unencrypted AAD (see `aad-help`) - Envelope data necessary for decryption (specifies algorithms, etc.) Takes a `KeyChain` (see `keychain`) or `KeyPair` (see `keypair-create`). Key algorithm must support use as an asymmetric cipher. Suitable algorithms: `:rsa-<nbits>`. Encryption uses receiver's asymmetric public key. Decryption uses receiver's asymmetric private key. Decrypt output byte[] with: `decrypt-with-1-keypair`. Options: `:ba-aad` - See `aad-help` `:ba-akm` - See `akm-help` And see `*config*` for details: `hash-algo`, `sym-cipher-algo`, `asym-cipher-algo`, `embed-key-ids`, `backup-key`, `backup-opts`.
(encrypt-with-2-keypairs ba-content
receiver-key-pub
sender-key-prv
&
[{:keys [ba-aad ba-akm hash-algo ka-algo
sym-cipher-algo embed-key-ids? embed-hmac?
backup-key backup-opts]}])
Uses a hybrid (symmetric + asymmetric) scheme to encrypt the given content byte[] and return a byte[] that includes: - The encrypted content - Optional unencrypted AAD (see `aad-help`) - Envelope data necessary for decryption (specifies algorithms, etc.) Takes `KeyChain`s (see `keychain`) and/or `KeyPair`s (see `keypair-create`). Key algorithm must support key agreement. Suitable algorithms: `:dh-<nbits>`, `:ec-<curve>`. Encryption uses: - Receiver's asymmetric public key - Sender's asymmetric private key Decryption uses: - Receiver's asymmetric private key - Sender's asymmetric public key Decrypt output byte[] with: `decrypt-with-2-keypairs`. Options: `:ba-aad` - See `aad-help` `:ba-akm` - See `akm-help` And see `*config*` for details: `hash-algo`, `ka-algo`, `sym-cipher-algo`, `embed-key-ids?`, `backup-key`, `backup-opts`.
(encrypt-with-password ba-content
password
&
[{:keys [ba-aad ba-akm hash-algo sym-cipher-algo
pbkdf-algo pbkdf-nwf embed-key-ids? embed-hmac?
backup-key backup-opts]}])
Uses a symmetric cipher to encrypt the given byte[] content and return a byte[] that includes: - The encrypted content - Optional unencrypted AAD (see `aad-help`) - Envelope data necessary for decryption (specifies algorithms, etc.) Takes a password (string, byte[], or char[]). Password will be "stretched" using an appropriate "Password-Based Key Derivation Function" (PBKDF). Decrypt output with: `decrypt-with-password`. Options: `:ba-aad` - See `aad-help` `:ba-akm` - See `akm-help` And see `*config*` for details: `hash-algo`, `sym-cipher-algo`, `pbkdf-algo`, `pbkdf-nwf`, `embed-key-ids?`, `embed-hmac?`, `backup-key`, `backup-opts`.
(encrypt-with-symmetric-key ba-content
key-sym
&
[{:keys [ba-aad ba-akm hash-algo sym-cipher-algo
embed-key-ids? embed-hmac? backup-key
backup-opts]}])
Uses a symmetric cipher to encrypt the given byte[] content and return a byte[] that includes: - The encrypted content - Optional unencrypted AAD (see `aad-help`) - Envelope data necessary for decryption (specifies algorithms, etc.) Takes a `KeyChain` (see `keychain`) or byte[] key. Decrypt output with: `decrypt-with-symmetric-key`. Options: `:ba-aad` - See `aad-help` `:ba-akm` - See `akm-help` And see `*config*` for details: `hash-algo`, `sym-cipher-algo`, `embed-key-ids?`, `backup-key`, `backup-opts`.
(keychain &
[{:keys [empty? only? symmetric-keys asymmetric-keys
keypair-creator]}])
Returns a new `KeyChain` with key/pairs as specified by options: `:symmetric-keys` - Seq of keys given to `keychain-add-symmetric-key` `:asymmetric-keypairs` - Seq of keypairs given to `keychain-add-asymmetric-keypair` (keychain :symmetric-keys [:random :random (byte-array [1 2 3 4))] :asymmetric-keypairs [:rsa-1024 :dh-1024 :ec-secp384r1]) Options: `:empty?` - When truthy, returns a `KeyChain` without any keys `:only?` - When truthy, returns a `KeyChain` with keys ONLY as specified in call options (ignores any keys specified in `*config*`) And see `*config*` for details: `symmetric-keys`, `asymmetric-keys`, `keypair-creator`.
(keychain-add-asymmetric-keypair keychain
x-keypair
&
[{:keys [key-id priority return]
:or {return :keychain}}])
Produces a ?new `KeyChain` that contains the given asymmetric keypair. `x-keypair` may be: ∈ #{:rsa-<nbits> :dh-<nbits> :ec-<curve>}, a `java.security.KeyPair`, or a map with {:keys [key-prv key-pub]}. New keys will by default get top priority, override with `:priority` option. Return value depends on `:return` option: `:keychain` - Returns (possibly new) `KeyChain` (default) `:map` - Returns {:keys [keychain changed? key-id]} And see `*config*` for details: `keypair-creator`.
(keychain-add-symmetric-key keychain
x-key
&
[{:keys [key-id priority return]
:or {return :keychain}}])
Produces a ?new `KeyChain` that contains the given symmetric key. `x-key` may be: `:random`, byte[] of length >= 32, or {:keys [key-sym]} map. New keys will by default get top priority, override with `:priority` option. Return value depends on `:return` option: `:keychain` - Returns (possibly new) `KeyChain` (default) `:map` - Returns {:keys [keychain changed? key-id]}
(keychain-decrypt ba-encrypted-keychain
&
[{:keys [password key-sym return ba-akm backup-key backup-opts
ignore-hmac?]
:or {return :keychain}}])
Complement of `keychain-encrypt`. Given a `ba-encrypted-keychain` byte[] as returned by `keychain-encrypt`, and a password or symmetric key - checks if given password is correct. If incorrect, returns nil. If correct, return value depends on `:return` option: `:keychain` - Returns decrypted `KeyChain` (default) `:ba-content` - Returns decrypted byte[] content `:ba-aad` - Returns verified unencrypted embedded ?byte[] AAD `:map` - Returns {:keys [keychain ba-aad ba-content]} map See `keychain-encrypt` for details. See Tempel Wiki for detailed usage info, common patterns, examples, etc.
(keychain-encrypt keychain
&
[{:keys [password key-sym ba-content ba-aad ba-akm hash-algo
sym-cipher-algo pbkdf-algo pbkdf-nwf embed-key-ids?
embed-hmac? backup-key backup-opts]}])
Given a `KeyChain` and password or symmetric key, returns a byte[] that includes: - Encrypted: - The entire keychain - Optional other content (see `ba-content` option below) - Unencrypted: - Any public keys in keychain (retrieve with `public-data`) - Optional AAD (see `aad-help`) - Envelope data necessary for decryption (specifies algorithms, etc.) Output can be safely stored (e.g. in a database). Decrypt output with: `keychain-decrypt`. See Tempel Wiki for detailed usage info, common patterns, examples, etc. Options: `:password` - String, byte[], or char[] as with `encrypt-with-password` `:key-sym` - `KeyChain` (see `keychain`) or byte[] as with `encrypt-with-symmetric-key` `:ba-aad` - See `aad-help` `:ba-akm` - See `akm-help` `:ba-content` - Optional additional byte[] content that should be encrypted and included in output for retrieval with `keychain-decrypt`. And see `*config*` for details: `hash-algo`, `sym-cipher-algo`, `pbkdf-algo`, `pbkdf-nwf`, `embed-key-ids?`, `embed-hmac?`, `backup-key`, `backup-opts`.
(keychain-normalize-priorities keychain)
Returns a ?new `KeyChain` with key priorities normalized to their relative rank order: {"a" {:priority -3}, "b" {:priority 8}} => {"a" {:priority 0}, "b" {:priority 1}}
(keychain-remove keychain
key-id
&
[{:keys [keep-private?] :or {keep-private? true}}])
Returns a ?new `KeyChain` with the identified key removed. Options: `:keep-private?` - Should only the public component of keypairs be removed? (Default true)
(keychain-update-priority keychain key-id update-fn)
Returns a ?new `KeyChain` with the identified key's `:priority` updated to be (update-fn <old-priority>). Priority values can be any integer, positive or negative. When multiple keys in a `KeyChain` are appropriate for a task, the key with highest priority will be selected.
(keypair-create key-algo)
(keypair-create key-algo needs)
Generates and returns a new `java.security.KeyPair` for given `key-algo` ∈ #{:rsa :rsa-<nbits> :dh :dh-<nbits> :ec-<curve>}. Slow! Consider instead using `keypair-creator`.
(keypair-creator &
[{:keys [buffer-len n-threads]
:or {buffer-len 16 n-threads [:perc 10]}}])
Returns a stateful (fn keypair-get [key-algo]) like `keypair-create` that eagerly pre-computes keypairs of all previously-requested algos. Compare: (keypair-create :rsa-2048) ; Slow, keypair generated on demand ;; vs (defonce kpc (keypair-create {:buffer-len 128, :n-threads [:perc 10]})) (kpc :rsa-2048) ; Slow first call, keypair generated on demand (kpc :rsa-2048) ; Fast subsequent calls, will use cache of up to ; 128 pre-generated keypairs
(pbkdf-nwf-estimate pbkdf-algo bench-spec msecs-target-or-targets)
(pbkdf-nwf-estimate bench-spec kfn sfn nwf-to-probe msecs-target-or-targets)
Returns normalized work factor (nwf) estimate/s for which pbkdf runtime best matches given msecs target/s on the current system: (pbkdf-nwf-estimate :pbkdf2-hmac-sha-256-v1 [2 3] 200) => Runs pbkdf2 a total of 2x3=6 times to estimate the normalized work factor that yields a ~200 msec runtime on the current system. Expensive!! Don't use in production. Used internally to help generate reference `nwf` consts: `:ref-10-msecs`, `:ref-100-msecs`, etc.
(public-data ba-tempel-output)
Given an encrypted Tempel byte[], returns a map of *UNVERIFIED* public (unencrypted) data embedded in the byte[]. Possible keys: `:ba-aad` - See `aad-help` `:keychain` - Public-key part of encrypted `KeyChain` `:key-id` - See `:embed-key-ids?` option of `encrypt-X` API `:receiver-key-id` - '' `:sender-key-id` - '' `:has-hmac?` - Does data have embedded HMAC? `:has-backup-key?` - Can data be decrypted with a secondary (backup) key? `:key-algo` - ∈ #{:rsa-<nbits> :dh-<nbits> :ec-<curve>} `:version` - Integer version of data format (1, 2, etc.). `:kind` - ∈ #{:encrypted-with-symmetric-key :encrypted-with-password :encrypted-with-1-keypair :encrypted-with-2-keypairs :encrypted-keychain :signed} NB: provides *UNVERIFIED* data that could be corrupted or forged! For cryptographically verified data, use the appropriate API function (e.g. `decrypt-X`) instead.
(rand-ba len)
Returns secure random byte[] of given length: (rand-ba 32) => random 32 byte (256 bit) byte[].
(rate-limiter spec)
(rate-limiter opts spec)
Takes a map spec of form {<limit-id> [<n-max-reqs> <msecs-window>]}, and returns a basic stateful (fn rate-limiter [req-id] [command req-id]). Call fn with a single request id (e.g. username) by which to count/limit. Will return: - nil when all limits pass for that id, or - [<worst-limit-id> <worst-backoff-msecs> {<limit-id> <backoff-msecs>}] when any limits fail for that id. Or call fn with an additional command argument: `:rl/peek` <req-id> - Check limits w/o incrementing count. `:rl/reset` <req-id> - Reset all limits for given req-id. Example: (defonce my-rate-limiter (rate-limiter {"1 per sec" [1 1000] "10 per min" [10 60000]})) (defn send-message! [username msg-content] (if-let [fail (my-rate-limiter username)] (throw (ex-info "Sorry, rate limited!" {:fail fail})) <send message>))
(sign ba-content
signer-key-prv
&
[{:keys [ba-aad ba-akm embed-content? hash-algo sig-algo embed-key-ids?
embed-content?]
:or {embed-content? true}}])
Cryptographically signs the given content byte[] and returns a byte[] that includes: - Optional unencrypted content (see `embed-content?` option below) - Optional unencrypted AAD (see `aad-help`) - Envelope data necessary for verification (specifies algorithms, etc.) Produces: - Signed content when `embed-content?` is true (default) - A signature when `embed-content?` is false Takes a `KeyChain` (see `keychain`) or `KeyPair` (see `keypair-create`). Key algorithm must support signatures. Suitable algorithms: `:rsa-<nbits>`, `:ec-<curve>`. Signing uses signer's asymmetric private key. Verification uses signer's asymmetric public key. Verify with: `signed`. Options: `:ba-aad` - See `aad-help` `:ba-akm` - See `akm-help` `:embed-content?` - See usage info above And see `*config*` for details: `hash-algo`, `sig-algo`, `embed-key-ids?`.
(signed ba-signed
signer-key-pub
&
[{:keys [ba-content return ba-akm] :or {return :map}}])
Complement of `sign`. Cryptographically verifies if the given signed byte[] was signed by the private key corresponding to the given public key. Return value depends on `:return` option: `:ba-content` - Returns verified ?byte[] content (when embedded) `:ba-aad` - Returns verified ?byte[] AAD (when embedded) `:map` - Returns {:keys [ba-aad ba-content]} map (default) Returns nil when verification fails. Takes a `KeyChain` (see `keychain`) or `KeyPair` (see `keypair-create`). Key algorithm must support signatures. Suitable algorithms: `:rsa-<nbits>`, `:ec-<curve>`. Signing uses signer's asymmetric private key. Verification uses signer's asymmetric public key.
(with-min-runtime msecs form)
Executes form and ensures that at least the given number of milliseconds have elapsed before returning result. Can be useful for protection against timing attacks, etc: (with-min-runtime 2000 <variable-time-form>)
(with-min-runtime* msecs f)
Executes (f) and ensures that at least the given number of milliseconds have elapsed before returning result. Can be useful for protection against timing attacks, etc.: (with-min-runtime* 2000 (fn variable-time-fn [] <...>))
(with-srng instance-fn & body)
Evaluates body with given (instance-fn) used as sole source of randomness in Tempel. (instance-fn) should return a `java.security.SecureRandom` instance.
(with-srng-insecure-deterministic!!! long-seed & body)
Evaluates body with *INSECURE* deterministic `java.util.Random` used as sole source of randomness in Tempel. Never use when encrypting real data, etc. Provided only for testing.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close