libpasta 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.gitmodules +3 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +37 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/Rakefile +9 -0
- data/ext/pasta-bindings/.gitmodules +3 -0
- data/ext/pasta-bindings/Makefile +84 -0
- data/ext/pasta-bindings/README.md +54 -0
- data/ext/pasta-bindings/libpasta/.gitignore +2 -0
- data/ext/pasta-bindings/libpasta/.travis.yml +60 -0
- data/ext/pasta-bindings/libpasta/Cargo.toml +42 -0
- data/ext/pasta-bindings/libpasta/LICENSE.md +21 -0
- data/ext/pasta-bindings/libpasta/Makefile +27 -0
- data/ext/pasta-bindings/libpasta/README.md +78 -0
- data/ext/pasta-bindings/libpasta/benches/bench.rs +125 -0
- data/ext/pasta-bindings/libpasta/examples/alternate_key_source.rs +33 -0
- data/ext/pasta-bindings/libpasta/examples/config.rs +10 -0
- data/ext/pasta-bindings/libpasta/examples/config_hmac.rs +25 -0
- data/ext/pasta-bindings/libpasta/examples/hash_password.rs +10 -0
- data/ext/pasta-bindings/libpasta/examples/migrate_password.rs +47 -0
- data/ext/pasta-bindings/libpasta/examples/verify_password.rs +24 -0
- data/ext/pasta-bindings/libpasta/libpasta-capi/Cargo.toml +12 -0
- data/ext/pasta-bindings/libpasta/libpasta-capi/ctest/compile +6 -0
- data/ext/pasta-bindings/libpasta/libpasta-capi/ctest/test +0 -0
- data/ext/pasta-bindings/libpasta/libpasta-capi/ctest/test.c +12 -0
- data/ext/pasta-bindings/libpasta/libpasta-capi/include/pasta.h +6 -0
- data/ext/pasta-bindings/libpasta/libpasta-capi/src/lib.rs +80 -0
- data/ext/pasta-bindings/libpasta/src/bench.rs +39 -0
- data/ext/pasta-bindings/libpasta/src/config.rs +358 -0
- data/ext/pasta-bindings/libpasta/src/hashing/de.rs +284 -0
- data/ext/pasta-bindings/libpasta/src/hashing/mod.rs +161 -0
- data/ext/pasta-bindings/libpasta/src/hashing/ser.rs +67 -0
- data/ext/pasta-bindings/libpasta/src/key/mod.rs +66 -0
- data/ext/pasta-bindings/libpasta/src/lib.rs +468 -0
- data/ext/pasta-bindings/libpasta/src/primitives/argon2.rs +180 -0
- data/ext/pasta-bindings/libpasta/src/primitives/bcrypt.rs +165 -0
- data/ext/pasta-bindings/libpasta/src/primitives/hmac.rs +134 -0
- data/ext/pasta-bindings/libpasta/src/primitives/mod.rs +312 -0
- data/ext/pasta-bindings/libpasta/src/primitives/pbkdf2.rs +272 -0
- data/ext/pasta-bindings/libpasta/src/primitives/scrypt.rs +144 -0
- data/ext/pasta-bindings/libpasta/src/sod.rs +46 -0
- data/ext/pasta-bindings/libpasta/tests/.libpasta.yaml +8 -0
- data/ext/pasta-bindings/libpasta/tests/common/mod.rs +37 -0
- data/ext/pasta-bindings/libpasta/tests/test_argon2.rs +8 -0
- data/ext/pasta-bindings/libpasta/tests/test_bcrypt.rs +8 -0
- data/ext/pasta-bindings/libpasta/tests/test_from_file.rs +13 -0
- data/ext/pasta-bindings/libpasta/tests/test_hmac.rs +26 -0
- data/ext/pasta-bindings/libpasta/tests/test_pbkdf2.rs +8 -0
- data/ext/pasta-bindings/libpasta/tests/test_ringpbkdf2.rs +8 -0
- data/ext/pasta-bindings/libpasta/tests/test_scrypt.rs +8 -0
- data/ext/pasta-bindings/pasta.i +31 -0
- data/ext/pasta-bindings/tests/Makefile +38 -0
- data/ext/pasta-bindings/tests/pasta_test.go +12 -0
- data/ext/pasta-bindings/tests/test.php +7 -0
- data/ext/pasta-bindings/tests/test.py +7 -0
- data/ext/pasta-bindings/tests/test.rb +5 -0
- data/lib/libpasta.rb +2 -0
- data/lib/libpasta/version.rb +3 -0
- data/libpasta.gemspec +52 -0
- data/spec/libpasta_spec.rb +11 -0
- data/spec/spec_helper.rb +11 -0
- metadata +183 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 Sam Scott
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
VERSION = 0.0.5
|
2
|
+
|
3
|
+
all: libpasta.so libpasta.a
|
4
|
+
|
5
|
+
clean:
|
6
|
+
rm -rf build/
|
7
|
+
|
8
|
+
force:
|
9
|
+
cargo clean --manifest-path libpasta-capi/Cargo.toml
|
10
|
+
make clean
|
11
|
+
make default
|
12
|
+
|
13
|
+
libpasta: Cargo.toml libpasta-capi/Cargo.toml
|
14
|
+
cargo build --release --manifest-path libpasta-capi/Cargo.toml
|
15
|
+
|
16
|
+
libpasta.%: libpasta
|
17
|
+
mkdir -p build
|
18
|
+
cp libpasta-capi/target/release/$@ build/$@
|
19
|
+
|
20
|
+
install: libpasta.so
|
21
|
+
sudo install -D -m0755 build/libpasta.so /usr/lib/libpasta.so.${VERSION}
|
22
|
+
sudo ln -sf /usr/lib/libpasta.so.${VERSION} /usr/lib/libpasta.so
|
23
|
+
|
24
|
+
uninstall:
|
25
|
+
sudo rm /usr/lib/libpasta.so.$(VERSION)
|
26
|
+
|
27
|
+
.PHONY: clean uninstall
|
@@ -0,0 +1,78 @@
|
|
1
|
+
libpasta - Password Storage Algorithms
|
2
|
+
===================================
|
3
|
+
|
4
|
+
[![Build Status][build_badge]][build_status]
|
5
|
+
[![Code Coverage][coverage_badge]][coverage_report]
|
6
|
+
|
7
|
+
#### _Making Password Painless_
|
8
|
+
|
9
|
+
This library aims to be a all-in-one solution for password storage. In
|
10
|
+
particular, we aim to provide:
|
11
|
+
|
12
|
+
- Easy-to-use password storage with sane defaults.
|
13
|
+
- Tools to provide parameter tuning for different use cases.
|
14
|
+
- Automatic migration of password hashes to new algorithms.
|
15
|
+
|
16
|
+
|
17
|
+
## Introduction
|
18
|
+
|
19
|
+
libpasta is designed to be as simple to use as possible. Most users would rather
|
20
|
+
not have to choose which password algorithm to use, nor understand what
|
21
|
+
are the best parameter choices.
|
22
|
+
|
23
|
+
Therefore, we take great care to make this all opaque to the user:
|
24
|
+
|
25
|
+
```rust
|
26
|
+
let password = "hunter2".owned();
|
27
|
+
let hash = hash_password(password);
|
28
|
+
// store hash in database
|
29
|
+
// ... time passes, user returns ...
|
30
|
+
let password = "hunter2".owned();
|
31
|
+
if verify_password(password, &hash) {
|
32
|
+
// do something
|
33
|
+
}
|
34
|
+
```
|
35
|
+
|
36
|
+
## Installation
|
37
|
+
|
38
|
+
To build the `libpasta` system library, simply run `make`. This outputs
|
39
|
+
a `build/libpasta.so` file (or system-appropriate filename).
|
40
|
+
|
41
|
+
You can also try running `make install` to automatically move it to the correct
|
42
|
+
location.
|
43
|
+
|
44
|
+
The library is generated as a result of building [libpasta-capi](libpasta-capi/),
|
45
|
+
which is a C-API wrapper built around the Rust code.
|
46
|
+
|
47
|
+
### The rest of this README is dedicated to developing the code. For more about the library, and examples, please see: https://libpasta.github.io/ or the [documentation](https://docs.rs/libpasta/).
|
48
|
+
|
49
|
+
## Roadmap
|
50
|
+
|
51
|
+
libpasta is still currently in development. The current version is `0.0.1`
|
52
|
+
representing a pre-release. After gathering some initial feedback we will
|
53
|
+
move to `0.1.0` release, at which point libpasta will be ready to use in
|
54
|
+
test environments. We are targetting a stable `1.0.0` release once the API
|
55
|
+
is stable, and testing reveals no major issues.
|
56
|
+
|
57
|
+
## Contributing
|
58
|
+
|
59
|
+
libpasta is still in its infancy, and the best way to contribute right now is
|
60
|
+
to start testing it in new projects.
|
61
|
+
|
62
|
+
Please feel free to open new issues or pull requests for any bugs found, feature
|
63
|
+
requests, or general suggestions.
|
64
|
+
|
65
|
+
We very much welcome any contributions, and simply ask for patience and civility
|
66
|
+
when dealing with any disagreements or problems.
|
67
|
+
|
68
|
+
## License
|
69
|
+
|
70
|
+
libpasta is licensed under the MIT license: [License](license).
|
71
|
+
|
72
|
+
|
73
|
+
[build_badge]: https://travis-ci.org/libpasta/libpasta.svg?branch=master
|
74
|
+
[build_status]: https://travis-ci.org/libpasta/libpasta
|
75
|
+
[coverage_badge]: https://codecov.io/gh/libpasta/libpasta/graph/badge.svg
|
76
|
+
[coverage_report]: https://codecov.io/gh/libpasta/libpasta/
|
77
|
+
[documentation]: https://libpasta.github.io/doc/libpasta/
|
78
|
+
[license]: LICENSE.md
|
@@ -0,0 +1,125 @@
|
|
1
|
+
#![feature(test)]
|
2
|
+
|
3
|
+
extern crate argon2rs;
|
4
|
+
extern crate cargon;
|
5
|
+
extern crate libpasta;
|
6
|
+
extern crate serde_mcf;
|
7
|
+
extern crate test;
|
8
|
+
extern crate time;
|
9
|
+
use test::Bencher;
|
10
|
+
|
11
|
+
|
12
|
+
use libpasta::primitives::{Argon2, Scrypt, Primitive};
|
13
|
+
use libpasta::hashing::Algorithm;
|
14
|
+
|
15
|
+
#[bench]
|
16
|
+
fn empty(b: &mut Bencher) {
|
17
|
+
b.iter(|| 1)
|
18
|
+
}
|
19
|
+
|
20
|
+
use std::fs::File;
|
21
|
+
|
22
|
+
#[bench]
|
23
|
+
fn raw_argon2(_b: &mut Bencher) {
|
24
|
+
let _f1 = File::create("native.txt").unwrap();
|
25
|
+
let _f2 = File::create("ffi.txt").unwrap();
|
26
|
+
let reps = 10;
|
27
|
+
let password = [0; 16];
|
28
|
+
let salt = [1; 16];
|
29
|
+
let t_cost = 3;
|
30
|
+
let thread_test = [1, 2, 4, 8];
|
31
|
+
let mut out = [0u8; 32];
|
32
|
+
let mut m_cost = 1 << 10;
|
33
|
+
while m_cost <= 1 << 22 {
|
34
|
+
for threads in &thread_test {
|
35
|
+
let alg = argon2rs::Argon2::new(t_cost, *threads, m_cost, argon2rs::Variant::Argon2i)
|
36
|
+
.unwrap();
|
37
|
+
let mut alg_ffi = mk_cargon(&alg, &mut out, &password, &salt, &[], &[]);
|
38
|
+
let prim: Primitive = Argon2::new(t_cost, *threads, m_cost);
|
39
|
+
let pastalg = Algorithm::Single(prim);
|
40
|
+
|
41
|
+
let start = time::precise_time_ns();
|
42
|
+
for _ in 0..reps {
|
43
|
+
alg.hash(&mut out, &password, &salt, &[], &[]);
|
44
|
+
}
|
45
|
+
let end = time::precise_time_ns();
|
46
|
+
let native = (end - start) as f64;
|
47
|
+
|
48
|
+
let start = time::precise_time_ns();
|
49
|
+
for _ in 0..reps {
|
50
|
+
unsafe {
|
51
|
+
cargon::argon2_ctx(&mut alg_ffi, argon2rs::Variant::Argon2i as usize);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
let end = time::precise_time_ns();
|
55
|
+
let ffi = (end - start) as f64;
|
56
|
+
|
57
|
+
let start = time::precise_time_ns();
|
58
|
+
for _ in 0..reps {
|
59
|
+
let _ = serde_mcf::to_string(&pastalg.hash("hunter2"));
|
60
|
+
}
|
61
|
+
let end = time::precise_time_ns();
|
62
|
+
let libp = (end - start) as f64;
|
63
|
+
|
64
|
+
println!("{} {} iterations {} MiB {} threads ... {} reps",
|
65
|
+
"Argon2i",
|
66
|
+
t_cost,
|
67
|
+
m_cost / 1024,
|
68
|
+
threads,
|
69
|
+
reps);
|
70
|
+
println!("Native: {:.4} seconds", native / 1_000_000_000f64);
|
71
|
+
println!("libpasta: {:.4} seconds", libp / 1_000_000_000f64);
|
72
|
+
println!("FFI: {:.4} seconds\n", ffi / 1_000_000_000f64);
|
73
|
+
}
|
74
|
+
m_cost <<= 1;
|
75
|
+
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
|
80
|
+
#[bench]
|
81
|
+
fn pasta_hash_static(b: &mut Bencher) {
|
82
|
+
let password = "hunter2";
|
83
|
+
b.iter(|| libpasta::hash_password(password))
|
84
|
+
}
|
85
|
+
|
86
|
+
#[bench]
|
87
|
+
fn pasta_hash_dyn(b: &mut Bencher) {
|
88
|
+
let password = "hunter2";
|
89
|
+
let alg = Algorithm::Single(Scrypt::new(14, 8, 1));
|
90
|
+
b.iter(|| {
|
91
|
+
alg.hash(password)
|
92
|
+
})
|
93
|
+
}
|
94
|
+
|
95
|
+
use std::ptr;
|
96
|
+
fn mk_cargon(a2: &argon2rs::Argon2,
|
97
|
+
out: &mut [u8],
|
98
|
+
p: &[u8],
|
99
|
+
s: &[u8],
|
100
|
+
k: &[u8],
|
101
|
+
x: &[u8])
|
102
|
+
-> cargon::CargonContext {
|
103
|
+
let (_, kib, passes, lanes) = a2.params();
|
104
|
+
cargon::CargonContext {
|
105
|
+
out: out.as_mut_ptr(),
|
106
|
+
outlen: out.len() as u32,
|
107
|
+
pwd: p.as_ptr(),
|
108
|
+
pwdlen: p.len() as u32,
|
109
|
+
salt: s.as_ptr(),
|
110
|
+
saltlen: s.len() as u32,
|
111
|
+
secret: k.as_ptr(),
|
112
|
+
secretlen: k.len() as u32,
|
113
|
+
ad: x.as_ptr(),
|
114
|
+
adlen: x.len() as u32,
|
115
|
+
|
116
|
+
t_cost: passes,
|
117
|
+
m_cost: kib,
|
118
|
+
lanes: lanes,
|
119
|
+
threads: lanes,
|
120
|
+
version: 0x13,
|
121
|
+
allocate_fptr: ptr::null(),
|
122
|
+
deallocate_fptr: ptr::null(),
|
123
|
+
flags: cargon::ARGON2_FLAG_CLEAR_MEMORY,
|
124
|
+
}
|
125
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
extern crate libpasta;
|
2
|
+
extern crate ring;
|
3
|
+
|
4
|
+
use libpasta::key;
|
5
|
+
use ring::digest;
|
6
|
+
|
7
|
+
#[derive(Debug)]
|
8
|
+
struct StaticSource(&'static [u8; 16]);
|
9
|
+
static STATIC_SOURCE: StaticSource = StaticSource(b"ThisIsAStaticKey");
|
10
|
+
|
11
|
+
impl key::Store for StaticSource {
|
12
|
+
/// Insert a new key into the `Store`.
|
13
|
+
fn insert(&self, _key: &[u8]) -> String {
|
14
|
+
"StaticKey".to_string()
|
15
|
+
}
|
16
|
+
|
17
|
+
/// Get a key from the `Store`.
|
18
|
+
fn get_key(&self, _id: &str) -> Option<Vec<u8>> {
|
19
|
+
Some(self.0.to_vec())
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
fn main() {
|
24
|
+
let mut config = libpasta::Config::default();
|
25
|
+
config.set_key_source(&STATIC_SOURCE);
|
26
|
+
|
27
|
+
// Construct an HMAC instance and use this as the outer configuration
|
28
|
+
let keyed_function = libpasta::primitives::Hmac::with_key_id(&digest::SHA256, "StaticKey");
|
29
|
+
config.set_keyed_hash(keyed_function);
|
30
|
+
|
31
|
+
let hash = config.hash_password("hunter2");
|
32
|
+
println!("Computed hash: {:?}", hash);
|
33
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
extern crate libpasta;
|
2
|
+
|
3
|
+
use libpasta::primitives::Bcrypt;
|
4
|
+
|
5
|
+
fn main() {
|
6
|
+
let config = libpasta::Config::with_primitive(Bcrypt::new(15));
|
7
|
+
let password_hash = config.hash_password("hunter2");
|
8
|
+
println!("The hashed password is: '{}'", password_hash);
|
9
|
+
// Prints bcrypt hash
|
10
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
extern crate libpasta;
|
2
|
+
extern crate ring;
|
3
|
+
|
4
|
+
use ring::digest;
|
5
|
+
|
6
|
+
fn main() {
|
7
|
+
// Use scrypt as the default inner hash
|
8
|
+
let hash_primitive = libpasta::primitives::Scrypt::default();
|
9
|
+
let mut config = libpasta::Config::with_primitive(hash_primitive);
|
10
|
+
|
11
|
+
// Some proper way of getting a key
|
12
|
+
let key = b"yellow submarine";
|
13
|
+
let key_id = config.add_key(key);
|
14
|
+
// Construct an HMAC instance and use this as the outer configuration
|
15
|
+
let keyed_function = libpasta::primitives::Hmac::with_key_id(&digest::SHA256, &key_id);
|
16
|
+
config.set_keyed_hash(keyed_function);
|
17
|
+
|
18
|
+
let hash = config.hash_password("hunter2");
|
19
|
+
println!("Computed hash: {:?}", hash);
|
20
|
+
// Outputs:
|
21
|
+
// Computed hash: "$!$hmac$key_id=LNMhDy...,h=SHA256$$scrypt$ln=14,r=8,p=1$ZJ5EY...$grlNA...."
|
22
|
+
|
23
|
+
assert!(hash.starts_with("$!$hmac"));
|
24
|
+
assert!(hash.contains("scrypt"));
|
25
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
extern crate libpasta;
|
2
|
+
|
3
|
+
// We re-export the rpassword crate for CLI password input.
|
4
|
+
use libpasta::rpassword::*;
|
5
|
+
|
6
|
+
fn main() {
|
7
|
+
let password = prompt_password_stdout("Please enter your password:").unwrap();
|
8
|
+
let password_hash = libpasta::hash_password(&password);
|
9
|
+
println!("The hashed password is: '{}'", password_hash);
|
10
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
extern crate libpasta;
|
2
|
+
use libpasta::rpassword::*;
|
3
|
+
|
4
|
+
#[derive(Debug)]
|
5
|
+
struct User {
|
6
|
+
// ...
|
7
|
+
password_hash: String,
|
8
|
+
}
|
9
|
+
|
10
|
+
fn migrate_users(users: &mut [User]) {
|
11
|
+
// Step 1: Wrap old hash
|
12
|
+
for user in users {
|
13
|
+
libpasta::migrate_hash(&mut user.password_hash);
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
fn auth_user(user: &mut User) {
|
18
|
+
// Step 2: Update algorithm during log in
|
19
|
+
let password = prompt_password_stdout("Enter password:").unwrap();
|
20
|
+
if libpasta::verify_password_update_hash(&mut user.password_hash, &password) {
|
21
|
+
println!("Password correct, new hash: \n{}", user.password_hash);
|
22
|
+
} else {
|
23
|
+
println!("Password incorrect, hash unchanged: \n{}",
|
24
|
+
user.password_hash);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
fn main() {
|
29
|
+
let mut users = vec![User { password_hash: deprected_hash("hunter2") },
|
30
|
+
User { password_hash: deprected_hash("hunter3") },
|
31
|
+
User { password_hash: deprected_hash("letmein") },
|
32
|
+
User { password_hash: deprected_hash("password") }];
|
33
|
+
|
34
|
+
migrate_users(&mut users);
|
35
|
+
println!("Passwords migrated: {:?}", users);
|
36
|
+
auth_user(&mut users[0]);
|
37
|
+
}
|
38
|
+
|
39
|
+
// Do not use this code as a good example of how to do hashing.
|
40
|
+
// This is intentionally awkward
|
41
|
+
use libpasta::{hashing, primitives};
|
42
|
+
extern crate serde_mcf;
|
43
|
+
|
44
|
+
fn deprected_hash(password: &str) -> String {
|
45
|
+
let alg = hashing::Algorithm::Single(primitives::Bcrypt::default());
|
46
|
+
serde_mcf::to_string(&alg.hash(password)).unwrap()
|
47
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
extern crate libpasta;
|
2
|
+
use libpasta::rpassword::*;
|
3
|
+
|
4
|
+
struct User {
|
5
|
+
// ...
|
6
|
+
password_hash: String,
|
7
|
+
}
|
8
|
+
|
9
|
+
fn auth_user(user: &User) {
|
10
|
+
let password = prompt_password_stdout("Enter password:").unwrap();
|
11
|
+
if libpasta::verify_password(&user.password_hash, &password) {
|
12
|
+
println!("The password is correct!");
|
13
|
+
// ~> Handle correct password
|
14
|
+
} else {
|
15
|
+
println!("Incorrect password.");
|
16
|
+
// ~> Handle incorrect password
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
fn main() {
|
22
|
+
let user = User { password_hash: libpasta::hash_password("hunter2") };
|
23
|
+
auth_user(&user);
|
24
|
+
}
|
Binary file
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#include <assert.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
#include "pasta.h"
|
4
|
+
|
5
|
+
int main(void) {
|
6
|
+
char *hash;
|
7
|
+
hash = hash_password("hello123");
|
8
|
+
assert (verify_password(hash, "hello123"));
|
9
|
+
printf("\x1b[1;32mC test passed\x1b[m\n");
|
10
|
+
free_string(hash);
|
11
|
+
return 0;
|
12
|
+
}
|