Skip to content

Commit

Permalink
Formatting, cleanup, update benchmarking code. (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
samscott89 committed Nov 29, 2020
1 parent 711debc commit da15f56
Show file tree
Hide file tree
Showing 22 changed files with 651 additions and 514 deletions.
13 changes: 11 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ documentation = "https://docs.rs/libpasta"
license = "MIT"
readme = "README.md"
repository = "https://github.com/libpasta/libpasta"
edition = "2015"

[lib]
bench = false

[[bench]]
name = "bench"
harness = false


[dependencies]
argon2rs = "0.2.5"
Expand All @@ -24,14 +33,14 @@ serde_yaml = "0.8.14"
scrypt = "0.5.0"

[dependencies.ring]
version = "0.16.16"
version = "0.16.18"
default-features = false
features = ["std"]

[dev-dependencies]
cargon = "0.0.1"
criterion = "0.3.3"
env_logger = "0.8.2"
time = "0.1.42"

[features]
bench = []
Expand Down
137 changes: 64 additions & 73 deletions benches/bench.rs
Original file line number Diff line number Diff line change
@@ -1,105 +1,88 @@
#![feature(test)]

extern crate argon2rs;
extern crate cargon;
extern crate criterion;
extern crate libpasta;
extern crate serde_mcf;
extern crate test;
extern crate time;
use test::Bencher;

use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};

use libpasta::primitives::{Argon2, Scrypt, Primitive};
use libpasta::hashing::Algorithm;
use libpasta::primitives::{Argon2, Primitive, Scrypt};

#[bench]
fn empty(b: &mut Bencher) {
b.iter(|| 1)
}

use std::fs::File;

