crypto::argon2+x86_64 +linux

This module provides an implementation of the argon2 key derivation function as described by RFC 9106. This is the recommended algorithm for password hashing in Hare programs, and for deriving keys for use with other cryptographic algorithms. Some thought must be given to the appropriate configuration for your use case. Some general advice is provided here; if in doubt, consult the RFC.

The argon2 parameters are configured via the conf structure. To determine the appropriate configuration parameters for a particular use-case, consult section 4 of the RFC. Otherwise, sane defaults for common scenarios are provided via default_conf and low_mem_conf; consult the docs of each configuration for details.

Once a suitable configuration has been selected, the user must provide a salt. This salt should be stored alongside the hash, should be unique for each password, and should be random: see crypto::random::. The salt and hash lengths are configurable, the recommended defaults are 16 and 32 bytes respectively.

Equipped with the necessary parameters, the user may call the appropriate argon2 variant via argon2d, argon2i, or argon2id. If unsure which to use, choose argon2id. The RFC is the authoratative source on the appropriate argon2 variant and configuration parameters for your use-case.

This is a low-level module which implements cryptographic primitives. Direct use of cryptographic primitives is not recommended for non-experts, as incorrect use of these primitives can easily lead to the introduction of security vulnerabilities. Non-experts are advised to use the high-level operations available in the top-level crypto:: module.

Be advised that Hare's cryptography implementations have not been audited.

Index

Types

type conf = struct {
	mem: (u32 | []u64),
	parallel: u32,
	passes: u32,
	version: u8,
	secret: []u8,
	data: []u8,
};

Constants

def BLOCKSZ: u32 = 128;
def VERSION: u8 = 19;

Globals

const default_conf: conf;
const low_mem_conf: conf;

Functions

fn argon2d(dest: []u8, password: []u8, salt: []u8, cfg: *conf) (void | nomem);
fn argon2i(dest: []u8, password: []u8, salt: []u8, cfg: *conf) (void | nomem);
fn argon2id(dest: []u8, password: []u8, salt: []u8, cfg: *conf) (void | nomem);

Types

type conf[link]

type conf = struct {
	mem: (u32 | []u64),
	parallel: u32,
	passes: u32,
	version: u8,
	secret: []u8,
	data: []u8,
};

This type provides configuration options for the argon2 algorithm. Most users will find default_conf or low_mem_conf suitable for their needs without providing a custom configuration. If writing a custom configuration, consult the RFC for advice on selecting suitable values for your use-case.

'parallel' specifies the number of parallel processes. 'pass' configures the number of iterations. Both values must be at least one. Note: the Hare implementation of argon2 does not process hashes in parallel, though it will still compute the correct hash if this value is greater than one.

'version' specifies the version of the argon2 function. The implementation currently only supports version 1.3. Use VERSION here.

'secret' and 'data' are optional byte arrays that are applied to the initial state. Consult the RFC for details.

The 'mem' parameter is used to configure working memory used during the computation. The argon2 algorithm requires a large amount of memory to compute hashes. If 'mem' set to a u32, it is interpreted as the desired number of 1024-byte blocks the implementation shall allocate for you. If the caller wants to manage the allocation itself, provide a []u8 instead. The length of this slice must be at least 8 times the value of 'parallel' in blocks, and must be a multiple of BLOCKSZ. To have the implementation allocate 64 KiB, set 'mem' to 64. To use the same amount of caller-provided memory, provide a slice of length 64 * BLOCKSZ.

Constants

def BLOCKSZ[link]

def BLOCKSZ: u32 = 128;

Number of u64 elements of one block.

def VERSION[link]

def VERSION: u8 = 19;

Latest version of argon2 supported by this implementation (1.3).

Globals

let default_conf[link]

const default_conf: conf;

The default recommended configuration for most use cases. This configuration uses 2 GiB of working memory. A 16-byte 'salt' and 32-byte 'dest' parameter is recommended in combination with this configuration.

let low_mem_conf[link]

const low_mem_conf: conf;

The default recommended configuration for memory-constrained use cases. This configuration uses 64 MiB of working memory. A 16-byte 'salt' and 32-byte 'dest' parameter is recommended in combination with this configuration.

Functions

fn argon2d[link]

fn argon2d(dest: []u8, password: []u8, salt: []u8, cfg: *conf) (void | nomem);

Computes an argon2d hash, writing the digest to 'dest'. A 'salt' length of 16 bytes is recommended, and 8 bytes is the minimum. A 'dest' length of 32 bytes is recommended, and 4 bytes is the minimum.

The argon2d mode uses data-dependent memory access and is suitable for applications with no threats of side-channel timing attacks.

fn argon2i[link]

fn argon2i(dest: []u8, password: []u8, salt: []u8, cfg: *conf) (void | nomem);

Computes an argon2i hash, writing the digest to 'dest'. A 'salt' length of 16 bytes is recommended, and 8 bytes is the minimum. A 'dest' length of 32 bytes is recommended, and 4 bytes is the minimum.

The argon2i mode uses data-independent memory access and is suitable for password hashing and key derivation. It makes more passes over memory to protect from trade-off attacks.

fn argon2id[link]

fn argon2id(dest: []u8, password: []u8, salt: []u8, cfg: *conf) (void | nomem);

Computes an argon2id hash, writing the digest to 'dest'. A 'salt' length of 16 bytes is recommended, and 8 bytes is the minimum. A 'dest' length of 32 bytes is recommended, and 4 bytes is the minimum.

The argon2id mode works by using argon2i for the first half of the first pass and argon2d further on. It provides therefore protection from side-channel attacks and brute-force cost savings due to memory trade-offs.

If you are unsure which variant to use, argon2id is recommended.