char
/byte
arrays as input (required for stealth-mode)Because Clojure deserves the best crypto-hashers ;)
There are two ways to leverage cryptohash-clj
.
This namespace contains two multi-methods:
hash-with [algo raw options]
verify-with [algo raw options hashed]
These will delegate to the right implementation according to the first parameter (:pbkdf2
, :bcrypt
, :scrypt
). For example:
(hash-with :pbkdf2 "_sUpErSeCrEt@1234!_" {:algo :hmac+sha256})
=> "250000$256$hmac+sha256$zv6x/KfjV1318e3kF1aWBQ$qXoIRxVrtVbMnABxh5eTbDfszyc/O4uZIV8QPsLkyhE"
(verify-with :pbkdf2 "_sUpErSeCrEt@1234!_" *1)
=> true
(hash-with :bcrypt "_sUpErSeCrEt@1234!_" {:cpu-cost 8})
=> "$2y$08$0mddgmeilGorJlk.t4JYXu/b/K7S4VOD9LkddsPGyyrJp0TsEaOIu"
(verify-with :bcrypt "_sUpErSeCrEt@1234!_" *1)
=> true
Note that all the supported algorithms produce values that include the params in them so strictly speaking there shouldn't be a need
for passing any options to verify-with
. However, there are some exceptions - for instance in pbkdf2 you can specify a custom separator
(subject to validation). If you choose to do so, it needs to be known when verifying. Similarly with BCrypt and its long-value
parameter. For piece of mind you can always rely on the defaults (for those parameters) which will allow you to verify w/o passing options.
If you don't want to go via the multi-methods, you can go via the individual implementation namespaces.
Each of the three namespaces (bcrypt.clj
, scrypt.clj
, pbkdf2.clj
, argon2.clj
) contains two public functions:
chash ([raw opts] [raw])
verify ([raw opts hashed] [raw hashed])
Can be configured with the following options:
:separator
(defaults to \$
):iterations
(defaults to 250,000
):algo
(defaults to :hmac+sha512
, but :hmac+sha256
and :hmac+sha1
are valid choices):salt-length
(defaults to 16
bytes):key-length
(defaults to the native output length of :algo
- 64, 32 and 20 bytes respectively)I would advise against overriding the default key-length
.
You should certainly avoid providing a number of bits (bytes * 8) greater than the native output length of your chosen algo
as it makes life easier for an attacker. Providing less is safer, but since it won't save you any computation, it's
best to stick with the native output length.
Can be configured with the following options:
:version
(defaults to :v2y
but :v2a
and :v2b
are valid choices):cpu-cost
(defaults to 14
):long-value
(defaults to :sha512
, but :truncate
is a valid choice)Can be configured with the following options:
:salt-length
(defaults to 16
bytes):cpu-cost
(defaults to 17
):mem-cost
(defaults to 8
):pfactor
(parallelization factor - defaults to 1
)Can be configured with the following options:
:type
(defaults to :argon2id
):version
(defaults to :v13
):key-length
(defaults to 32
bytes):salt-length
(defaults to 16
bytes):secret
(bytes of some secret):additional
(additional bytes to include):iterations
(defaults to 100
):mem-cost
(defaults to 12
)Stealth mode is controlled by cryptohash-clj.stealth/*stealth?*
(bound to true
).
A convenience macro with-stealth
is also provided in the same namespace for easy overriding.
All random bytes are produced via a global instance of SecureRandom
which lives in cryptohash-clj.random/*PRNG*
.
A convenience macro with-PRNG
is also provided in the same namespace for easy overriding.
Equality comparison is performed in a way that resists timing attacks (see cryptohash-clj.equality
).
The length of the data being compared is still discoverable by an attacker, but in the context of
cryptographic hashing this is not a concern. In fact, many crypto-hashing functions produce fixed/well-known key lengths.
This will, of course, vary from CPU to CPU, but all the defaults have been tuned to produce a time cost of around 400-500 ms, on this (relatively modern) MacBook-Pro (2.8-3.8GHz Intel Core i7) from 2017.
crypto-password is the obvious alternative here. However it lacks an api for bytes/chars (even if the underlying Java lib supports it), stealth-mode, and generally speaking is less configurable. Moreover, it comes with several dependencies.
Copyright © 2019 Dimitrios Piliouras
This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.
Can you improve this documentation? These fine people already did:
Dimitrios Piliouras & jimpilEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close