Merge branch 'update-dependency-and-edition' into 'master'

lumi created

Update dependencies, edition, remove OpenSSL, and release 0.4.3

Closes #4

See merge request lumi/sasl-rs!5

Change summary

sasl/Cargo.toml                         | 16 ++--
sasl/src/client/mechanisms/anonymous.rs |  4 
sasl/src/client/mechanisms/plain.rs     |  4 
sasl/src/client/mechanisms/scram.rs     | 22 +++---
sasl/src/client/mod.rs                  |  2 
sasl/src/common/scram.rs                | 90 ++++++++++++++------------
sasl/src/error.rs                       | 12 +-
sasl/src/lib.rs                         |  7 -
sasl/src/secret.rs                      | 12 +-
sasl/src/server/mechanisms/plain.rs     |  6 
sasl/src/server/mechanisms/scram.rs     | 18 ++--
sasl/src/server/mod.rs                  |  4 
12 files changed, 99 insertions(+), 98 deletions(-)

Detailed changes

sasl/Cargo.toml 🔗

@@ -1,6 +1,6 @@
 [package]
 name = "sasl"
-version = "0.4.2"
+version = "0.4.3"
 authors = ["lumi <lumi@pew.im>"]
 description = "A crate for SASL authentication. Currently only does the client side."
 homepage = "https://gitlab.com/lumi/sasl-rs"
@@ -9,17 +9,19 @@ documentation = "https://docs.rs/sasl"
 readme = "README.md"
 keywords = ["sasl", "authentication"]
 license = "LGPL-3.0+"
+edition = "2018"
 
 [badges]
 gitlab = { repository = "lumi/sasl-rs" }
 
 [features]
 default = ["scram"]
-scram = ["openssl"]
+scram = []
 
 [dependencies]
-base64 = "0.9.1"
-
-[dependencies.openssl]
-version = "0.10.7"
-optional = true
+base64 = "0.10"
+rand_os = "0.1"
+sha-1 = "0.8"
+sha2 = "0.8"
+hmac = "0.7"
+pbkdf2 = { version = "0.3", default-features = false }

sasl/src/client/mechanisms/anonymous.rs 🔗

@@ -1,7 +1,7 @@
 //! Provides the SASL "ANONYMOUS" mechanism.
 
-use client::Mechanism;
-use common::{Credentials, Secret};
+use crate::client::Mechanism;
+use crate::common::{Credentials, Secret};
 
 /// A struct for the SASL ANONYMOUS mechanism.
 pub struct Anonymous;

sasl/src/client/mechanisms/plain.rs 🔗

@@ -1,7 +1,7 @@
 //! Provides the SASL "PLAIN" mechanism.
 
