# compact_argon2
The ergonomics of the [`argon2`](https://crates.io/crates/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
```rs
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` `impl`s on `Hash`.
```rs
#[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.
```rs
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.
```rs
#[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.
```rs
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);
```