diff --git a/Cargo.toml b/Cargo.toml index da90912..691f464 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,16 @@ version = "0.3.3" optional = true version = "0.3" +[dependencies.digest] +version = "0.4" + +[dependencies.generic-array] +# same version that digest depends on +version = "^0.6" + +[dev-dependencies.sha2] +version = "0.4" + [features] default = ["std"] std = ["rand"] diff --git a/src/lib.rs b/src/lib.rs index fe26b70..13fec92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,10 +38,15 @@ extern crate std; #[cfg(test)] extern crate test; +#[cfg(test)] +extern crate sha2; #[macro_use] extern crate arrayref; +extern crate generic_array; +extern crate digest; + #[cfg(feature = "std")] extern crate rand; diff --git a/src/scalar.rs b/src/scalar.rs index 85c77be..60d92ba 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -36,6 +36,10 @@ use core::ops::{Neg}; #[cfg(feature = "std")] use rand::Rng; +use digest::Digest; +use generic_array::GenericArray; +use generic_array::typenum::U64; + use constants; use utils::{load3, load4}; use subtle::CTAssignable; @@ -159,6 +163,37 @@ impl Scalar { Scalar::reduce(&scalar_bytes) } + /// Hash a slice of bytes into a scalar. + /// + /// Takes a type parameter `D`, which is any `Digest` producing 64 + /// bytes (512 bits) of output. + /// + /// # Example + /// + /// ``` + /// # extern crate curve25519_dalek; + /// # use curve25519_dalek::scalar::Scalar; + /// extern crate sha2; + /// use sha2::Sha512; + /// + /// # // Need fn main() here in comment so the doctest compiles + /// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests + /// # fn main() { + /// let msg = "To really appreciate architecture, you may even need to commit a murder"; + /// let s = Scalar::hash_from_bytes::(msg.as_bytes()); + /// # } + /// ``` + /// + pub fn hash_from_bytes(input: &[u8]) -> Scalar + where D: Digest + Default { + let mut hash = D::default(); + hash.input(input); + // XXX this seems clumsy + let mut output = [0u8;64]; + output.copy_from_slice(hash.result().as_slice()); + Scalar::reduce(&output) + } + /// Construct the additive identity pub fn zero() -> Self { Scalar([0u8; 32])