On this page:
kdf-spec?
kdf-impl?
get-kdf
kdf
pwhash
pwhash-verify
pbkdf2-hmac
scrypt
Bibliography

6 Key Derivation and Password Hashing

A key derivation function can be used to derive keys from secret material that is not directly suitable for use as a key, such as a passphrase or the result of a key agreement algorithm. Differnt KDFs have different additional parameters such as work factors and context information fields.

KDFs with adjustable work factors are also used to store passwords [HtSSaP, DUB]. A KDF is preferable to a simple digest function (even with a salt) because the work factor can be chosen to make exhaustively searching the space of likely passwords (typically short and composed of alpha-numeric characters) costly.

procedure

(kdf-spec? v)  boolean?

  v : any/c
Returns #t if v is a KDF specifier, #f otherwise.

There are two groups of KDF specifiers. The following KDFs have work factors and are suitable for producing keys from passwords and storing passwords:

The following KDFs are suitable for producing keys from the results of key-agreement algorithms. They are not suitable for storing passwords.

Changed in version 1.3 of package crypto-lib: Added support for 'hkdf, 'concat, 'sp800-108-*, and 'ans-x9.63 algorithms.

procedure

(kdf-impl? v)  boolean?

  v : any/c
Returns #t if v is an implementation of a key-derivation function, #f otherwise.

procedure

