	Optimal yescrypt configuration.

yescrypt is very flexible, but configuring it optimally is complicated.
Here are some guidelines to simplify near-optimal configuration.  We
start by listing the parameters and their typical values, and then give
currently recommended parameter sets by use case.


	Parameters and their typical values.

Set flags (yescrypt flavor) to YESCRYPT_DEFAULTS to use the currently
recommended flavor.  (Other flags values exist for compatibility and for
specialized cases where you think you know what you're doing.)

Set N (block count) based on target memory usage and running time, as
well as on the value of r (block size in 128 byte units).  N must be a
power of two.

Set r (block size) to 8 (so that N is in KiB, which is convenient) or to
another small value (if more optimal or for fine-tuning of the total
size and/or running time).  Reasonable values for r are from 8 to 96.

Set p (parallelism) to 1 meaning no thread-level parallelism within one
computation of yescrypt.  (Use of thread-level parallelism within
yescrypt makes sense for ROM initialization and for key derivation at
high memory usage, but usually not for password hashing where
parallelism is available through concurrent authentication attempts.
Don't use p > 1 unnecessarily.)

Set t (time) to 0 to use the optimal running time for a given memory
usage.  This will allow you to maximize the memory usage (the value of
N*r) while staying within your running time constraints.  (Non-zero t
makes sense in specialized cases where you can't afford higher memory
usage but can afford more time.)

Set g (upgrades) to 0 because there have been no hash upgrades yet.

Set NROM (block count of ROM) to 0 unless you use a ROM (see below).
NROM must be a power of two.


	Password hashing for user authentication, no ROM.

Small and fast (memory usage 2 MiB, performance like bcrypt cost 2^5 -
latency 2-3 ms and throughput 10,000+ per second on a 16-core server):

flags = YESCRYPT_DEFAULTS, N = 2048, r = 8, p = 1, t = 0, g = 0, NROM = 0

Large and slow (memory usage 16 MiB, performance like bcrypt cost 2^8 -
latency 10-30 ms and throughput 1000+ per second on a 16-core server):

flags = YESCRYPT_DEFAULTS, N = 4096, r = 32, p = 1, t = 0, g = 0, NROM = 0

Of course, even heavier and slower settings are possible, if affordable.
Simply double the value of N as many times as needed.  Since N must be a
power of two, you may use r (in the range of 8 to 32) or/and t (in the
range of 0 to 2) for fine-tuning the running time, but first bring N to
the maximum you can afford.  If this feels too complicated, just use one
of the two parameter sets given above (preferably the second) as-is.


	Password hashing for user authentication, with ROM.

It's similar to the above, except that you need to adjust r, set NROM,
and initialize the ROM.

First decide on a ROM size, such as making it a large portion of your
dedicated authentication servers' RAM sizes.  Since NROM (block count)
must be a power of two, you might need to choose r (block size) based on
how your desired ROM size corresponds to a power of two.  Also tuning
for performance on current hardware, you'll likely end up with r in the
range from slightly below 16 to 32.  For example, to use 15/16 of a
server's 256 GiB RAM as ROM (thus, making it 240 GiB), you could use
r=15 or r=30.  To use 23/24 of a server's 384 GiB RAM as ROM (thus,
making it 368 GiB), you'd use r=23.  Then set NROM to your desired ROM
size in KiB divided by 128*r.  Note that these examples might (or might
not) be too extreme, leaving little memory for the rest of the system.
You could as well opt for 7/8 with r=14 or 11/12 with r=11 or r=22.

Note that higher r may make placing of ROM in e.g. NVMe flash memory
instead of in RAM more reasonable (or less unreasonable) than it would
have been with a lower r.  If this is a concern as it relates to
possible attacks and you do not intend to ever do it defensively, you
might want to keep r lower (e.g., prefer r=15 over r=30 in the example
above, even if 30 performs slightly faster).

Your adjustments to r, if you deviate from powers of two, will also
result in weirder memory usage per hash.  Like 1.75 MiB at r=14 instead
of 2 MiB at r=8 that you would have used without a ROM.  That's OK.

For ROM initialization, which you do with yescrypt_init_shared(), use
the same r and NROM that you'd later use for password hashing, choose p
based on your servers' physical and/or logical CPU count (maybe
considering eventual upgrades as you won't be able to change this later,
but without going unnecessarily high - e.g., p=28, p=56, or p=112 make
sense on servers that currently have 28 physical / 56 logical CPUs), and
set the rest of the parameters to:

