compact_argon2 0.1.0

Thin wrapper around the argon2 crate to improve ergonomics and provide a smaller serialization format
Documentation

compact_argon2

The ergonomics of the argon2 crate sucks. This crate provides a thin wrapper around argon2's methods and an alternate, much smaller binary serialization format. It uses whatever the default parameters of argon2 current are, but uses deserialized parameters during verification, just like the argon2 crate. It's hardcoded to use the argon2id algorithm with the default salt and output lengths because get real.

Usage

let password = b"hunter2";

let hash = compact_argon2::hash(password).unwrap();

assert!(hash.verify(password.as_bytes()).unwrap());

// save to a file
let bytes: [u8; 64] = hash.as_bytes();

serde compatibility

Enable the serde feature for Serialize and Deserialize impls on Hash.

#[derive(Serialize, Deserialize)]
struct User {
    pub name: String,
    pub password: compact_argon2::Hash,
}

hex representation

Enable the hex feature to convert Hash to/from a hex string.

let hash = compact_argon2::hash(b"hunter2").unwrap();
let hex_string = hash.to_string();
let parsed_hash = hex_string.parse().unwrap();

assert_eq!(hash, parsed_hash);

// Can also be used with serde

#[derive(Serialize, Deserialize)]
struct User {
    pub name: String,
    #[serde(with = "compact_argon2::hex")]
    pub password: compact_argon2::Hash,
}

sqlx::Postgres compatibility

Enable the postgres feature to use Hash with sqlx's PostgeSQL driver.

#[derive(FromRow)]
struct User {
    pub name: String,
    pub password: compact_argon2::Hash,
}

let mut user: User = sqlx::query_as("SELECT * FROM users WHERE name=?")
    .bind("AzureDiamond")
    .fetch_one(&pool)
    .await?;

let new_password = compact_argon2::hash(b"hunter2").unwrap();

sqlx::query("UPDATE users SET password=? WHERE name=?")
    .bind(&new_password)
    .bind(&user.name)
    .execute(&pool)
    .await?;

Serialized format

The Hash struct is fully stack allocated and serializes to a nice and even 64 bytes (128 in hex).

  • litte endian u32 (4 bytes) - t_cost
  • litte endian u32 (4 bytes) - p_cost
  • litte endian u32 (4 bytes) - m_cost
  • litte endian u32 (4 bytes) - Version
  • 16 bytes - Salt
  • 32 bytes - Hash output

Zero-copy deserialization

On little-endian targets, enable the zerocopy feature to deserialize &'a [u8] into &'a Hash directly, copying only 16 bytes to verify params.

let original_hash = compact_argon2::hash(b"hunter2").unwrap();
let bytes = original_hash.as_bytes();
let reconstructed = compact_argon2::Hash::checked_cast(&bytes).unwrap();

assert_eq!(reconstructed, &original_hash);