Skip to content

Commit

Permalink
build (warning-free) on modern Rust and deps (#11)
Browse files Browse the repository at this point in the history
* profile.debug should be profile.dev

profile.dev apparently was always the proper name in spite of some
confusion in cargo (see rust-lang/cargo#3519).

With Rust 1.48.0, cargo refuses to build with a [profile.debug],
saying you need the named-profiles nightly feature for that.

* update most deps, notably ring

ring folks think it's quite important to stay current:
https://github.com/briansmith/ring#versioning--stability
so update, catching up on two years of ring API changes:

* ring's "std" feature is roughly equivalent to the previous "new-heap".
  It's required for ring::error::Unspecified to impl Error as expected
  by libpasta's error_chain! block.

* hkdf uses hkdf::Salt rather than directly operating on an
  hmac::SigningKey (9addfcebdf).

* hkdf::extract_and_expand is gone, in favor of methods (6ec8f34c57).

* SystemRandom must be constructed with new (f31f41d7a5).

* hmac, hkdf, and pbdf2 use distinct Algorithm types (169803f490).
  A few interesting points here:
  * I took out a branch from hash_from_id when updating this: SHA512_256
    doesn't map to a hkdf type. It was effectively dead; the caller
    (Pbkdf2::hash_id) would panic on encountering it.
  * I changed hash_to_id to not rely on ring's Debug that has no
    guarantee of stability.
  * I changed Pbkdf2's Debug output slightly, as a
    ring::pbkdf2::Algorithm is inconvenient to use as before (no
    Debug impl or access to underlying type). This should be the only
    visible behavior change.

There were no code changes necessary for the other dep updates.

I left the "time" crate alone.

* cargo +nightly fix

This fixed a bunch of warnings, particularly adding "dyn" to trait
refs and a couple renamed lints.

* stop referencing obsolete plugin_as_library lint

Addresses this warning:
warning: lint `plugin_as_library` has been removed: `plugins have been deprecated and retired`

This one wasn't automatically fixed by "cargo +nightly fix"; maybe
it only does the renames and not the removals.
  • Loading branch information
scottlamb committed Nov 29, 2020
1 parent 6a7bcd9 commit e246a8f
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 107 deletions.
28 changes: 14 additions & 14 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,35 @@ repository = "https://github.com/libpasta/libpasta"

[dependencies]
argon2rs = "0.2.5"
data-encoding = "2.1.2"
error-chain = "0.12.0"
lazy_static = "1.2.0"
log = "0.4.6"
num-traits = "0.2.6"
rpassword = "2.1.0"
data-encoding = "2.3.1"
error-chain = "0.12.4"
lazy_static = "1.4.0"
log = "0.4.11"
num-traits = "0.2.14"
rpassword = "5.0.0"
rust-crypto = "0.2.36"
serde = { version = "1.0.85", features = ["serde_derive"]}
serde = { version = "1.0.117", features = ["serde_derive"] }
serde_mcf = "0.1.3"
serde_yaml = "0.8.8"
scrypt = "0.2.0"
serde_yaml = "0.8.14"
scrypt = "0.5.0"

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

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

[features]
bench = []
long_tests = []
simd = ["argon2rs/simd"]

[profile.debug]
[profile.dev]
opt-level = 2

[profile.test]
opt-level = 2
opt-level = 2
4 changes: 2 additions & 2 deletions examples/alternate_key_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ extern crate libpasta;
extern crate ring;

use libpasta::key;
use ring::digest;
use ring::hkdf;

#[derive(Debug)]
struct StaticSource(&'static [u8; 16]);
Expand All @@ -25,7 +25,7 @@ fn main() {
config.set_key_source(&STATIC_SOURCE);

// Construct an HMAC instance and use this as the outer configuration
let keyed_function = libpasta::primitives::Hmac::with_key_id(&digest::SHA256, "StaticKey");
let keyed_function = libpasta::primitives::Hmac::with_key_id(hkdf::HKDF_SHA256, "StaticKey");
config.set_keyed_hash(keyed_function);

let hash = config.hash_password("hunter2");
Expand Down
4 changes: 2 additions & 2 deletions examples/config_hmac.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate libpasta;
extern crate ring;

use ring::digest;
use ring::hkdf;

fn main() {
// Use scrypt as the default inner hash
Expand All @@ -12,7 +12,7 @@ fn main() {
let key = b"yellow submarine";
let key_id = config.add_key(key);
// Construct an HMAC instance and use this as the outer configuration
let keyed_function = libpasta::primitives::Hmac::with_key_id(&digest::SHA256, &key_id);
let keyed_function = libpasta::primitives::Hmac::with_key_id(hkdf::HKDF_SHA256, &key_id);
config.set_keyed_hash(keyed_function);

let hash = config.hash_password("hunter2");
Expand Down
42 changes: 20 additions & 22 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//! There are a number of ways panics can happen through using the configuration
//! files. `libpasta` does not try to recover gracefully if
use lazy_static;
use ring::{digest, hkdf, hmac, rand};
use ring::{hkdf, rand};
use ring::rand::SecureRandom;
use serde_mcf;
use serde_yaml;
Expand All @@ -24,31 +24,30 @@ use key;
use errors::*;
use hashing::{Algorithm, Output};
use primitives::{self, Primitive};
use sod::Sod;

use std::default::Default;
use std::fs::File;
use std::marker::{Send, Sync};
use std::path::Path;
use std::io::BufReader;
use std::sync::{Arc, Mutex};

static RAND_REF: &'static (SecureRandom + Send + Sync) = &rand::SystemRandom;
lazy_static! {
/// Global source of randomness for generating salts
pub static ref RANDOMNESS_SOURCE: Sod<SecureRandom + Send + Sync> = {
pub static ref RANDOMNESS_SOURCE: rand::SystemRandom = {
lazy_static::initialize(&RAND_BACKUP);
Sod::Static(RAND_REF)
rand::SystemRandom::new()
};

/// Backup PRNG source for when `SystemRandom`is unavailable
/// Backup PRNG source for when `SystemRandom` is unavailable
static ref RAND_BACKUP: Arc<Mutex<BackupPrng>> = {
let rng = rand::SystemRandom::new();
let mut seed = [0_u8; 32];
let mut salt_key_value = [0_u8; 32];
rng.fill(&mut seed).expect("could not generate any randomness");
rng.fill(&mut salt_key_value).expect("could not generate any randomness");
Arc::new(Mutex::new(BackupPrng {
salt: hmac::SigningKey::generate(&digest::SHA256, &rng).expect("could not generate any randomness"),
seed: seed,
salt: hkdf::Salt::new(hkdf::HKDF_SHA256, &salt_key_value[..]),
seed,
}))
};

Expand Down Expand Up @@ -78,7 +77,7 @@ pub struct Config {
primitive: Primitive,
keyed: Option<Primitive>,
#[serde(skip, default = "key::get_global")]
keys: &'static key::Store,
keys: &'static dyn key::Store,
}


Expand Down Expand Up @@ -258,7 +257,7 @@ impl Config {
}

/// Sets the location of keys for keyed functions.
pub fn set_key_source(&mut self, store: &'static key::Store) {
pub fn set_key_source(&mut self, store: &'static dyn key::Store) {
self.keys = store;
}

Expand All @@ -270,21 +269,20 @@ impl Config {
}

struct BackupPrng {
salt: hmac::SigningKey,
salt: hkdf::Salt,
seed: [u8; 32],
}

impl BackupPrng {
fn gen_salt(&mut self) -> Vec<u8> {
let mut output = vec![0_u8; 48];
hkdf::extract_and_expand(
&self.salt,
&self.seed,
b"libpasta backup PRNG",
&mut output
);
self.seed.copy_from_slice(&output[16..]);
output.truncate(16);
let mut buf = [0_u8; 48];
let alg = self.salt.algorithm();
self.salt.extract(&self.seed)
.expand(&[b"libpasta backup PRNG"], alg).expect("expand failure")
.fill(&mut buf[..]).expect("fill failure");
self.seed.copy_from_slice(&buf[16..]);
let mut output = Vec::with_capacity(16);
output.extend_from_slice(&buf[0..16]);
output
}
}
Expand Down Expand Up @@ -334,7 +332,7 @@ mod test {
config.set_key_source(&STATIC_SOURCE);
let id = config.add_key(&[]);
assert_eq!(config.get_key(&id), Some(b"ThisIsAStaticKey".to_vec()));
let hmac = primitives::Hmac::with_key_id(&ring::digest::SHA256, "dummy");
let hmac = primitives::Hmac::with_key_id(ring::hkdf::HKDF_SHA256, "dummy");
config.set_keyed_hash(hmac);
let hash = config.hash_password("hunter2");
assert!(config.verify_password_safe(&hash, "hunter2").unwrap())
Expand Down
2 changes: 1 addition & 1 deletion src/hashing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl Output {
impl Algorithm {
/// Type-safe function to compute the hash of a password.
pub fn hash(&self, password: &str) -> Output {
let salt = super::gen_salt(&**config::RANDOMNESS_SOURCE);
let salt = super::gen_salt(&*config::RANDOMNESS_SOURCE);
let output = self.hash_with_salt(password.as_bytes(), &salt);
Output {
hash: output,
Expand Down
7 changes: 3 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
const_err,
dead_code,
deprecated,
exceeding_bitshifts,
arithmetic_overflow,
improper_ctypes,
missing_docs,
mutable_transmutes,
Expand All @@ -66,7 +66,6 @@
non_upper_case_globals,
overflowing_literals,
path_statements,
plugin_as_library,
stable_features,
trivial_numeric_casts,
unconditional_recursion,
Expand Down Expand Up @@ -262,7 +261,7 @@ pub fn migrate_hash_safe(hash: &str) -> Result<Option<String>> {

}

fn gen_salt(rng: &SecureRandom) -> Vec<u8> {
fn gen_salt(rng: &dyn SecureRandom) -> Vec<u8> {
let mut salt = vec![0_u8; 16];
if rng.fill(&mut salt).is_ok() {
salt
Expand All @@ -277,7 +276,7 @@ use ring::rand::SystemRandom;

#[cfg(test)]
fn get_salt() -> Vec<u8> {
gen_salt(&SystemRandom)
gen_salt(&SystemRandom::new())
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion src/primitives/bcrypt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ mod native {
}

lazy_static! {
static ref DEFAULT: Arc<Box<PrimitiveImpl>> = {
static ref DEFAULT: Arc<Box<dyn PrimitiveImpl>> = {
Arc::new(Box::new(Bcrypt::new_impl(12)))
};
}
Expand Down
36 changes: 20 additions & 16 deletions src/primitives/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ mod hmac_ring {
use key::Store;
use primitives::Primitive;

use ring::{digest, hkdf, hmac, rand};
use ring::{hkdf, rand};
use ring::rand::SecureRandom as _;
use serde_mcf::Hashes;

use std::fmt;
Expand All @@ -17,17 +18,17 @@ mod hmac_ring {
/// This struct holds the parameters used.
/// Represents the `ring` implementation.
pub struct Hmac {
h: &'static digest::Algorithm,
key: Option<hmac::SigningKey>,
algorithm: hkdf::Algorithm,
salt: Option<hkdf::Salt>,
key_id: String,
}

impl Hmac {
/// Construct a new `Hmac` instance with a specified key identifier
pub fn with_key_id(h: &'static digest::Algorithm, key_id: &str) -> Primitive {
pub fn with_key_id(algorithm: hkdf::Algorithm, key_id: &str) -> Primitive {
Self {
h,
key: key::get_global().get_key(key_id).map(|k| hmac::SigningKey::new(h, &k)),
algorithm,
salt: key::get_global().get_key(key_id).map(|k| hkdf::Salt::new(algorithm, &k)),
key_id: key_id.to_string(),
}.into()
}
Expand All @@ -40,12 +41,13 @@ mod hmac_ring {
fn new() -> Self {
let rng = rand::SystemRandom::new();
let mut key_bytes = [0_u8; 32];
let key = hmac::SigningKey::generate_serializable(&digest::SHA256, &rng, &mut key_bytes)
.expect("could not generate random bytes for key");
rng.fill(&mut key_bytes).expect("could not generate random bytes for key");
let algorithm = hkdf::HKDF_SHA256;
let salt = hkdf::Salt::new(algorithm, &key_bytes[..]);
let key_id = key::get_global().insert(&key_bytes);
Self {
h: &digest::SHA256,
key: Some(key),
algorithm,
salt: Some(salt),
key_id,
}
}
Expand All @@ -55,16 +57,18 @@ mod hmac_ring {
/// Compute the scrypt hash
fn compute(&self, password: &[u8], _salt: &[u8]) -> Vec<u8> {
let mut hash = vec![0_u8; 32];
let key = self.key.as_ref().expect_report("key not found");
hkdf::extract_and_expand(key, password, b"libpasta password hashing", &mut hash);
let salt = self.salt.as_ref().expect_report("key not found");
salt.extract(password)
.expand(&[b"libpasta password hashing"], salt.algorithm()).expect("expand failure")
.fill(&mut hash).expect("fill failure");
hash
}

/// Convert parameters into a vector of (key, value) tuples
/// for serializing.
fn params_as_vec(&self) -> Vec<(&'static str, String)> {
vec![("key_id", self.key_id.clone()),
("h", super::super::hash_to_id(self.h))]
("h", super::super::hash_to_id(self.algorithm))]
}

fn hash_id(&self) -> Hashes {
Expand All @@ -73,8 +77,8 @@ mod hmac_ring {

fn update_key(&self, config: &config::Config) -> Option<Primitive> {
Some(Self {
h: self.h,
key: config.get_key(&self.key_id).map(|k| hmac::SigningKey::new(self.h, &k)),
algorithm: self.algorithm,
salt: config.get_key(&self.key_id).map(|k| hkdf::Salt::new(self.algorithm, &k)),
key_id: self.key_id.clone(),
}.into())
}
Expand All @@ -85,7 +89,7 @@ mod hmac_ring {
write!(f,
"Hmac, KeyID: {}, Hash: {}",
self.key_id,
super::super::hash_to_id(self.h))
super::super::hash_to_id(self.algorithm))
}
}
}
Expand Down
Loading

0 comments on commit e246a8f

Please sign in to comment.