Method: OpenSSL::KDF.scrypt

Defined in:
ossl_kdf.c

.scrypt(pass, salt: , N: ,r:, p: , length: ) ⇒ aString

Derives a key from pass using given parameters with the scrypt password-based key derivation function. The result can be used for password storage.

scrypt is designed to be memory-hard and more secure against brute-force attacks using custom hardwares than alternative KDFs such as PBKDF2 or bcrypt.

The keyword arguments N, r and p can be used to tune scrypt. RFC 7914 (published on 2016-08, tools.ietf.org/html/rfc7914#section-2) states that using values r=8 and p=1 appears to yield good results.

See RFC 7914 (tools.ietf.org/html/rfc7914) for more information.

Parameters

pass

Passphrase.

salt

Salt.

N

CPU/memory cost parameter. This must be a power of 2.

r

Block size parameter.

p

Parallelization parameter.

length

Length in octets of the derived key.

Example

pass = "password"
salt = SecureRandom.random_bytes(16)
dk = OpenSSL::KDF.scrypt(pass, salt: salt, N: 2**14, r: 8, p: 1, length: 32)
p dk #=> "\xDA\xE4\xE2...\x7F\xA1\x01T"

Returns:

  • (aString)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'ossl_kdf.c', line 103

static VALUE
kdf_scrypt(int argc, VALUE *argv, VALUE self)
{
    VALUE pass, salt, opts, kwargs[5], str;
    static ID kwargs_ids[5];
    size_t len;
    uint64_t N, r, p, maxmem;

    if (!kwargs_ids[0]) {
	kwargs_ids[0] = rb_intern_const("salt");
	kwargs_ids[1] = rb_intern_const("N");
	kwargs_ids[2] = rb_intern_const("r");
	kwargs_ids[3] = rb_intern_const("p");
	kwargs_ids[4] = rb_intern_const("length");
    }
    rb_scan_args(argc, argv, "1:", &pass, &opts);
    rb_get_kwargs(opts, kwargs_ids, 5, 0, kwargs);

    StringValue(pass);
    salt = StringValue(kwargs[0]);
    N = NUM2UINT64T(kwargs[1]);
    r = NUM2UINT64T(kwargs[2]);
    p = NUM2UINT64T(kwargs[3]);
    len = NUM2LONG(kwargs[4]);
    /*
     * OpenSSL uses 32MB by default (if zero is specified), which is too small.
     * Let's not limit memory consumption but just let malloc() fail inside
     * OpenSSL. The amount is controllable by other parameters.
     */
    maxmem = SIZE_MAX;

    str = rb_str_new(0, len);
    if (!EVP_PBE_scrypt(RSTRING_PTR(pass), RSTRING_LEN(pass),
			(unsigned char *)RSTRING_PTR(salt), RSTRING_LEN(salt),
			N, r, p, maxmem, (unsigned char *)RSTRING_PTR(str), len))
	ossl_raise(eKDF, "EVP_PBE_scrypt");

    return str;
}