mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-05 20:30:57 +00:00
Merge branch 'release/0.2.0'
This commit is contained in:
commit
3cb7aa6124
4 changed files with 53 additions and 32 deletions
20
Cargo.toml
20
Cargo.toml
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ed25519-dalek"
|
name = "ed25519-dalek"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
authors = ["Isis Lovecruft <isis@torproject.org>"]
|
authors = ["Isis Lovecruft <isis@torproject.org>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = "CC0-1.0"
|
license = "CC0-1.0"
|
||||||
|
|
@ -11,10 +11,20 @@ exclude = [ ".gitignore", "TESTVECTORS" ]
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
arrayref = "0.3.2"
|
arrayref = "0.3.3"
|
||||||
rust-crypto = "^0.2"
|
sha2 = "^0.4"
|
||||||
rand = "^0.3"
|
|
||||||
curve25519-dalek = "^0.1"
|
[dependencies.curve25519-dalek]
|
||||||
|
version = "^0.3"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.rand]
|
||||||
|
optional = true
|
||||||
|
version = "^0.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rustc-serialize = "0.3"
|
rustc-serialize = "0.3"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = ["rand"]
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ Documentation is available [here](https://docs.rs/ed25519-dalek).
|
||||||
To install, add the following to the dependencies section of your project's
|
To install, add the following to the dependencies section of your project's
|
||||||
`Cargo.toml`:
|
`Cargo.toml`:
|
||||||
|
|
||||||
ed25519-dalek = "0.1.0"
|
ed25519-dalek = "^0.2"
|
||||||
|
|
||||||
Then, in your library or executable source, add:
|
Then, in your library or executable source, add:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,20 +10,21 @@
|
||||||
|
|
||||||
//! A Rust implementation of ed25519 key generation, signing, and verification.
|
//! A Rust implementation of ed25519 key generation, signing, and verification.
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
use crypto::digest::Digest;
|
use sha2::{Digest, Sha512};
|
||||||
use crypto::sha2::Sha512;
|
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use curve25519_dalek::curve;
|
use curve25519_dalek::curve;
|
||||||
use curve25519_dalek::curve::CompressedPoint;
|
use curve25519_dalek::curve::CompressedEdwardsY;
|
||||||
use curve25519_dalek::curve::ExtendedPoint;
|
use curve25519_dalek::curve::ExtendedPoint;
|
||||||
use curve25519_dalek::curve::ProjectivePoint;
|
use curve25519_dalek::curve::ProjectivePoint;
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
use curve25519_dalek::util::arrays_equal_ct;
|
use curve25519_dalek::util::arrays_equal_ct;
|
||||||
|
|
||||||
|
pub const SIGNATURE_LENGTH: usize = 64;
|
||||||
|
|
||||||
/// An ed25519 signature.
|
/// An ed25519 signature.
|
||||||
///
|
///
|
||||||
|
|
@ -33,14 +34,14 @@ use curve25519_dalek::util::arrays_equal_ct;
|
||||||
/// "detached"—that is, they do **not** include a copy of the message which
|
/// "detached"—that is, they do **not** include a copy of the message which
|
||||||
/// has been signed.
|
/// has been signed.
|
||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
pub struct Signature(pub [u8; 64]);
|
pub struct Signature(pub [u8; SIGNATURE_LENGTH]);
|
||||||
|
|
||||||
impl Clone for Signature {
|
impl Clone for Signature {
|
||||||
fn clone(&self) -> Self { *self }
|
fn clone(&self) -> Self { *self }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Signature {
|
impl Debug for Signature {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||||
write!(f, "Signature: {:?}", &self.0[..])
|
write!(f, "Signature: {:?}", &self.0[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -68,16 +69,16 @@ impl PartialEq for Signature {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Signature {
|
impl Signature {
|
||||||
/// View this signature as an array of 32 bytes.
|
/// View this signature as an array of 64 bytes.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_bytes(&self) -> [u8; 64] {
|
pub fn to_bytes(&self) -> [u8; SIGNATURE_LENGTH] {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a `Signature` from a slice of bytes.
|
/// Construct a `Signature` from a slice of bytes.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_bytes(bytes: &[u8]) -> Signature {
|
pub fn from_bytes(bytes: &[u8]) -> Signature {
|
||||||
Signature(*array_ref!(bytes, 0, 64))
|
Signature(*array_ref!(bytes, 0, SIGNATURE_LENGTH))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,7 +86,7 @@ impl Signature {
|
||||||
pub struct SecretKey(pub [u8; 64]);
|
pub struct SecretKey(pub [u8; 64]);
|
||||||
|
|
||||||
impl Debug for SecretKey {
|
impl Debug for SecretKey {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||||
write!(f, "SecretKey: {:?}", &self.0[..])
|
write!(f, "SecretKey: {:?}", &self.0[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -136,56 +137,57 @@ impl SecretKey {
|
||||||
pub fn sign(&self, message: &[u8]) -> Signature {
|
pub fn sign(&self, message: &[u8]) -> Signature {
|
||||||
let mut h: Sha512 = Sha512::new();
|
let mut h: Sha512 = Sha512::new();
|
||||||
let mut hash: [u8; 64] = [0u8; 64];
|
let mut hash: [u8; 64] = [0u8; 64];
|
||||||
let signature_bytes: Vec<u8>;
|
let mut signature_bytes: [u8; 64] = [0u8; SIGNATURE_LENGTH];
|
||||||
let mut expanded_key_secret: Scalar;
|
let mut expanded_key_secret: Scalar;
|
||||||
let mesg_digest: Scalar;
|
let mesg_digest: Scalar;
|
||||||
let hram_digest: Scalar;
|
let hram_digest: Scalar;
|
||||||
let r: ExtendedPoint;
|
let r: ExtendedPoint;
|
||||||
let s: Scalar;
|
let s: Scalar;
|
||||||
let t: CompressedPoint;
|
let t: CompressedEdwardsY;
|
||||||
|
|
||||||
let secret_key: &[u8; 32] = array_ref!(&self.0, 0, 32);
|
let secret_key: &[u8; 32] = array_ref!(&self.0, 0, 32);
|
||||||
let public_key: &[u8; 32] = array_ref!(&self.0, 32, 32);
|
let public_key: &[u8; 32] = array_ref!(&self.0, 32, 32);
|
||||||
|
|
||||||
h.input(secret_key);
|
h.input(secret_key);
|
||||||
h.result(&mut hash);
|
hash.copy_from_slice(h.result().as_slice());
|
||||||
|
|
||||||
expanded_key_secret = Scalar(*array_ref!(&hash, 0, 32));
|
expanded_key_secret = Scalar(*array_ref!(&hash, 0, 32));
|
||||||
expanded_key_secret[0] &= 248;
|
expanded_key_secret[0] &= 248;
|
||||||
expanded_key_secret[31] &= 63;
|
expanded_key_secret[31] &= 63;
|
||||||
expanded_key_secret[31] |= 64;
|
expanded_key_secret[31] |= 64;
|
||||||
|
|
||||||
h.reset();
|
h = Sha512::new();
|
||||||
h.input(&hash[32..]);
|
h.input(&hash[32..]);
|
||||||
h.input(&message);
|
h.input(&message);
|
||||||
h.result(&mut hash);
|
hash.copy_from_slice(h.result().as_slice());
|
||||||
|
|
||||||
mesg_digest = Scalar::reduce(&hash);
|
mesg_digest = Scalar::reduce(&hash);
|
||||||
|
|
||||||
r = ExtendedPoint::basepoint_mult(&mesg_digest);
|
r = ExtendedPoint::basepoint_mult(&mesg_digest);
|
||||||
|
|
||||||
h.reset();
|
h = Sha512::new();
|
||||||
h.input(&r.compress().to_bytes()[..]);
|
h.input(&r.compress().to_bytes()[..]);
|
||||||
h.input(public_key);
|
h.input(public_key);
|
||||||
h.input(&message);
|
h.input(&message);
|
||||||
h.result(&mut hash);
|
hash.copy_from_slice(h.result().as_slice());
|
||||||
|
|
||||||
hram_digest = Scalar::reduce(&hash);
|
hram_digest = Scalar::reduce(&hash);
|
||||||
|
|
||||||
s = Scalar::multiply_add(&hram_digest, &expanded_key_secret, &mesg_digest);
|
s = Scalar::multiply_add(&hram_digest, &expanded_key_secret, &mesg_digest);
|
||||||
t = r.compress();
|
t = r.compress();
|
||||||
|
|
||||||
signature_bytes = [t.0, s.0].concat();
|
signature_bytes[..32].copy_from_slice(&t.0);
|
||||||
|
signature_bytes[32..64].copy_from_slice(&s.0);
|
||||||
Signature(*array_ref!(&signature_bytes, 0, 64))
|
Signature(*array_ref!(&signature_bytes, 0, 64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An ed25519 public key.
|
/// An ed25519 public key.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct PublicKey(pub CompressedPoint);
|
pub struct PublicKey(pub CompressedEdwardsY);
|
||||||
|
|
||||||
impl Debug for PublicKey {
|
impl Debug for PublicKey {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||||
write!(f, "PublicKey( CompressedPoint( {:?} ))", self.0)
|
write!(f, "PublicKey( CompressedPoint( {:?} ))", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -202,7 +204,7 @@ impl PublicKey {
|
||||||
/// # Warning
|
/// # Warning
|
||||||
///
|
///
|
||||||
/// The caller is responsible for ensuring that the bytes passed into this
|
/// The caller is responsible for ensuring that the bytes passed into this
|
||||||
/// method actually represent a `curve25519_dalek::curve::CompressedPoint`
|
/// method actually represent a `curve25519_dalek::curve::CompressedEdwardsY`
|
||||||
/// and that said compressed point is actually a point on the curve.
|
/// and that said compressed point is actually a point on the curve.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
|
@ -224,7 +226,7 @@ impl PublicKey {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn from_bytes(bytes: &[u8]) -> PublicKey {
|
fn from_bytes(bytes: &[u8]) -> PublicKey {
|
||||||
PublicKey(CompressedPoint(*array_ref!(bytes, 0, 32)))
|
PublicKey(CompressedEdwardsY(*array_ref!(bytes, 0, 32)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert this public key to its underlying extended twisted Edwards coordinate.
|
/// Convert this public key to its underlying extended twisted Edwards coordinate.
|
||||||
|
|
@ -267,7 +269,7 @@ impl PublicKey {
|
||||||
h.input(&bottom_half[..]);
|
h.input(&bottom_half[..]);
|
||||||
h.input(&self.to_bytes());
|
h.input(&self.to_bytes());
|
||||||
h.input(&message);
|
h.input(&message);
|
||||||
h.result(&mut digest);
|
digest.copy_from_slice(h.result().as_slice());
|
||||||
|
|
||||||
digest_reduced = Scalar::reduce(&digest);
|
digest_reduced = Scalar::reduce(&digest);
|
||||||
r = curve::double_scalar_mult_vartime(&digest_reduced, &a, &Scalar(*top_half));
|
r = curve::double_scalar_mult_vartime(&digest_reduced, &a, &Scalar(*top_half));
|
||||||
|
|
@ -297,6 +299,7 @@ impl Keypair {
|
||||||
/// A CSPRING with a `fill_bytes()` method, e.g. the one returned
|
/// A CSPRING with a `fill_bytes()` method, e.g. the one returned
|
||||||
/// from `rand::OsRng::new()` (in the `rand` crate).
|
/// from `rand::OsRng::new()` (in the `rand` crate).
|
||||||
// we reassign 0 bytes to the temp variable t to overwrite it
|
// we reassign 0 bytes to the temp variable t to overwrite it
|
||||||
|
#[cfg(feature = "std")]
|
||||||
#[allow(unused_assignments)]
|
#[allow(unused_assignments)]
|
||||||
pub fn generate<T: Rng>(cspring: &mut T) -> Keypair {
|
pub fn generate<T: Rng>(cspring: &mut T) -> Keypair {
|
||||||
let mut h: Sha512 = Sha512::new();
|
let mut h: Sha512 = Sha512::new();
|
||||||
|
|
@ -309,7 +312,7 @@ impl Keypair {
|
||||||
cspring.fill_bytes(&mut t);
|
cspring.fill_bytes(&mut t);
|
||||||
|
|
||||||
h.input(&t);
|
h.input(&t);
|
||||||
h.result(&mut hash);
|
hash.copy_from_slice(h.result().as_slice());
|
||||||
|
|
||||||
digest = array_mut_ref!(&mut hash, 0, 32);
|
digest = array_mut_ref!(&mut hash, 0, 32);
|
||||||
digest[0] &= 248;
|
digest[0] &= 248;
|
||||||
|
|
@ -325,7 +328,7 @@ impl Keypair {
|
||||||
}
|
}
|
||||||
|
|
||||||
Keypair{
|
Keypair{
|
||||||
public: PublicKey(CompressedPoint(pk)),
|
public: PublicKey(CompressedEdwardsY(pk)),
|
||||||
secret: SecretKey(sk),
|
secret: SecretKey(sk),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -346,6 +349,8 @@ mod test {
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::BufRead;
|
use std::io::BufRead;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::string::String;
|
||||||
|
use std::vec::Vec;
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
use curve25519_dalek::curve::ExtendedPoint;
|
use curve25519_dalek::curve::ExtendedPoint;
|
||||||
use rand::OsRng;
|
use rand::OsRng;
|
||||||
|
|
|
||||||
|
|
@ -58,16 +58,22 @@
|
||||||
//! assert!(verified);
|
//! assert!(verified);
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
#![feature(rand)]
|
#![feature(rand)]
|
||||||
#![allow(unused_features)]
|
#![allow(unused_features)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate arrayref;
|
extern crate arrayref;
|
||||||
extern crate crypto;
|
extern crate sha2;
|
||||||
extern crate curve25519_dalek;
|
extern crate curve25519_dalek;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate std;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate test;
|
extern crate test;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue