]> git.lizzy.rs Git - PAKEs.git/commitdiff
move from (unmaintained) rust-crypto to RustCrypto ('sha2' crate)
authorBrian Warner <warner@lothar.com>
Wed, 2 Aug 2017 19:55:35 +0000 (12:55 -0700)
committerBrian Warner <warner@lothar.com>
Thu, 21 Sep 2017 20:02:12 +0000 (13:02 -0700)
Also upgrade to curve25519-dalek 0.11, hkdf-0.2, refine error types, add more
tests.

Cargo.toml
src/lib.rs
src/spake2.rs

index 53441714212eec26a29acd289ff0349872cdb888..f2a286f9ae575968b69142819c0661e37cfcf50d 100644 (file)
@@ -16,10 +16,10 @@ exclude = [
 travis-ci = { repository = "warner/spake2.rs" }
 
 [dependencies]
-curve25519-dalek = "0.9"
+curve25519-dalek = "0.11"
 rand = "0.3"
-#sha2 = "0.4.0"
-rust-crypto = "0.2"
+sha2 = "0.6"
+hkdf = "0.2"
 num-bigint = "0.1"
 hex = "0.2"
 
index 9083473c43ef190bf2ec8fe82748c67d56071056..beffd19df29464f9709157f525bbb7aaa267be76 100644 (file)
@@ -1,8 +1,8 @@
 
 extern crate rand;
 extern crate curve25519_dalek;
-//extern crate sha2;
-extern crate crypto;
+extern crate sha2;
+extern crate hkdf;
 extern crate num_bigint;
 
 extern crate hex;
@@ -15,7 +15,7 @@ pub use spake2::*;
 
 #[cfg(test)]
 mod tests {
-    use spake2::{SPAKE2, Ed25519Group};
+    use spake2::{SPAKE2, SPAKEErr, Ed25519Group, ErrorType};
 
     #[test]
     fn test_basic() {
@@ -28,6 +28,35 @@ mod tests {
         assert_eq!(key1, key2);
     }
 
+    #[test]
+    fn test_mismatch() {
+        let (s1, msg1) = SPAKE2::<Ed25519Group>::start_a(b"password",
+                                                         b"idA", b"idB");
+        let (s2, msg2) = SPAKE2::<Ed25519Group>::start_b(b"password2",
+                                                         b"idA", b"idB");
+        let key1 = s1.finish(msg2.as_slice()).unwrap();
+        let key2 = s2.finish(msg1.as_slice()).unwrap();
+        assert_ne!(key1, key2);
+    }
+
+    #[test]
+    fn test_reflected_message() {
+        let (s1, msg1) = SPAKE2::<Ed25519Group>::start_a(b"password",
+                                                         b"idA", b"idB");
+        let r = s1.finish(msg1.as_slice());
+        assert_eq!(r.unwrap_err(), SPAKEErr{kind: ErrorType::BadSide});
+    }
+
+    #[test]
+    fn test_bad_length() {
+        let (s1, msg1) = SPAKE2::<Ed25519Group>::start_a(b"password",
+                                                      b"idA", b"idB");
+        let mut msg2 = Vec::<u8>::with_capacity(msg1.len()+1);
+        msg2.resize(msg1.len()+1, 0u8);
+        let r = s1.finish(&msg2);
+        assert_eq!(r.unwrap_err(), SPAKEErr{kind: ErrorType::WrongLength});
+    }
+
     #[test]
     fn test_basic_symmetric() {
         let (s1, msg1) = SPAKE2::<Ed25519Group>::start_symmetric(b"password",
index 4a9f4700f01846c58bba24ec20fc3ba4ca3364e0..abd0373c5f3a11ebb2b4354f21499dac88f5b668 100644 (file)
@@ -1,20 +1,27 @@
 #![allow(dead_code)]
 
 use curve25519_dalek::scalar::Scalar as c2_Scalar;
-use curve25519_dalek::curve::ExtendedPoint as c2_Element;
-use curve25519_dalek::constants::ED25519_BASEPOINT;
-use curve25519_dalek::curve::CompressedEdwardsY;
+use curve25519_dalek::edwards::ExtendedPoint as c2_Element;
+use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
+use curve25519_dalek::edwards::CompressedEdwardsY;
 use rand::{Rng, OsRng};
-//use sha2::{Sha256, Sha512, Digest};
-use crypto::sha2::Sha256;
-use crypto::digest::Digest;
-use crypto::hkdf;
+use sha2::{Sha256, Digest};
+use hkdf::Hkdf;
 use num_bigint::BigUint;
 
 use hex::ToHex;
 
-#[derive(Debug)]
-pub struct SPAKEErr ( String );
+#[derive(Debug, PartialEq)]
+pub enum ErrorType {
+    BadSide,
+    WrongLength,
+    CorruptMessage,
+}
+
+#[derive(Debug, PartialEq)]
+pub struct SPAKEErr {
+    pub kind: ErrorType,
+}
 
 pub trait Group {
     type Scalar;
@@ -107,7 +114,7 @@ impl Group for Ed25519Group {
 
     fn basepoint_mult(s: &c2_Scalar) -> c2_Element {
         //c2_Element::basepoint_mult(s)
-        &ED25519_BASEPOINT * s
+        &ED25519_BASEPOINT_POINT * s
     }
     fn scalarmult(e: &c2_Element, s: &c2_Scalar) -> c2_Element {
         e * s
@@ -134,12 +141,7 @@ fn ed25519_hash_to_scalar(s: &[u8]) -> c2_Scalar {
     //  i = int(h, 16)
     //  i % q
 
-    let mut prk = [0u8; 32];
-    let digest = Sha256::new();
-    hkdf::hkdf_extract(digest, b"", s, &mut prk);
-    let mut okm = [0u8; 32+16];
-    hkdf::hkdf_expand(digest, &prk, b"SPAKE2 pw", &mut okm);
-    //okm[32+16-2] = 1;
+    let okm = Hkdf::<Sha256>::new(s, b"").derive(b"SPAKE2 pw", 32+16);
     println!("expanded:   {}{}", "................................", okm.iter().to_hex()); // ok
 
     let mut reducible = [0u8; 64]; // little-endian
@@ -169,15 +171,15 @@ fn ed25519_hash_ab(password_vec: &[u8], id_a: &[u8], id_b: &[u8],
 
     let mut pw_hash = Sha256::new();
     pw_hash.input(password_vec);
-    pw_hash.result(&mut transcript[0..32]);
+    transcript[0..32].copy_from_slice(&pw_hash.result());
 
     let mut ida_hash = Sha256::new();
     ida_hash.input(id_a);
-    ida_hash.result(&mut transcript[32..64]);
+    transcript[32..64].copy_from_slice(&ida_hash.result());
 
     let mut idb_hash = Sha256::new();
     idb_hash.input(id_b);
-    idb_hash.result(&mut transcript[64..96]);
+    transcript[64..96].copy_from_slice(&idb_hash.result());
 
     transcript[96..128].copy_from_slice(first_msg);
     transcript[128..160].copy_from_slice(second_msg);
@@ -188,9 +190,7 @@ fn ed25519_hash_ab(password_vec: &[u8], id_a: &[u8], id_b: &[u8],
     //let mut hash = G::TranscriptHash::default();
     let mut hash = Sha256::new();
     hash.input(&transcript);
-    let mut out = [0u8; 32];
-    hash.result(&mut out);
-    out.to_vec()
+    hash.result().to_vec()
 }
 
 fn ed25519_hash_symmetric(password_vec: &[u8], id_s: &[u8],
@@ -214,11 +214,11 @@ fn ed25519_hash_symmetric(password_vec: &[u8], id_s: &[u8],
 
     let mut pw_hash = Sha256::new();
     pw_hash.input(password_vec);
-    pw_hash.result(&mut transcript[0..32]);
+    transcript[0..32].copy_from_slice(&pw_hash.result());
 
     let mut ids_hash = Sha256::new();
     ids_hash.input(id_s);
-    ids_hash.result(&mut transcript[32..64]);
+    transcript[32..64].copy_from_slice(&ids_hash.result());
 
     if msg_u < msg_v {
         transcript[64..96].copy_from_slice(msg_u);
@@ -231,9 +231,7 @@ fn ed25519_hash_symmetric(password_vec: &[u8], id_s: &[u8],
 
     let mut hash = Sha256::new();
     hash.input(&transcript);
-    let mut out = [0u8; 32];
-    hash.result(&mut out);
-    out.to_vec()
+    hash.result().to_vec()
 }
 
 /* "session type pattern" */
@@ -345,28 +343,28 @@ impl<G: Group> SPAKE2<G> {
 
     pub fn finish(self, msg2: &[u8]) -> Result<Vec<u8>, SPAKEErr> {
         if msg2.len() != 1 + G::element_length() {
-            return Err(SPAKEErr(String::from("inbound message is the wrong length")))
+            return Err(SPAKEErr{kind: ErrorType::WrongLength});
         }
         let msg_side = msg2[0];
 
         match self.side {
             Side::A => match msg_side {
                 0x42 => (), // 'B'
-                _ => return Err(SPAKEErr(String::from("bad side"))),
+                _ => return Err(SPAKEErr{kind: ErrorType::BadSide}),
             },
             Side::B => match msg_side {
                 0x41 => (), // 'A'
-                _ => return Err(SPAKEErr(String::from("bad side"))),
+                _ => return Err(SPAKEErr{kind: ErrorType::BadSide}),
             },
             Side::Symmetric => match msg_side {
                 0x53 => (), // 'S'
-                _ => return Err(SPAKEErr(String::from("bad side"))),
+                _ => return Err(SPAKEErr{kind: ErrorType::BadSide}),
             },
         }
 
         let msg2_element = match G::bytes_to_element(&msg2[1..]) {
             Some(x) => x,
-            None => {return Err(SPAKEErr(String::from("message corrupted")))},
+            None => {return Err(SPAKEErr{kind: ErrorType::CorruptMessage})},
         };
 
         // a: K = (Y+N*(-pw))*x
@@ -415,7 +413,7 @@ mod test {
     "random_scalar()" function, which results in some particular scalar.
      */
     use curve25519_dalek::scalar::Scalar;
-    use curve25519_dalek::constants::ED25519_BASEPOINT;
+    use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
     use spake2::{SPAKE2, Ed25519Group};
     use hex::ToHex;
     use super::*;
@@ -441,7 +439,7 @@ mod test {
     fn test_serialize_basepoint() {
         // make sure elements are serialized same as the python library
         let exp = "5866666666666666666666666666666666666666666666666666666666666666";
-        let base_vec = ED25519_BASEPOINT.compress_edwards().as_bytes().to_vec();
+        let base_vec = ED25519_BASEPOINT_POINT.compress_edwards().as_bytes().to_vec();
         let base_hex = base_vec.to_hex();
         println!("exp: {:?}", exp);
         println!("got: {:?}", base_hex);