2023-06-02 14:35:52 +00:00
|
|
|
/* eslint-disable camelcase */
|
|
|
|
const b4a = require('b4a')
|
2023-06-02 14:45:24 +00:00
|
|
|
const argon2 = require('argon2hash-wasm')
|
2023-06-02 14:35:52 +00:00
|
|
|
const { randombytes_buf } = require('./randombytes')
|
|
|
|
|
|
|
|
const crypto_pwhash_argon2i_ALG_ARGON2I13 = 1
|
|
|
|
const crypto_pwhash_argon2i_BYTES_MIN = 16
|
|
|
|
const crypto_pwhash_argon2i_BYTES_MAX = 4294967295
|
|
|
|
const crypto_pwhash_argon2i_PASSWD_MIN = 0
|
|
|
|
const crypto_pwhash_argon2i_PASSWD_MAX = 4294967295
|
|
|
|
const crypto_pwhash_argon2i_SALTBYTES = 16
|
|
|
|
const crypto_pwhash_argon2i_STRBYTES = 128
|
|
|
|
const crypto_pwhash_argon2i_STRPREFIX = '$argon2i$'
|
|
|
|
const crypto_pwhash_argon2i_OPSLIMIT_MIN = 3
|
|
|
|
const crypto_pwhash_argon2i_OPSLIMIT_MAX = 4294967295
|
|
|
|
const crypto_pwhash_argon2i_MEMLIMIT_MIN = 8192
|
|
|
|
const crypto_pwhash_argon2i_MEMLIMIT_MAX = 2147483648
|
|
|
|
const crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE = 4
|
|
|
|
const crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE = 33554432
|
|
|
|
const crypto_pwhash_argon2i_OPSLIMIT_MODERATE = 6
|
|
|
|
const crypto_pwhash_argon2i_MEMLIMIT_MODERATE = 134217728
|
|
|
|
const crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE = 8
|
|
|
|
const crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE = 536870912
|
|
|
|
|
|
|
|
const crypto_pwhash_argon2id_ALG_ARGON2ID13 = 2
|
|
|
|
const crypto_pwhash_argon2id_BYTES_MIN = 16
|
|
|
|
const crypto_pwhash_argon2id_BYTES_MAX = 4294967295
|
|
|
|
const crypto_pwhash_argon2id_PASSWD_MIN = 0
|
|
|
|
const crypto_pwhash_argon2id_PASSWD_MAX = 4294967295
|
|
|
|
const crypto_pwhash_argon2id_SALTBYTES = 16
|
|
|
|
const crypto_pwhash_argon2id_STRBYTES = 128
|
|
|
|
const crypto_pwhash_argon2id_STRPREFIX = '$argon2id$'
|
|
|
|
const crypto_pwhash_argon2id_OPSLIMIT_MIN = 1
|
|
|
|
const crypto_pwhash_argon2id_OPSLIMIT_MAX = 4294967295
|
|
|
|
const crypto_pwhash_argon2id_MEMLIMIT_MIN = 8192
|
|
|
|
const crypto_pwhash_argon2id_MEMLIMIT_MAX = 2147483648
|
|
|
|
const crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE = 2
|
|
|
|
const crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE = 67108864
|
|
|
|
const crypto_pwhash_argon2id_OPSLIMIT_MODERATE = 3
|
|
|
|
const crypto_pwhash_argon2id_MEMLIMIT_MODERATE = 268435456
|
|
|
|
const crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE = 4
|
|
|
|
const crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE = 1073741824
|
|
|
|
|
|
|
|
const crypto_pwhash_ALG_ARGON2I13 = crypto_pwhash_argon2i_ALG_ARGON2I13
|
|
|
|
const crypto_pwhash_ALG_ARGON2ID13 = crypto_pwhash_argon2id_ALG_ARGON2ID13
|
|
|
|
const crypto_pwhash_ALG_DEFAULT = crypto_pwhash_ALG_ARGON2ID13
|
|
|
|
const crypto_pwhash_BYTES_MIN = crypto_pwhash_argon2id_BYTES_MIN
|
|
|
|
const crypto_pwhash_BYTES_MAX = crypto_pwhash_argon2id_BYTES_MAX
|
|
|
|
const crypto_pwhash_PASSWD_MIN = crypto_pwhash_argon2id_PASSWD_MIN
|
|
|
|
const crypto_pwhash_PASSWD_MAX = crypto_pwhash_argon2id_PASSWD_MAX
|
|
|
|
const crypto_pwhash_SALTBYTES = crypto_pwhash_argon2id_SALTBYTES
|
|
|
|
const crypto_pwhash_STRBYTES = crypto_pwhash_argon2id_STRBYTES
|
|
|
|
const crypto_pwhash_STRPREFIX = crypto_pwhash_argon2id_STRPREFIX
|
|
|
|
const crypto_pwhash_OPSLIMIT_MIN = crypto_pwhash_argon2id_OPSLIMIT_MIN
|
|
|
|
const crypto_pwhash_OPSLIMIT_MAX = crypto_pwhash_argon2id_OPSLIMIT_MAX
|
|
|
|
const crypto_pwhash_MEMLIMIT_MIN = crypto_pwhash_argon2id_MEMLIMIT_MIN
|
|
|
|
const crypto_pwhash_MEMLIMIT_MAX = crypto_pwhash_argon2id_MEMLIMIT_MAX
|
|
|
|
const crypto_pwhash_OPSLIMIT_INTERACTIVE = crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE
|
|
|
|
const crypto_pwhash_MEMLIMIT_INTERACTIVE = crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE
|
|
|
|
const crypto_pwhash_OPSLIMIT_MODERATE = crypto_pwhash_argon2id_OPSLIMIT_MODERATE
|
|
|
|
const crypto_pwhash_MEMLIMIT_MODERATE = crypto_pwhash_argon2id_MEMLIMIT_MODERATE
|
|
|
|
const crypto_pwhash_OPSLIMIT_SENSITIVE = crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE
|
|
|
|
const crypto_pwhash_MEMLIMIT_SENSITIVE = crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
crypto_pwhash_ALG_ARGON2I13,
|
|
|
|
crypto_pwhash_ALG_ARGON2ID13,
|
|
|
|
crypto_pwhash_ALG_DEFAULT,
|
|
|
|
crypto_pwhash_BYTES_MIN,
|
|
|
|
crypto_pwhash_BYTES_MAX,
|
|
|
|
crypto_pwhash_PASSWD_MIN,
|
|
|
|
crypto_pwhash_PASSWD_MAX,
|
|
|
|
crypto_pwhash_SALTBYTES,
|
|
|
|
crypto_pwhash_STRBYTES,
|
|
|
|
crypto_pwhash_STRPREFIX,
|
|
|
|
crypto_pwhash_OPSLIMIT_MIN,
|
|
|
|
crypto_pwhash_OPSLIMIT_MAX,
|
|
|
|
crypto_pwhash_MEMLIMIT_MIN,
|
|
|
|
crypto_pwhash_MEMLIMIT_MAX,
|
|
|
|
crypto_pwhash_OPSLIMIT_INTERACTIVE,
|
|
|
|
crypto_pwhash_MEMLIMIT_INTERACTIVE,
|
|
|
|
crypto_pwhash_OPSLIMIT_MODERATE,
|
|
|
|
crypto_pwhash_MEMLIMIT_MODERATE,
|
|
|
|
crypto_pwhash_OPSLIMIT_SENSITIVE,
|
|
|
|
crypto_pwhash_MEMLIMIT_SENSITIVE,
|
|
|
|
crypto_pwhash_argon2i,
|
|
|
|
crypto_pwhash_argon2id,
|
|
|
|
crypto_pwhash_argon2i_str,
|
|
|
|
crypto_pwhash_argon2id_str,
|
|
|
|
crypto_pwhash,
|
|
|
|
crypto_pwhash_str,
|
|
|
|
crypto_pwhash_str_verify,
|
|
|
|
crypto_pwhash_str_needs_rehash
|
|
|
|
}
|
|
|
|
|
|
|
|
function crypto_pwhash_argon2i (out, passwd, salt, passes, memory, alg) {
|
|
|
|
const outlen = out.byteLength
|
|
|
|
const passwdlen = passwd.byteLength
|
|
|
|
out.fill(0)
|
|
|
|
|
|
|
|
if (outlen > crypto_pwhash_argon2i_BYTES_MAX) {
|
|
|
|
throw new Error('Too large')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (outlen < crypto_pwhash_argon2i_BYTES_MIN) {
|
|
|
|
throw new Error('Invalid opts')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX ||
|
|
|
|
passes > crypto_pwhash_argon2i_OPSLIMIT_MAX ||
|
|
|
|
memory > crypto_pwhash_argon2i_MEMLIMIT_MAX) {
|
|
|
|
throw new Error('Too large')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN ||
|
|
|
|
(passes && passes < crypto_pwhash_argon2i_OPSLIMIT_MIN) ||
|
|
|
|
(memory && memory < crypto_pwhash_argon2i_MEMLIMIT_MIN)) {
|
|
|
|
throw new Error('Invalid opts')
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (alg) {
|
|
|
|
case crypto_pwhash_argon2i_ALG_ARGON2I13: {
|
|
|
|
const buf = argon2(passwd, salt, null, null, 'binary', { memory: memory >> 10, passes, outlen, type: argon2.ARGON2I })
|
|
|
|
out.set(buf)
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw new Error('Invalid input')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function crypto_pwhash_argon2id (out, passwd, salt, passes, memory, alg) {
|
|
|
|
const outlen = out.byteLength
|
|
|
|
const passwdlen = passwd.byteLength
|
|
|
|
out.fill(0)
|
|
|
|
|
|
|
|
if (outlen > crypto_pwhash_argon2id_BYTES_MAX) {
|
|
|
|
throw new Error('Too large')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (outlen < crypto_pwhash_argon2id_BYTES_MIN) {
|
|
|
|
throw new Error('Invalid opts')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
|
|
|
|
passes > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
|
|
|
|
memory > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
|
|
|
|
throw new Error('Too large')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
|
|
|
|
(passes && passes < crypto_pwhash_argon2id_OPSLIMIT_MIN) ||
|
|
|
|
(memory && memory < crypto_pwhash_argon2id_MEMLIMIT_MIN)) {
|
|
|
|
throw new Error('Invalid opts')
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (alg) {
|
|
|
|
case crypto_pwhash_argon2id_ALG_ARGON2ID13: {
|
|
|
|
const buf = argon2(passwd, salt, null, null, 'binary', { memory: memory >> 10, passes, outlen, type: argon2.ARGON2ID })
|
|
|
|
out.set(buf)
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw new Error('Invalid input')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function crypto_pwhash_argon2i_str (out, passwd, salt, passes, memory, alg) {
|
|
|
|
const outlen = 32
|
|
|
|
const passwdlen = passwd.byteLength
|
|
|
|
|
|
|
|
if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX ||
|
|
|
|
passes > crypto_pwhash_argon2i_OPSLIMIT_MAX ||
|
|
|
|
memory > crypto_pwhash_argon2i_MEMLIMIT_MAX) {
|
|
|
|
throw new Error('Too large')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN ||
|
|
|
|
(passes && passes < crypto_pwhash_argon2i_OPSLIMIT_MIN) ||
|
|
|
|
(memory && memory < crypto_pwhash_argon2i_MEMLIMIT_MIN)) {
|
|
|
|
throw new Error('Invalid opts')
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (alg) {
|
|
|
|
case crypto_pwhash_argon2i_ALG_ARGON2I13:
|
|
|
|
return argon2(passwd, salt, null, null, { memory: memory >> 10, passes, outlen, type: argon2.ARGON2I })
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw new Error('Invalid input')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function crypto_pwhash_argon2id_str (out, passwd, salt, passes, memory, alg) {
|
|
|
|
const outlen = 32
|
|
|
|
const passwdlen = passwd.byteLength
|
|
|
|
|
|
|
|
if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
|
|
|
|
passes > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
|
|
|
|
memory > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
|
|
|
|
throw new Error('Too large')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
|
|
|
|
(passes && passes < crypto_pwhash_argon2id_OPSLIMIT_MIN) ||
|
|
|
|
(memory && memory < crypto_pwhash_argon2id_MEMLIMIT_MIN)) {
|
|
|
|
throw new Error('Invalid opts')
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (alg) {
|
|
|
|
case crypto_pwhash_argon2id_ALG_ARGON2ID13:
|
|
|
|
out.write(argon2(passwd, salt, null, null, { memory: memory >> 10, passes, outlen, type: argon2.ARGON2ID }))
|
|
|
|
return
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw new Error('Invalid input')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function crypto_pwhash (out, passwd, salt, opslimit, memlimit, alg) {
|
|
|
|
switch (alg) {
|
|
|
|
case crypto_pwhash_argon2i_ALG_ARGON2I13:
|
|
|
|
return crypto_pwhash_argon2i(out, passwd, salt, opslimit, memlimit, alg)
|
|
|
|
|
|
|
|
case crypto_pwhash_argon2id_ALG_ARGON2ID13:
|
|
|
|
return crypto_pwhash_argon2id(out, passwd, salt, opslimit, memlimit, alg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function crypto_pwhash_str (out, passwd, opslimit, memlimit) {
|
|
|
|
const salt = b4a.alloc(crypto_pwhash_SALTBYTES)
|
|
|
|
randombytes_buf(salt)
|
|
|
|
|
|
|
|
return crypto_pwhash_argon2id_str(out, passwd, salt, opslimit, memlimit, crypto_pwhash_ALG_DEFAULT)
|
|
|
|
}
|
|
|
|
|
|
|
|
function crypto_pwhash_str_verify (str, passwd) {
|
|
|
|
if (b4a.isBuffer(str)) return crypto_pwhash_str_verify(str.toString(), passwd)
|
|
|
|
|
|
|
|
if (str.slice(0, crypto_pwhash_argon2id_STRPREFIX.length) === crypto_pwhash_argon2id_STRPREFIX) {
|
|
|
|
return argon2.verify(str, passwd, null)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (str.slice(0, crypto_pwhash_argon2i_STRPREFIX.length) === crypto_pwhash_argon2i_STRPREFIX) {
|
|
|
|
return argon2.verify(str, passwd, null)
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
function crypto_pwhash_str_needs_rehash (str, opslimit, memlimit, type) {
|
|
|
|
memlimit >>= 10
|
|
|
|
|
|
|
|
if ((opslimit | memlimit) > 0xffffffff || (str.byteLength > crypto_pwhash_STRBYTES)) {
|
|
|
|
throw new Error('Invalid opts.')
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
return argon2.needsRehash(str, opslimit, memlimit, type)
|
|
|
|
} catch {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|