flags = YESCRYPT_DEFAULTS, N = 0, t = 0, g = 0

N is set to 0 because it isn't relevant during ROM initialization (you
can use different values of N for hashing passwords with the same ROM).

To keep the ROM in e.g. SysV shared memory and reuse it across your
authentication service restarts, you'd need to allocate the memory and
set the flags to "YESCRYPT_DEFAULTS | YESCRYPT_SHARED_PREALLOCATED".

For actual password hashing, you'd use your chosen values for N, r,
NROM, and set the rest of the parameters to:

flags = YESCRYPT_DEFAULTS, p = 1, t = 0, g = 0

Note that although you'd use a large p for ROM initialization, you
should use p=1 for actual password hashing like you would without a ROM.

Do not forget to pass the ROM into the actual password hashing (and keep
r and NROM set accordingly).

Since N must be a power of two and r is dependent on ROM size, you may
use t (in the range of 0 to 2) for fine-tuning the running time, but
first bring N to the maximum you can afford.

If this feels too complicated, or even if it doesn't, please consider
engaging Openwall for your yescrypt deployment.  We'd be happy to help.


	Password-based key derivation.

(Or rather passphrase-based.)

Use settings similar to those for password hashing without a ROM, but
adjusted for higher memory usage and running time, and optionally with
thread-level parallelism.

Small and fast (memory usage 128 MiB, running time under 100 ms on a
fast desktop):

flags = YESCRYPT_DEFAULTS, N = 32768, r = 32, p = 1, t = 0, g = 0, NROM = 0

Large and fast (memory usage 1 GiB, running time under 200 ms on a fast
quad-core desktop not including memory allocation overhead, under 250 ms
with the overhead included), but requires build with OpenMP support (or
otherwise will run as slow as yet be weaker than its p=1 alternative):

flags = YESCRYPT_DEFAULTS, N = 262144, r = 32, p = 4, t = 0, g = 0, NROM = 0

Large and slower (memory usage 1 GiB, running time under 300 ms on a
fast quad-core desktop not including memory allocation overhead, under
350 ms with the overhead included), also requires build with OpenMP
support (or otherwise will run slower than the p=1 alternative below):

flags = YESCRYPT_DEFAULTS, N = 262144, r = 32, p = 4, t = 2, g = 0, NROM = 0

Large and slow (memory usage 1 GiB, running time under 600 ms on a fast
desktop not including memory allocation overhead, under 650 ms with the
overhead included):

flags = YESCRYPT_DEFAULTS, N = 262144, r = 32, p = 1, t = 0, g = 0, NROM = 0

Just like with password hashing, even heavier and slower settings are
possible, if affordable, and you achieve them by adjusting N, r, t in
the same way and in the same preferred ranges (please see the section on
password hashing without a ROM, above).  Unlike with password hashing,
it makes some sense to go above t=2 if you expect that your users might
not be able to afford more memory but can afford more time.  However,
increasing the memory usage provides better protection, and we don't
recommend forcing your users to wait for more than 1 second as they
could as well type more characters in that time.  If this feels too
complicated, just use one of the above parameter sets as-is.


	Amortization of memory allocation overhead.

It takes a significant fraction of yescrypt's total running time to
allocate memory from the operating system, especially considering that
the kernel zeroizes the memory before handing it over to your program.

Unless you naturally need to compute yescrypt just once per process, you
may achieve greater efficiency by fully using advanced yescrypt APIs
that let you preserve and reuse the memory allocation across yescrypt
invocations.  This is done by reusing the structure pointed to by the
"yescrypt_local_t *local" argument of yescrypt_r() or yescrypt_kdf()
without calling yescrypt_free_local() inbetween the repeated invocations
of yescrypt.


	YESCRYPT_DEFAULTS macro.

Please note that the value of the YESCRYPT_DEFAULTS macro might change
later, so if you use the macro like it's recommended here then for
results reproducible across versions you might need to store its value
somewhere along with the hashes or the encrypted data.

If you use yescrypt's standard hash string encoding, then yescrypt
already encodes and decodes this value for you, so you don't need to
worry about this.
