Scrypt (Scrypt v0.1.0)

Copy Markdown View Source

A pure Elixir implementation of the scrypt password-based key derivation function as specified in RFC 7914.

The memory-hard core (Salsa20/8, BlockMix, ROMix) is implemented here in pure Elixir, building on the Salsa20 primitives exposed by the salsa20 library. The PBKDF2-HMAC-SHA256 layers are provided by OTP's :crypto.

The implementation is byte-exact against the reference algorithm: a given password, salt and parameter set always yields the same derived key across every platform and language (see test/scrypt_test.exs for the RFC 7914 and third-party vectors).

Summary

Functions

Run scryptBlockMix (RFC 7914, section 4) over a 128 * r byte block.

Compute a single scrypt intermediate via the memory-hard ROMix on a 128 * r byte block (RFC 7914, section 3).

Derive a key of keylen bytes from password and salt using scrypt.

Functions

blockmix(block, r)

@spec blockmix(binary(), pos_integer()) :: binary()

Run scryptBlockMix (RFC 7914, section 4) over a 128 * r byte block.

Exposed for testing against the RFC 7914 intermediate vectors.

romix(block, n, r)

@spec romix(binary(), pos_integer(), pos_integer()) :: binary()

Compute a single scrypt intermediate via the memory-hard ROMix on a 128 * r byte block (RFC 7914, section 3).

Exposed for testing against the reference intermediate values.

scrypt(password, salt, n, r, p, keylen)

@spec scrypt(
  binary(),
  binary(),
  pos_integer(),
  pos_integer(),
  pos_integer(),
  pos_integer()
) :: binary()

Derive a key of keylen bytes from password and salt using scrypt.

Parameters

  • password - the input passphrase as a binary
  • salt - the salt as a binary
  • n - CPU/memory cost. A power of 2 greater than 1 (e.g. 2, 1024, 16384).
  • r - block size parameter
  • p - parallelization parameter
  • keylen - the derived key length in bytes

Requires: n is a power of two > 1, r > 0, p > 0 and 128*r*p < 2^30.

Examples

iex> Scrypt.scrypt("", "", 16, 1, 1, 64) |> Base.encode16()
"77D6576238657B203B19CA42C18A0497F16B4844E3074AE8DFDFFA3FEDE21442FCD0069DED0948F8326A753A0FC81F17E8D3E0FB2E0D3628CF35E20C38D18906"

iex> Scrypt.scrypt("password", "NaCl", 1024, 8, 16, 64) |> Base.encode16()
"FDBABE1C9D3472007856E7190D01E9FE7C6AD7CBC8237830E77376634B3731622EAF30D92E22A3886FF109279D9830DAC727AFB94A83EE6D8360CBDFA2CC0640"