Argon2 Reference Implementation

repository·master·Indexed 26 days ago

https://github.com/p-h-c/phc-winner-argon2

The reference C implementation of the Argon2 password-hashing function, winner of the Password Hashing Competition (PHC). Designed to be memory-hard and resistant to GPU cracking and side-channel attacks, it provides a command-line utility and both high-level and low-level C APIs for Argon2i, Argon2d, and Argon2id variants.

Tokens
2.1K
Snippets
4
Records
8
Agent score
40%

What's inside Argon2

  1. Build and install Argon2

    master

    To build the Argon2 executable, static library (libargon2.a), and shared library (libargon2.so or libargon2.dylib), use make. It is recommended to specify an installation prefix during compilation and run tests to verify the build.

    1. Build the project: make
    2. Verify the build: make test
    3. Install to the system: sudo make install PREFIX=/usr
    make
    make test
    sudo make install PREFIX=/usr
  2. Generate Argon2 hashes via CLI

    master
    Use the argon2 command-line utility to generate Argon2 hashes. The command requires a salt as the first argument (minimum 8 octets) and expects the password to be provided via standard input (stdin). By default, the tool uses the Argon2i variant.
  3. Use the Argon2 low-level C API

    master

    The low-level API uses an argon2_context structure to provide fine-grained control over the hashing process. This allows for advanced features like keyed hashing and secure memory erasure.

    Key Features:

    • secret parameter: Used for keyed hashing (HMAC-like). Provides a secret key to be folded into the hash.
    • ad (associated data) parameter: Folds additional data into the hash value.
    • flags parameter: Controls secure memory erasure. Use ARGON2_FLAG_CLEAR_PASSWORD or ARGON2_FLAG_CLEAR_SECRET to wipe sensitive buffers after use.

    Implementation Pattern:

    1. Initialize an argon2_context struct.
    2. Call the variant-specific context function (e.g., argon2i_ctx(&context)).
    3. Check the return code against ARGON2_OK.

    Example:

    argon2_context context = {
        hash2,  /* output array */
        HASHLEN, /* digest length */
        pwd, /* password array */
        pwdlen, /* password length */
        salt,  /* salt array */
        SALTLEN, /* salt length */
        NULL, 0, /* optional secret data */
        NULL, 0, /* optional associated data */
        t_cost, m_cost, parallelism, parallelism,
        ARGON2_VERSION_13, /* algorithm version */
        NULL, NULL, /* custom memory functions */
        ARGON2_DEFAULT_FLAGS
    };
    
    int rc = argon2i_ctx(&context);
    #include "argon2.h"
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define HASHLEN 32
    #define SALTLEN 16
    #define PWD "password"
    
    int main(void)
    {
        uint8_t hash1[HASHLEN];
        uint8_t hash2[HASHLEN];
    
        uint8_t salt[SALTLEN];
        memset( salt, 0x00, SALTLEN );
    
        uint8_t *pwd = (uint8_t *)strdup(PWD);
        uint32_t pwdlen = strlen((char *)pwd);
    
        uint32_t t_cost = 2;            // 2-pass computation
        uint32_t m_cost = (1<<16);      // 64 mebibytes memory usage
        uint32_t parallelism = 1;       // number of threads and lanes
    
        // high-level API
        argon2i_hash_raw(t_cost, m_cost, parallelism, pwd, pwdlen, salt, SALTLEN, hash1, HASHLEN);
    
        // low-level API
        argon2_context context = {
            hash2,  /* output array, at least HASHLEN in size */
            HASHLEN, /* digest length */
            pwd, /* password array */
            pwdlen, /* password length */
            salt,  /* salt array */
            SALTLEN, /* salt length */
            NULL, 0, /* optional secret data */
            NULL, 0, /* optional associated data */
            t_cost, m_cost, parallelism, parallelism,
            ARGON2_VERSION_13, /* algorithm version */
            NULL, NULL, /* custom memory allocation / deallocation functions */
            /* by default only internal memory is cleared (pwd is not wiped) */
            ARGON2_DEFAULT_FLAGS
        };
    
        int rc = argon2i_ctx( &context );
        if(ARGON2_OK != rc) {
            printf("Error: %s\n", argon2_error_message(rc));
            exit(1);
        }
        free(pwd);
    
        for( int i=0; i<HASHLEN; ++i ) printf( "%02x", hash1[i] ); printf( "\n" );
        if (memcmp(hash1, hash2, HASHLEN)) {
            for( int i=0; i<HASHLEN; ++i ) {
                printf( "%02x", hash2[i] );
            }
            printf( "\nfail\n" );
        }
        else printf( "ok\n" );
        return 0;
    }
  4. Use the Argon2 high-level C API

    master

    The high-level API provides simple functions for hashing. Functions are named based on the variant and whether they return raw bytes or encoded strings:

    • Argon2i: argon2i_hash_raw(...) or argon2i_hash_encoded(...)
    • Argon2d: argon2d_hash_raw(...) or argon2d_hash_encoded(...)
    • Argon2id: argon2id_hash_raw(...) or argon2id_hash_encoded(...)

    Parameters:

    • t_cost: Number of iterations.
    • m_cost: Memory usage in kibibytes.
    • parallelism: Number of threads/lanes.
    • pwd: Password input buffer.
    • pwdlen: Password length.
    • salt: Salt input buffer.
    • saltlen: Salt length.
    • hash: Output buffer.
    • hashlen: Desired hash length.
  5. Use the Argon2 command-line utility

    master

    The argon2 CLI tool allows you to test specific Argon2 instances. The password is read from stdin.

    Usage: ./argon2 [-h] salt [-i|-d|-id] [-t iterations] [-m memory] [-p parallelism] [-l hash length] [-e|-r] [-v (10|13)]

    Parameters:

    • salt: The salt to use (at least 8 characters).
    • -i: Use Argon2i (default).
    • -d: Use Argon2d.
    • -id: Use Argon2id.
    • -t N: Sets iterations to N (default 3).
    • -m N: Sets memory usage to $2^N$ KiB (default 12).
    • -p N: Sets parallelism to N threads (default 1).
    • -l N: Sets hash output length to N bytes (default 32).
    • -e: Output only encoded hash.
    • -r: Output only the raw bytes of the hash.
    • -v (10|13): Argon2 version (defaults to 13).
    • -h: Print usage.

    Example: To hash "password" using "somesalt" with 2 iterations, 64 MiB memory ($2^{16}$ KiB), 4 threads, and a 24-byte hash:

    echo -n "password" | ./argon2 somesalt -t 2 -m 16 -p 4 -l 24
  6. Configure Argon2 CLI options

    master

    The argon2 command supports several options to tune the hashing parameters and output format:

    Variants

    • -d: Use Argon2d instead of the default Argon2i.
    • -id: Use Argon2id instead of the default Argon2i.

    Tuning Parameters

    • -t " N": Sets the number of iterations to N (default = 3).
    • -m " N": Sets the memory usage to $2^N$ KiB (default = 12).
    • -p " N": Sets parallelism to N threads (default = 1).
    • -l " N": Sets hash output length to N bytes (default = 32).
    • -v (10|13): Specifies the Argon2 version (defaults to the most recent, currently 13).

    Output Formats

    • -e: Output only the encoded hash.
    • -r: Output only the raw bytes of the hash.
    • -h: Display tool usage.