(get-kdf k [factories])  (or/c kdf-impl? #f)

  k : kdf-spec?
  factories : (or/c crypto-factory? (listof crypto-factory?))
   = (crypto-factories)
Returns an implementation of KDF k from the given factories. If no factory in factories implements k, returns #f.

procedure

(kdf k pass salt [params])  bytes?

  k : (or/c kdf-spec? kdf-impl?)
  pass : bytes?
  salt : (or/c bytes? #f)
  params : (listof (list/c symbol? any/c)) = '()
Runs the KDF specified by k on the password or passphrase pass and the given salt and produces a derived key (or password hash). Additional parameters such as iteration count are passed via params.

The salt must be a bytestring (bytes?) except in the following cases: if the KDF is 'ans-x9.63, 'concat with a digest, 'sp800-108-counter, or 'sp800-108-double-pipeline, then salt must be #f; if the KDF is 'hkdf or 'concat with HMAC, then salt may be either #f or a bytestring.

The following parameters are recognized for (list 'pbkdf2 'hmac digest):

In 2000 PKCS#5 [PKCS5] recommended a minimum of 1000 iterations; the iteration count should be exponentially larger today.

The following parameters are recognized for 'scrypt:

In 2009 the original scrypt paper [scrypt] used parameters such as 214 to 220 for N, 1 for p, and 8 for r.

The following parameters are recognized for 'argon2d, 'argon2i, and 'argon2id:

The following parameters are recognized for the 'hkdf, 'concat, 'sp800-108-*, and 'asn-x9.63 families of KDFs:

Examples:
> (kdf '(pbkdf2 hmac sha256)
       #"I am the eggman"
       (crypto-random-bytes 16)
       '((iterations 100000) (key-size 32)))

#"M\275\226\361\355\[email protected]\231\37\365}9\354<81$3O\256\270\331\346QFZ_5?9\312\5"

> (kdf 'argon2id
       #"I am the walrus"
       #"googoogjoob"
       '((t 100) (m 2048) (p 1) (key-size 32)))

#"\30V\214|i\2072VE\242\345`+A\262\352Ni\230|6\365\227M\364\2\326y{\256\271\21"

> (define pre-key (.... do key agreement ....))
> (list (kdf '(hkdf sha256) pre-key #f
             '((info #"enc") (key-size 16)))
        (kdf '(hkdf sha256) pre-key #f
             '((info #"mac") (key-size 16))))

'(#"\265\361c&2\361\301\26\273\271\264\255\334\365\313\212"

  #"\235\t\220s\246C\f\230if'\303M\210\314\236")

procedure

(pwhash k password config)  string?

  k : (or/c kdf-spec? kdf-impl?)
  password : bytes?
  config : (listof (list/c symbol? any/c))
Computes a “password hash” from password suitable for storage, using the KDF algorithm k. The resulting string contains an identifier for the algorithm as well as the parameters from config. The formats are intended to be compatible with Modular Crypt Format.

The config parameters are nearly the same as for kdf, with the following exceptions:

Examples:
> (define pwcred (pwhash 'argon2id #"mypassword" '((t 1000) (m 4096) (p 1))))
> pwcred

"$argon2id$v=19$m=4096,t=1000,p=1$m+clolnAitzUfS2LdXAecw$tk4bWb9R4qjzOexnJVVkdCdKjSaZIVzjD7x7QBKZGeE"

Added in version 1.2 of package crypto-lib.

procedure

(pwhash-verify k password pwh)  boolean?

  k : (or/c kdf-impl? #f)
  password : bytes?
  pwh : string?
Check password against the password hash pwh.

If k is a KDF implementation (kdf-impl?), pwh must have been generated with the same KDF algorithm (but not necessarily the same implementation); otherwise an exception is raised. If k is #f, then the KDF algorithm is extracted from pwh and the (crypto-factories) list is searched for an implementation; if no implementation is found an exception is raised.

Examples:
> (pwhash-verify #f #"mypassword" pwcred)

#t

> (pwhash-verify #f #"wildguess" pwcred)

#f

Added in version 1.2 of package crypto-lib.

procedure

(pbkdf2-hmac di    
  pass    
  salt    
  #:iterations iterations    
  [#:key-size key-size])  bytes?
  di : digest-spec?
  pass : bytes?
  salt : bytes?
  iterations : exact-positive-integer?
  key-size : exact-positive-integer? = (digest-size di)
Finds an implementation of PBKDF2-HMAC-di using (crypto-factories) and uses it to derive a key of key-size bytes from pass and salt. The iterations argument controls the amount of work done.

Example:
> (pbkdf2-hmac 'sha256 #"I am the walrus" #"abcd" #:iterations 100000)

#"\aR>\"^\241\301\253f\v\237\310\263\330T\321\301\307|\212`\370\rD\347\f`{>\226c\371"

procedure

(scrypt pass    
  salt    
  #:N N    
  [#:p p    
  #:r r    
  #:key-size key-size])  bytes?
  pass : bytes?
  salt : bytes?
  N : exact-positive-integer?
  p : exact-positive-integer? = 1
  r : exact-positive-integer? = 8
  key-size : exact-positive-integer? = 32
Finds an implementation of scrypt [scrypt] using (crypto-factories) and uses it to derive a key of key-size bytes from pass and salt. The N parameter specifies the cost factor (affecting both CPU and memory resources).

Bibliography

[OWASP] “Password Storage Cheat Sheet.” https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
[HtSSaP] Coda Hale, “How to Safely Store a Password: Use bcrypt.” http://codahale.com/how-to-safely-store-a-password/
[DUB] Tony Arcieri, “Don’t Use bcrypt.” http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
[PKCS5] B. Kaliski, “PKCS #5: Password-Based Cryptography Specification.” https://tools.ietf.org/html/rfc2898
[bcrypt] Niels Provos and David Mazières, “A Future-Adaptable Password Scheme.” https://www.usenix.org/legacy/events/usenix99/provos.html
[scrypt] Colin Percival, “The scrypt key derivation function.” http://www.tarsnap.com/scrypt.html
[Argon2] Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich, “Argon2: the memory-hard function for password hashing and other applications.” https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
[PHC] “Password Hashing Competition.” https://password-hashing.net/
[HKDF] “RFC 5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF).” https://tools.ietf.org/html/rfc5869
[SP800-56A] “NIST Special Publication 800-56A Rev. 3: Recommendation for Pair-Wise Key-Establishment Schemes Using Discrete Logarithm Cryptography.” https://csrc.nist.gov/publications/detail/sp/800-56a/rev-3/final
[SP800-56C] “NIST Special Publication 800-56C Rev. 1: Recommendation for Key-Derivation Methods in Key-Establishment Schemes.” https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
[SP800-108] “NIST Special Publication 800-108: Recommendation for Key Derivation Using Pseudorandom Functions (Revised).” https://csrc.nist.gov/publications/detail/sp/800-108/final
[X963] “Public Key Cryptography for the Financial Services Industry - Key Agreement and Key Transport Using Elliptic Curve Cryptography.” — Not freely available. The KDF definition can be found in Section 3.6.1 of [SEC1].