compact_argon2 0.2.0

Thin wrapper around the argon2 crate to improve ergonomics and provide a smaller serialization format
Documentation
# 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";

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

// verify a password against a hash
assert!(hash.verify(password).unwrap());
// can also be written as
assert!(compact_argon2::verify(password, &hash).unwrap());

// serialize a hash into a byte array
let bytes: [u8; compact_argon2::OUTPUT_LEN] = hash.to_bytes();

// deserialize a hash from a byte array
let reconstructed = compact_argon2.from_bytes(&bytes).unwrap();
assert_eq!(hash, reconstructed);
```

## Stability

The format may change with only a minor version bump until the 1.0.0 release,
by which it should hopefully be stable.

## `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,
}
```

## Binary format

The `Hash` struct is fully stack allocated and serializes to a compact binary
representation. This is the recommended format, and the default for `serde`.
The format looks like this (made up types, all integers are big-endian):

```rs
#[repr(C, packed)]
struct Hash {
    iterations: u24be, // non-zero
    parallelism: u24be, // non-zero
    memory: u32be, // non-zero
    version: u8,
    salt: [u8; 16],
    out: [u8; 32]
}
```

## base64 format

This crate also offers helpers to serialize/deserialize hashes in base64, if
you need to store hashes as strings for whatever reason. The output is still
constant size and always smaller than the PHC equivalent. This is just a
wrapper around the [`base64`](https://crates.io/crates/base64) crate with
the URL-safe alphabet and no padding (because it's constant size).

```rs
let hash = compact_argon2::hash(b"hunter2").unwrap();
let hash_string = hash.to_string();
let parsed_hash = hash_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::serde::base64")]
    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?;
```