-use client::Mechanism;
-use common::{Credentials, Identity, Password, Secret};
+use crate::client::Mechanism;
+use crate::common::{Credentials, Identity, Password, Secret};
 
 /// A struct for the SASL PLAIN mechanism.
 pub struct Plain {

sasl/src/client/mechanisms/scram.rs 🔗

@@ -2,11 +2,11 @@
 
 use base64;
 
-use client::Mechanism;
-use common::scram::{generate_nonce, ScramProvider};
-use common::{parse_frame, xor, ChannelBinding, Credentials, Identity, Password, Secret};
+use crate::client::Mechanism;
+use crate::common::scram::{generate_nonce, ScramProvider};
+use crate::common::{parse_frame, xor, ChannelBinding, Credentials, Identity, Password, Secret};
 
-use error::Error;
+use crate::error::Error;
 
 use std::marker::PhantomData;
 
@@ -137,8 +137,8 @@ impl<S: ScramProvider> Mechanism for Scram<S> {
                 client_final_message_bare.extend(b",r=");
                 client_final_message_bare.extend(server_nonce.bytes());
                 let salted_password = S::derive(&self.password, &salt, iterations)?;
-                let client_key = S::hmac(b"Client Key", &salted_password);
-                let server_key = S::hmac(b"Server Key", &salted_password);
+                let client_key = S::hmac(b"Client Key", &salted_password)?;
+                let server_key = S::hmac(b"Server Key", &salted_password)?;
                 let mut auth_message = Vec::new();
                 auth_message.extend(initial_message);
                 auth_message.push(b',');
@@ -146,9 +146,9 @@ impl<S: ScramProvider> Mechanism for Scram<S> {
                 auth_message.push(b',');
                 auth_message.extend(&client_final_message_bare);
                 let stored_key = S::hash(&client_key);
-                let client_signature = S::hmac(&auth_message, &stored_key);
+                let client_signature = S::hmac(&auth_message, &stored_key)?;
                 let client_proof = xor(&client_key, &client_signature);
-                let server_signature = S::hmac(&auth_message, &server_key);
+                let server_signature = S::hmac(&auth_message, &server_key)?;
                 let mut client_final_message = Vec::new();
                 client_final_message.extend(&client_final_message_bare);
                 client_final_message.extend(b",p=");
@@ -189,9 +189,9 @@ impl<S: ScramProvider> Mechanism for Scram<S> {
 
 #[cfg(test)]
 mod tests {
-    use client::mechanisms::Scram;
-    use client::Mechanism;
-    use common::scram::{Sha1, Sha256};
+    use crate::client::mechanisms::Scram;
+    use crate::client::Mechanism;
+    use crate::common::scram::{Sha1, Sha256};
 
     #[test]
     fn scram_sha1_works() {

sasl/src/client/mod.rs 🔗

@@ -1,4 +1,4 @@
-use common::Credentials;
+use crate::common::Credentials;
 
 /// A trait which defines SASL mechanisms.
 pub trait Mechanism {

sasl/src/common/scram.rs 🔗

@@ -1,21 +1,23 @@
-use openssl::error::ErrorStack;
-use openssl::hash::hash;
-use openssl::hash::MessageDigest;
-use openssl::pkcs5::pbkdf2_hmac;
-use openssl::pkey::PKey;
-use openssl::rand::rand_bytes;
-use openssl::sign::Signer;
+use hmac::{Hmac, Mac};
+use pbkdf2::pbkdf2;
+use rand_os::{
+    rand_core::{Error as RngError, RngCore},
+    OsRng,
+};
+use sha1::{Digest, Sha1 as Sha1_hash};
+use sha2::Sha256 as Sha256_hash;
 
-use common::Password;
+use crate::common::Password;
 
-use secret;
+use crate::secret;
 
 use base64;
 
 /// Generate a nonce for SCRAM authentication.
-pub fn generate_nonce() -> Result<String, ErrorStack> {
-    let mut data = vec![0; 32];
-    rand_bytes(&mut data)?;
+pub fn generate_nonce() -> Result<String, RngError> {
+    let mut data = [0u8; 32];
+    let mut rng = OsRng::new()?;
+    rng.fill_bytes(&mut data);
     Ok(base64::encode(&data))
 }
 
@@ -31,7 +33,7 @@ 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]) -> Vec<u8>;
+    fn hmac(data: &[u8], key: &[u8]) -> Result<Vec<u8>, String>;
 
     /// A function which does PBKDF2 key derivation using the hash function.
     fn derive(data: &Password, salt: &[u8], iterations: usize) -> Result<Vec<u8>, String>;
@@ -41,7 +43,6 @@ pub trait ScramProvider {
 pub struct Sha1;
 
 impl ScramProvider for Sha1 {
-    // TODO: look at all these unwraps
     type Secret = secret::Pbkdf2Sha1;
 
     fn name() -> &'static str {
@@ -49,28 +50,30 @@ impl ScramProvider for Sha1 {
     }
 
     fn hash(data: &[u8]) -> Vec<u8> {
-        hash(MessageDigest::sha1(), data).unwrap().to_vec()
+        let hash = Sha1_hash::digest(data);
+        let mut vec = Vec::with_capacity(Sha1_hash::output_size());
+        vec.extend_from_slice(hash.as_slice());
+        vec
     }
 
-    fn hmac(data: &[u8], key: &[u8]) -> Vec<u8> {
-        let pkey = PKey::hmac(key).unwrap();
-        let mut signer = Signer::new(MessageDigest::sha1(), &pkey).unwrap();
-        signer.update(data).unwrap();
-        signer.sign_to_vec().unwrap()
+    fn hmac(data: &[u8], key: &[u8]) -> Result<Vec<u8>, String> {
+        type HmacSha1 = Hmac<Sha1_hash>;
+        let mut mac = match HmacSha1::new_varkey(key) {
+            Ok(mac) => mac,
+            Err(err) => return Err(format!("{}", err)),
+        };
+        mac.input(data);
+        let result = mac.result();
+        let mut vec = Vec::with_capacity(Sha1_hash::output_size());
+        vec.extend_from_slice(result.code().as_slice());
+        Ok(vec)
     }
 
     fn derive(password: &Password, salt: &[u8], iterations: usize) -> Result<Vec<u8>, String> {
         match *password {
             Password::Plain(ref plain) => {
                 let mut result = vec![0; 20];
-                pbkdf2_hmac(
-                    plain.as_bytes(),
-                    salt,
-                    iterations,
-                    MessageDigest::sha1(),
-                    &mut result,
-                )
-                .unwrap();
+                pbkdf2::<Hmac<Sha1_hash>>(plain.as_bytes(), salt, iterations, &mut result);
                 Ok(result)
             }
             Password::Pbkdf2 {
@@ -104,7 +107,6 @@ impl ScramProvider for Sha1 {
 pub struct Sha256;
 
 impl ScramProvider for Sha256 {
-    // TODO: look at all these unwraps
     type Secret = secret::Pbkdf2Sha256;
 
     fn name() -> &'static str {
@@ -112,28 +114,30 @@ impl ScramProvider for Sha256 {
     }
 
     fn hash(data: &[u8]) -> Vec<u8> {
-        hash(MessageDigest::sha256(), data).unwrap().to_vec()
+        let hash = Sha256_hash::digest(data);
+        let mut vec = Vec::with_capacity(Sha256_hash::output_size());
+        vec.extend_from_slice(hash.as_slice());
+        vec
     }
 
-    fn hmac(data: &[u8], key: &[u8]) -> Vec<u8> {
-        let pkey = PKey::hmac(key).unwrap();
-        let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap();
-        signer.update(data).unwrap();
-        signer.sign_to_vec().unwrap()
+    fn hmac(data: &[u8], key: &[u8]) -> Result<Vec<u8>, String> {
+        type HmacSha256 = Hmac<Sha256_hash>;
+        let mut mac = match HmacSha256::new_varkey(key) {
+            Ok(mac) => mac,
+            Err(err) => return Err(format!("{}", err)),
+        };
+        mac.input(data);
+        let result = mac.result();
+        let mut vec = Vec::with_capacity(Sha256_hash::output_size());
+        vec.extend_from_slice(result.code().as_slice());
+        Ok(vec)
     }
 
     fn derive(password: &Password, salt: &[u8], iterations: usize) -> Result<Vec<u8>, String> {
         match *password {
             Password::Plain(ref plain) => {
                 let mut result = vec![0; 32];
-                pbkdf2_hmac(
-                    plain.as_bytes(),
-                    salt,
-                    iterations,
-                    MessageDigest::sha256(),
-                    &mut result,
-                )
-                .unwrap();
+                pbkdf2::<Hmac<Sha256_hash>>(plain.as_bytes(), salt, iterations, &mut result);
                 Ok(result)
             }
             Password::Pbkdf2 {

sasl/src/error.rs 🔗

@@ -1,19 +1,19 @@
 #[cfg(feature = "scram")]
-use openssl::error::ErrorStack;
+use rand_os::rand_core::Error as RngError;
 
 /// A wrapper enum for things that could go wrong in this crate.
 #[derive(Debug)]
 pub enum Error {
     #[cfg(feature = "scram")]
-    /// An error in OpenSSL.
-    OpenSslErrorStack(ErrorStack),
+    /// An error while initializing the Rng.
+    RngError(RngError),
     /// An error in a SASL mechanism.
     SaslError(String),
 }
 
 #[cfg(feature = "scram")]
-impl From<ErrorStack> for Error {
-    fn from(err: ErrorStack) -> Error {
-        Error::OpenSslErrorStack(err)
+impl From<RngError> for Error {
+    fn from(err: RngError) -> Error {
+        Error::RngError(err)
     }
 }

sasl/src/lib.rs 🔗

@@ -163,11 +163,6 @@
 //! sasl = "*"
 //! ```
 
-extern crate base64;
-
-#[cfg(feature = "scram")]
-extern crate openssl;
-
 mod error;
 
 pub mod client;
@@ -176,4 +171,4 @@ pub mod server;
 pub mod common;
 pub mod secret;
 
-pub use error::Error;
+pub use crate::error::Error;

sasl/src/secret.rs 🔗

@@ -19,10 +19,10 @@ pub struct Pbkdf2Sha1 {
 }
 
 impl Pbkdf2Sha1 {
-    #[cfg(feature = "openssl")]
+    #[cfg(feature = "scram")]
     pub fn derive(password: &str, salt: &[u8], iterations: usize) -> Result<Pbkdf2Sha1, String> {
-        use common::scram::{ScramProvider, Sha1};
-        use common::Password;
+        use crate::common::scram::{ScramProvider, Sha1};
+        use crate::common::Password;
         let digest = Sha1::derive(&Password::Plain(password.to_owned()), salt, iterations)?;
         Ok(Pbkdf2Sha1 {
             salt: salt.to_vec(),
@@ -54,10 +54,10 @@ pub struct Pbkdf2Sha256 {
 }
 
 impl Pbkdf2Sha256 {
-    #[cfg(feature = "openssl")]
+    #[cfg(feature = "scram")]
     pub fn derive(password: &str, salt: &[u8], iterations: usize) -> Result<Pbkdf2Sha256, String> {
-        use common::scram::{ScramProvider, Sha256};
-        use common::Password;
+        use crate::common::scram::{ScramProvider, Sha256};
+        use crate::common::Password;
         let digest = Sha256::derive(&Password::Plain(password.to_owned()), salt, iterations)?;
         Ok(Pbkdf2Sha256 {
             salt: salt.to_vec(),

sasl/src/server/mechanisms/plain.rs 🔗

@@ -1,6 +1,6 @@
-use common::Identity;
-use secret;
-use server::{Mechanism, Response, Validator};
+use crate::common::Identity;
+use crate::secret;
+use crate::server::{Mechanism, Response, Validator};
 
 pub struct Plain<V: Validator<secret::Plain>> {
     validator: V,

sasl/src/server/mechanisms/scram.rs 🔗

@@ -2,11 +2,11 @@ use std::marker::PhantomData;
 
 use base64;
 
-use common::scram::{generate_nonce, ScramProvider};
-use common::{parse_frame, xor, ChannelBinding, Identity};
-use secret;
-use secret::Pbkdf2Secret;
-use server::{Mechanism, Provider, Response};
+use crate::common::scram::{generate_nonce, ScramProvider};
+use crate::common::{parse_frame, xor, ChannelBinding, Identity};
+use crate::secret;
+use crate::secret::Pbkdf2Secret;
+use crate::server::{Mechanism, Provider, Response};
 
 enum ScramState {
     Init,
@@ -150,8 +150,8 @@ where
                 client_final_message_bare.extend(base64::encode(&cb_data).bytes());
                 client_final_message_bare.extend(b",r=");
                 client_final_message_bare.extend(server_nonce.bytes());
-                let client_key = S::hmac(b"Client Key", &salted_password);
-                let server_key = S::hmac(b"Server Key", &salted_password);
+                let client_key = S::hmac(b"Client Key", &salted_password)?;
+                let server_key = S::hmac(b"Server Key", &salted_password)?;
                 let mut auth_message = Vec::new();
                 auth_message.extend(initial_client_message);
                 auth_message.extend(b",");
@@ -159,7 +159,7 @@ where
                 auth_message.extend(b",");
                 auth_message.extend(client_final_message_bare.clone());
                 let stored_key = S::hash(&client_key);
-                let client_signature = S::hmac(&auth_message, &stored_key);
+                let client_signature = S::hmac(&auth_message, &stored_key)?;
                 let client_proof = xor(&client_key, &client_signature);
                 let sent_proof = frame.get("p").ok_or_else(|| "no proof".to_owned())?;
                 let sent_proof =
@@ -167,7 +167,7 @@ where
                 if client_proof != sent_proof {
                     return Err("authentication failed".to_owned());
                 }
-                let server_signature = S::hmac(&auth_message, &server_key);
+                let server_signature = S::hmac(&auth_message, &server_key)?;
                 let mut buf = Vec::new();
                 buf.extend(b"v=");
                 buf.extend(base64::encode(&server_signature).bytes());

sasl/src/server/mod.rs 🔗

@@ -1,5 +1,5 @@
-use common::Identity;
-use secret::Secret;
+use crate::common::Identity;
+use crate::secret::Secret;
 
 #[macro_export]
 macro_rules! impl_validator_using_provider {