#[bench]
fn raw_argon2(_b: &mut Bencher) {
let _f1 = File::create("native.txt").unwrap();
let _f2 = File::create("ffi.txt").unwrap();
let reps = 10;
fn argon2_comparison(c: &mut Criterion) {
let password = [0; 16];
let salt = [1; 16];
let t_cost = 3;
let thread_test = [1, 2, 4, 8];
let thread_test = [1, 4];
let mut out = [0u8; 32];
let mut m_cost = 1 << 10;
while m_cost <= 1 << 22 {
let m_costs: Vec<u32> = (10..=14).map(|i| 1 << i).collect();

let mut group = c.benchmark_group("argon2");

for &m_cost in &m_costs {
group.throughput(Throughput::Bytes(u64::from(m_cost)));
for threads in &thread_test {
let alg = argon2rs::Argon2::new(t_cost, *threads, m_cost, argon2rs::Variant::Argon2i)
.unwrap();
group.bench_function(
BenchmarkId::from_parameter(format!("native_{}", threads)),
|b| b.iter(|| alg.hash(&mut out, &password, &salt, &[], &[])),
);
}
}

for &m_cost in &m_costs {
group.throughput(Throughput::Bytes(u64::from(m_cost)));
for threads in &thread_test {
let alg = argon2rs::Argon2::new(t_cost, *threads, m_cost, argon2rs::Variant::Argon2i)
.unwrap();
let mut alg_ffi = mk_cargon(&alg, &mut out, &password, &salt, &[], &[]);
group.bench_function(
BenchmarkId::from_parameter(format!("ffi_{}", threads)),
|b| {
b.iter(|| unsafe {
cargon::argon2_ctx(&mut alg_ffi, argon2rs::Variant::Argon2i as usize);
})
},
);
}
}

for &m_cost in &m_costs {
group.throughput(Throughput::Bytes(u64::from(m_cost)));
for threads in &thread_test {
let prim: Primitive = Argon2::new(t_cost, *threads, m_cost);
let pastalg = Algorithm::Single(prim);

let start = time::precise_time_ns();
for _ in 0..reps {
alg.hash(&mut out, &password, &salt, &[], &[]);
}
let end = time::precise_time_ns();
let native = (end - start) as f64;

let start = time::precise_time_ns();
for _ in 0..reps {
unsafe {
cargon::argon2_ctx(&mut alg_ffi, argon2rs::Variant::Argon2i as usize);
}
}
let end = time::precise_time_ns();
let ffi = (end - start) as f64;

let start = time::precise_time_ns();
for _ in 0..reps {
let _ = serde_mcf::to_string(&pastalg.hash("hunter2"));
}
let end = time::precise_time_ns();
let libp = (end - start) as f64;

println!("{} {} iterations {} MiB {} threads ... {} reps",
"Argon2i",
t_cost,
m_cost / 1024,
threads,
reps);
println!("Native: {:.4} seconds", native / 1_000_000_000f64);
println!("libpasta: {:.4} seconds", libp / 1_000_000_000f64);
println!("FFI: {:.4} seconds\n", ffi / 1_000_000_000f64);
group.bench_function(
BenchmarkId::from_parameter(format!("pasta_{}", threads)),
|b| b.iter(|| pastalg.hash_with_salt(&password, &salt)),
);
}
m_cost <<= 1;

}
}


#[bench]
fn pasta_hash_static(b: &mut Bencher) {
fn pasta_hash_static(c: &mut Criterion) {
let password = "hunter2";
b.iter(|| libpasta::hash_password(password))
c.bench_function("pasta_hash", |b| {
b.iter(|| libpasta::hash_password(password))
});
}

#[bench]
fn pasta_hash_dyn(b: &mut Bencher) {
fn pasta_hash_dyn(c: &mut Criterion) {
let password = "hunter2";
let alg = Algorithm::Single(Scrypt::new(14, 8, 1));
b.iter(|| {
alg.hash(password)
})
c.bench_function("pasta_hash_dyn_alg", |b| b.iter(|| alg.hash(password)));
}

use std::ptr;
fn mk_cargon(a2: &argon2rs::Argon2,
out: &mut [u8],
p: &[u8],
s: &[u8],
k: &[u8],
x: &[u8])
-> cargon::CargonContext {
fn mk_cargon(
a2: &argon2rs::Argon2,
out: &mut [u8],
p: &[u8],
s: &[u8],
k: &[u8],
x: &[u8],
) -> cargon::CargonContext {
let (_, kib, passes, lanes) = a2.params();
cargon::CargonContext {
out: out.as_mut_ptr(),
Expand All @@ -115,11 +98,19 @@ fn mk_cargon(a2: &argon2rs::Argon2,

t_cost: passes,
m_cost: kib,
lanes: lanes,
lanes,
threads: lanes,
version: 0x13,
allocate_fptr: ptr::null(),
deallocate_fptr: ptr::null(),
flags: cargon::ARGON2_FLAG_CLEAR_MEMORY,
}
}

criterion_group!(
benches,
pasta_hash_static,
pasta_hash_dyn,
argon2_comparison
);
criterion_main!(benches);
26 changes: 19 additions & 7 deletions examples/migrate_password.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,31 @@ fn auth_user(user: &mut User) {
user.password_hash = new_hash;
}
println!("Password correct, new hash: \n{}", user.password_hash);
},
}
HashUpdate::Failed => {
println!("Password incorrect, hash unchanged: \n{}",
user.password_hash);
println!(
"Password incorrect, hash unchanged: \n{}",
user.password_hash
);
}
}
}

fn main() {
let mut users = vec![User { password_hash: deprected_hash("hunter2") },
User { password_hash: deprected_hash("hunter3") },
User { password_hash: deprected_hash("letmein") },
User { password_hash: deprected_hash("password") }];
let mut users = vec![
User {
password_hash: deprected_hash("hunter2"),
},
User {
password_hash: deprected_hash("hunter3"),
},
User {
password_hash: deprected_hash("letmein"),
},
User {
password_hash: deprected_hash("password"),
},
];

migrate_users(&mut users);
println!("Passwords migrated: {:?}", users);
Expand Down
7 changes: 4 additions & 3 deletions examples/verify_password.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ fn auth_user(user: &User) {
let password = prompt_password_stdout("Enter password:").unwrap();
if libpasta::verify_password(&user.password_hash, &password) {
println!("The password is correct!");
// ~> Handle correct password
// ~> Handle correct password
} else {
println!("Incorrect password.");
// ~> Handle incorrect password
}
}


fn main() {
let user = User { password_hash: libpasta::hash_password("hunter2") };
let user = User {
password_hash: libpasta::hash_password("hunter2"),
};
auth_user(&user);
}
6 changes: 3 additions & 3 deletions libpasta-capi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ build = "build.rs"
[dependencies]
libc = "0.2"
libpasta = { version = "0.1.0", path = ".." }
rpassword = "2.0"
rpassword = "5.0.0"

[build-dependencies]
cbindgen = "0.6"
cbindgen = "0.15.0"

[lib]
crate-type = ["cdylib", "staticlib"]
crate-type = ["cdylib", "staticlib"]
34 changes: 18 additions & 16 deletions libpasta-capi/include/pasta-bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ typedef struct Config Config;

/**
* Password hashing primitives
*
* Each variant is backed up by different implementation.
* Internally, primitives can either be static values, for example,
* the `lazy_static` generated value `DEFAULT_PRIM`, or dynamically allocated
* variables, which are `Arc<Box<...>>`.
*
* Most operations are expected to be performed using the static functions,
* since most use the default algorithms. However, the flexibilty to support
* arbitrary parameter sets is essential.
Expand All @@ -38,20 +40,32 @@ typedef struct {
};
} HashUpdateFfi;

void config_free(Config *config);
char *read_password(const char *prompt);

char *config_hash_password(const Config *config, const char *password);
void free_string(char *s);

HashUpdateFfi *config_migrate_hash(const Config *config, const char *hash);
char *hash_password(const char *password);

Config *config_new(void);

void config_free(Config *config);

char *config_hash_password(const Config *config, const char *password);

bool verify_password(const char *hash, const char *password);

bool config_verify_password(const Config *config, const char *hash, const char *password);

HashUpdateFfi *verify_password_update_hash(const char *hash, const char *password);

HashUpdateFfi *config_verify_password_update_hash(const Config *config,
const char *hash,
const char *password);

HashUpdateFfi *migrate_hash(const char *hash);

HashUpdateFfi *config_migrate_hash(const Config *config, const char *hash);

Config *config_with_primitive(const Primitive *prim);

Primitive *default_argon2i(void);
Expand All @@ -62,22 +76,10 @@ Primitive *default_pbkdf2i(void);

Primitive *default_scrypt(void);

void free_Primitive(Primitive *prim);

void free_string(char *s);

char *hash_password(const char *password);

HashUpdateFfi *migrate_hash(const char *hash);

Primitive *new_argon2i(unsigned int passes, unsigned int lanes, unsigned int kib);

Primitive *new_bcrypt(unsigned int cost);

Primitive *new_scrypt(unsigned char log_n, unsigned int r, unsigned int p);

char *read_password(const char *prompt);

bool verify_password(const char *hash, const char *password);

HashUpdateFfi *verify_password_update_hash(const char *hash, const char *password);
void free_Primitive(Primitive *prim);
Loading

0 comments on commit da15f56

Please sign in to comment.