Skip to content

Instantly share code, notes, and snippets.

@Owez
Last active October 17, 2020 12:43
Show Gist options
  • Save Owez/b857ec315e9cb51eb784bcf0b0416967 to your computer and use it in GitHub Desktop.
Save Owez/b857ec315e9cb51eb784bcf0b0416967 to your computer and use it in GitHub Desktop.
Argon2 + api key hashing
/// Encodes plaintext with [ARGON_PEPPER] before the salt is added
fn encode_pepper<P: Into<String>>(plaintext: P) -> String {
format!("{}{}", plaintext.into(), ARGON_PEPPER)
}
/// Simplifies frontend of [gen_argon_hash] + [encode_hash_base64] into
/// a single function that only returns completed, [String]ified hash, typically
/// used for comparisons with already made hashes
pub fn hash_plaintext<P: Into<String>, S: Into<Option<i64>>>(
password: P,
existing_salt: S,
) -> String {
encode_hash_base64(&gen_argon_hash(password, existing_salt).0)
}
/// Generates an argon2 hash from given `password` and generates a new salt
/// automatically, returning the salt used.
///
/// If inputted `existing_salt` is an [Option::Some], this function will instead use that salt
///
/// Will always put a pepper in the form of [ARGON_PEPPER] before the salt, being
/// as such: `[password][pepper][salt]` in that order
pub fn gen_argon_hash<P: Into<String>, S: Into<Option<i64>>>(
password: P,
existing_salt: S,
) -> ([u8; 32], i64) {
let peppered_password = encode_pepper(password);
let salt = existing_salt
.into()
.map_or_else(|| rand::rngs::OsRng.gen(), |s| s);
let argon_res = argon2rs::argon2i_simple(&peppered_password, &base64::encode(salt.to_string()));
(argon_res.to_owned(), salt)
}
/// Converts a raw password hash of `[u8; 32]` to a string for use in easily
/// storing inside of database and such
pub fn encode_hash_base64(hash: &[u8; 32]) -> String {
let mut encoded_hash = String::new();
base64::encode_config_buf(hash, base64::STANDARD, &mut encoded_hash);
encoded_hash
}
/// Generates a new 128-bit api key similarly to how [hash_plaintext] works but
/// with a heavier salt. Works by combining two cryptographically secure u128
/// nums together then encoding in base64 then adding id to front, hashing and
/// base64 encoding once more
pub fn gen_api_key(id: i32) -> String {
let gen_plain_salt = || -> [u8; 16] { rand::rngs::OsRng.gen::<u128>().to_be_bytes() };
let mut full_salt = gen_plain_salt().to_vec();
full_salt.append(&mut gen_plain_salt().to_vec());
base64::encode(argon2rs::argon2i_simple(
&id.to_string(),
&base64::encode(full_salt),
))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment