Merge branch 'no-string-error' into 'master'
Use structs for errors instead of plain strings Closes #3 See merge request lumi/sasl-rs!8
This commit is contained in:
commit
5550148149
10 changed files with 365 additions and 107 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use getrandom::{getrandom, Error as RngError};
|
||||
use hmac::{Hmac, Mac};
|
||||
use hmac::{crypto_mac::InvalidKeyLength, Hmac, Mac};
|
||||
use pbkdf2::pbkdf2;
|
||||
use sha1::{Digest, Sha1 as Sha1_hash};
|
||||
use sha2::Sha256 as Sha256_hash;
|
||||
|
|
@ -17,6 +17,29 @@ pub fn generate_nonce() -> Result<String, RngError> {
|
|||
Ok(base64::encode(&data))
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DeriveError {
|
||||
IncompatibleHashingMethod(String, String),
|
||||
IncorrectSalt,
|
||||
IncompatibleIterationCount(usize, usize),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for DeriveError {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
DeriveError::IncompatibleHashingMethod(one, two) => {
|
||||
write!(fmt, "incompatible hashing method, {} is not {}", one, two)
|
||||
}
|
||||
DeriveError::IncorrectSalt => write!(fmt, "incorrect salt"),
|
||||
DeriveError::IncompatibleIterationCount(one, two) => {
|
||||
write!(fmt, "incompatible iteration count, {} is not {}", one, two)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for DeriveError {}
|
||||
|
||||
/// A trait which defines the needed methods for SCRAM.
|
||||
pub trait ScramProvider {
|
||||
/// The kind of secret this `ScramProvider` requires.
|
||||
|
|
@ -29,10 +52,10 @@ pub trait ScramProvider {
|
|||
fn hash(data: &[u8]) -> Vec<u8>;
|
||||
|
||||
/// A function which performs an HMAC using the hash function.
|
||||
fn hmac(data: &[u8], key: &[u8]) -> Result<Vec<u8>, String>;
|
||||
fn hmac(data: &[u8], key: &[u8]) -> Result<Vec<u8>, InvalidKeyLength>;
|
||||
|
||||
/// A function which does PBKDF2 key derivation using the hash function.
|
||||
fn derive(data: &Password, salt: &[u8], iterations: usize) -> Result<Vec<u8>, String>;
|
||||
fn derive(data: &Password, salt: &[u8], iterations: usize) -> Result<Vec<u8>, DeriveError>;
|
||||
}
|
||||
|
||||
/// A `ScramProvider` which provides SCRAM-SHA-1 and SCRAM-SHA-1-PLUS
|
||||
|
|
@ -52,12 +75,9 @@ impl ScramProvider for Sha1 {
|
|||
vec
|
||||
}
|
||||
|
||||
fn hmac(data: &[u8], key: &[u8]) -> Result<Vec<u8>, String> {
|
||||
fn hmac(data: &[u8], key: &[u8]) -> Result<Vec<u8>, InvalidKeyLength> {
|
||||
type HmacSha1 = Hmac<Sha1_hash>;
|
||||
let mut mac = match HmacSha1::new_varkey(key) {
|
||||
Ok(mac) => mac,
|
||||
Err(err) => return Err(format!("{}", err)),
|
||||
};
|
||||
let mut mac = HmacSha1::new_varkey(key)?;
|
||||
mac.input(data);
|
||||
let result = mac.result();
|
||||
let mut vec = Vec::with_capacity(Sha1_hash::output_size());
|
||||
|
|
@ -65,7 +85,7 @@ impl ScramProvider for Sha1 {
|
|||
Ok(vec)
|
||||
}
|
||||
|
||||
fn derive(password: &Password, salt: &[u8], iterations: usize) -> Result<Vec<u8>, String> {
|
||||
fn derive(password: &Password, salt: &[u8], iterations: usize) -> Result<Vec<u8>, DeriveError> {
|
||||
match *password {
|
||||
Password::Plain(ref plain) => {
|
||||
let mut result = vec![0; 20];
|
||||
|
|
@ -79,17 +99,16 @@ impl ScramProvider for Sha1 {
|
|||
ref data,
|
||||
} => {
|
||||
if method != Self::name() {
|
||||
Err(format!(
|
||||
"incompatible hashing method, {} is not {}",
|
||||
method,
|
||||
Self::name()
|
||||
Err(DeriveError::IncompatibleHashingMethod(
|
||||
method.to_string(),
|
||||
Self::name().to_string(),
|
||||
))
|
||||
} else if my_salt == &salt {
|
||||
Err(format!("incorrect salt"))
|
||||
Err(DeriveError::IncorrectSalt)
|
||||
} else if my_iterations == iterations {
|
||||
Err(format!(
|
||||
"incompatible iteration count, {} is not {}",
|
||||
my_iterations, iterations
|
||||
Err(DeriveError::IncompatibleIterationCount(
|
||||
my_iterations,
|
||||
iterations,
|
||||
))
|
||||
} else {
|
||||
Ok(data.to_vec())
|
||||
|
|
@ -116,12 +135,9 @@ impl ScramProvider for Sha256 {
|
|||
vec
|
||||
}
|
||||
|
||||
fn hmac(data: &[u8], key: &[u8]) -> Result<Vec<u8>, String> {
|
||||
fn hmac(data: &[u8], key: &[u8]) -> Result<Vec<u8>, InvalidKeyLength> {
|
||||
type HmacSha256 = Hmac<Sha256_hash>;
|
||||
let mut mac = match HmacSha256::new_varkey(key) {
|
||||
Ok(mac) => mac,
|
||||
Err(err) => return Err(format!("{}", err)),
|
||||
};
|
||||
let mut mac = HmacSha256::new_varkey(key)?;
|
||||
mac.input(data);
|
||||
let result = mac.result();
|
||||
let mut vec = Vec::with_capacity(Sha256_hash::output_size());
|
||||
|
|
@ -129,7 +145,7 @@ impl ScramProvider for Sha256 {
|
|||
Ok(vec)
|
||||
}
|
||||
|
||||
fn derive(password: &Password, salt: &[u8], iterations: usize) -> Result<Vec<u8>, String> {
|
||||
fn derive(password: &Password, salt: &[u8], iterations: usize) -> Result<Vec<u8>, DeriveError> {
|
||||
match *password {
|
||||
Password::Plain(ref plain) => {
|
||||
let mut result = vec![0; 32];
|
||||
|
|
@ -143,17 +159,16 @@ impl ScramProvider for Sha256 {
|
|||
ref data,
|
||||
} => {
|
||||
if method != Self::name() {
|
||||
Err(format!(
|
||||
"incompatible hashing method, {} is not {}",
|
||||
method,
|
||||
Self::name()
|
||||
Err(DeriveError::IncompatibleHashingMethod(
|
||||
method.to_string(),
|
||||
Self::name().to_string(),
|
||||
))
|
||||
} else if my_salt == &salt {
|
||||
Err(format!("incorrect salt"))
|
||||
Err(DeriveError::IncorrectSalt)
|
||||
} else if my_iterations == iterations {
|
||||
Err(format!(
|
||||
"incompatible iteration count, {} is not {}",
|
||||
my_iterations, iterations
|
||||
Err(DeriveError::IncompatibleIterationCount(
|
||||
my_iterations,
|
||||
iterations,
|
||||
))
|
||||
} else {
|
||||
Ok(data.to_vec())
|
||||
|
|
|
|||
Loading…
Reference in a new issue