mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-06 20:41:14 +00:00
Use ed25519 + signature interop crates
The `signature` crate provides `Signer` and `Verifier` traits generic over signature types: https://github.com/RustCrypto/traits/tree/master/signature There's presently an open call to stabilize the parts of its API needed by Ed25519 signatures and release a 1.0 version: https://github.com/RustCrypto/traits/issues/78 The `ed25519` crate, based on the `signature` crate, provides an `ed25519::Signature` type which can be shared across multiple Ed25519 crates (e.g. it is also used by the `yubihsm` crate): https://github.com/RustCrypto/signatures/tree/master/ed25519 This commit integrates the `ed25519::Signature` type, and changes the existing `sign` and `verify` methods (where applicable) to use the `Signer` and `Verifier` traits from the `signature` crate. Additionally, it replaces `SignatureError` with the `signature` crate's error type. This has the drawback of requiring the `Signer` and/or `Verifier` traits are in scope in order to create and/or verify signatures, but with the benefit of supporting interoperability with other Ed25519 crates which also make use of these traits.
This commit is contained in:
parent
3a9101933b
commit
6e0667d429
9 changed files with 169 additions and 157 deletions
|
|
@ -23,10 +23,11 @@ features = ["nightly", "batch"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
curve25519-dalek = { version = "2", default-features = false }
|
curve25519-dalek = { version = "2", default-features = false }
|
||||||
|
ed25519 = { version = "1", default-features = false }
|
||||||
merlin = { version = "1", default-features = false, optional = true, git = "https://github.com/isislovecruft/merlin", branch = "develop" }
|
merlin = { version = "1", default-features = false, optional = true, git = "https://github.com/isislovecruft/merlin", branch = "develop" }
|
||||||
rand = { version = "0.7", default-features = false, optional = true }
|
rand = { version = "0.7", default-features = false, optional = true }
|
||||||
rand_core = { version = "0.5", default-features = false, optional = true }
|
rand_core = { version = "0.5", default-features = false, optional = true }
|
||||||
serde = { version = "1.0", default-features = false, optional = true }
|
serde_crate = { package = "serde", version = "1.0", default-features = false, optional = true }
|
||||||
sha2 = { version = "0.8", default-features = false }
|
sha2 = { version = "0.8", default-features = false }
|
||||||
zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] }
|
zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] }
|
||||||
|
|
||||||
|
|
@ -45,9 +46,10 @@ harness = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "u64_backend"]
|
default = ["std", "u64_backend"]
|
||||||
std = ["curve25519-dalek/std", "serde/std", "sha2/std", "rand/std"]
|
std = ["curve25519-dalek/std", "ed25519/std", "serde_crate/std", "sha2/std", "rand/std"]
|
||||||
alloc = ["curve25519-dalek/alloc", "rand/alloc", "zeroize/alloc"]
|
alloc = ["curve25519-dalek/alloc", "rand/alloc", "zeroize/alloc"]
|
||||||
nightly = ["curve25519-dalek/nightly", "rand/nightly"]
|
nightly = ["curve25519-dalek/nightly", "rand/nightly"]
|
||||||
|
serde = ["serde_crate", "ed25519/serde"]
|
||||||
batch = ["merlin", "rand"]
|
batch = ["merlin", "rand"]
|
||||||
# This feature enables deterministic batch verification.
|
# This feature enables deterministic batch verification.
|
||||||
batch_deterministic = ["merlin", "rand", "rand_core"]
|
batch_deterministic = ["merlin", "rand", "rand_core"]
|
||||||
|
|
|
||||||
20
src/batch.rs
20
src/batch.rs
|
|
@ -14,6 +14,7 @@ use alloc::vec::Vec;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
|
use core::convert::TryFrom;
|
||||||
use core::iter::once;
|
use core::iter::once;
|
||||||
|
|
||||||
use curve25519_dalek::constants;
|
use curve25519_dalek::constants;
|
||||||
|
|
@ -37,7 +38,7 @@ use sha2::Sha512;
|
||||||
use crate::errors::InternalError;
|
use crate::errors::InternalError;
|
||||||
use crate::errors::SignatureError;
|
use crate::errors::SignatureError;
|
||||||
use crate::public::PublicKey;
|
use crate::public::PublicKey;
|
||||||
use crate::signature::Signature;
|
use crate::signature::InternalSignature;
|
||||||
|
|
||||||
trait BatchTranscript {
|
trait BatchTranscript {
|
||||||
fn append_hrams(&mut self, hrams: &Vec<Scalar>);
|
fn append_hrams(&mut self, hrams: &Vec<Scalar>);
|
||||||
|
|
@ -127,6 +128,7 @@ fn zero_rng() -> ZeroRng {
|
||||||
/// use ed25519_dalek::verify_batch;
|
/// use ed25519_dalek::verify_batch;
|
||||||
/// use ed25519_dalek::Keypair;
|
/// use ed25519_dalek::Keypair;
|
||||||
/// use ed25519_dalek::PublicKey;
|
/// use ed25519_dalek::PublicKey;
|
||||||
|
/// use ed25519_dalek::Signer;
|
||||||
/// use ed25519_dalek::Signature;
|
/// use ed25519_dalek::Signature;
|
||||||
/// use rand::rngs::OsRng;
|
/// use rand::rngs::OsRng;
|
||||||
///
|
///
|
||||||
|
|
@ -147,7 +149,7 @@ fn zero_rng() -> ZeroRng {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn verify_batch(
|
pub fn verify_batch(
|
||||||
messages: &[&[u8]],
|
messages: &[&[u8]],
|
||||||
signatures: &[Signature],
|
signatures: &[ed25519::Signature],
|
||||||
public_keys: &[PublicKey],
|
public_keys: &[PublicKey],
|
||||||
) -> Result<(), SignatureError>
|
) -> Result<(), SignatureError>
|
||||||
{
|
{
|
||||||
|
|
@ -155,13 +157,19 @@ pub fn verify_batch(
|
||||||
if signatures.len() != messages.len() ||
|
if signatures.len() != messages.len() ||
|
||||||
signatures.len() != public_keys.len() ||
|
signatures.len() != public_keys.len() ||
|
||||||
public_keys.len() != messages.len() {
|
public_keys.len() != messages.len() {
|
||||||
return Err(SignatureError(InternalError::ArrayLengthError{
|
return Err(InternalError::ArrayLengthError{
|
||||||
name_a: "signatures", length_a: signatures.len(),
|
name_a: "signatures", length_a: signatures.len(),
|
||||||
name_b: "messages", length_b: messages.len(),
|
name_b: "messages", length_b: messages.len(),
|
||||||
name_c: "public_keys", length_c: public_keys.len(),
|
name_c: "public_keys", length_c: public_keys.len(),
|
||||||
}));
|
}.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert all signatures to `InternalSignature`
|
||||||
|
let signatures = signatures
|
||||||
|
.iter()
|
||||||
|
.map(InternalSignature::try_from)
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
// Compute H(R || A || M) for each (signature, public_key, message) triplet
|
// Compute H(R || A || M) for each (signature, public_key, message) triplet
|
||||||
let hrams: Vec<Scalar> = (0..signatures.len()).map(|i| {
|
let hrams: Vec<Scalar> = (0..signatures.len()).map(|i| {
|
||||||
let mut h: Sha512 = Sha512::default();
|
let mut h: Sha512 = Sha512::default();
|
||||||
|
|
@ -213,11 +221,11 @@ pub fn verify_batch(
|
||||||
let id = EdwardsPoint::optional_multiscalar_mul(
|
let id = EdwardsPoint::optional_multiscalar_mul(
|
||||||
once(-B_coefficient).chain(zs.iter().cloned()).chain(zhrams),
|
once(-B_coefficient).chain(zs.iter().cloned()).chain(zhrams),
|
||||||
B.chain(Rs).chain(As),
|
B.chain(Rs).chain(As),
|
||||||
).ok_or_else(|| SignatureError(InternalError::VerifyError))?;
|
).ok_or(InternalError::VerifyError)?;
|
||||||
|
|
||||||
if id.is_identity() {
|
if id.is_identity() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(SignatureError(InternalError::VerifyError))
|
Err(InternalError::VerifyError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,18 +80,16 @@ impl Error for InternalError { }
|
||||||
/// only be constructed from 255-bit integers.)
|
/// only be constructed from 255-bit integers.)
|
||||||
///
|
///
|
||||||
/// * Failure of a signature to satisfy the verification equation.
|
/// * Failure of a signature to satisfy the verification equation.
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
|
pub type SignatureError = ed25519::signature::Error;
|
||||||
pub struct SignatureError(pub(crate) InternalError);
|
|
||||||
|
|
||||||
impl Display for SignatureError {
|
impl From<InternalError> for SignatureError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
#[cfg(not(feature = "std"))]
|
||||||
write!(f, "{}", self.0)
|
fn from(_err: InternalError) -> SignatureError {
|
||||||
}
|
SignatureError::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl Error for SignatureError {
|
fn from(err: InternalError) -> SignatureError {
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
SignatureError::from_source(err)
|
||||||
Some(&self.0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@
|
||||||
|
|
||||||
//! ed25519 keypairs.
|
//! ed25519 keypairs.
|
||||||
|
|
||||||
use core::default::Default;
|
|
||||||
|
|
||||||
#[cfg(feature = "rand")]
|
#[cfg(feature = "rand")]
|
||||||
use rand::{CryptoRng, RngCore};
|
use rand::{CryptoRng, RngCore};
|
||||||
|
|
||||||
|
|
@ -26,13 +24,12 @@ pub use sha2::Sha512;
|
||||||
use curve25519_dalek::digest::generic_array::typenum::U64;
|
use curve25519_dalek::digest::generic_array::typenum::U64;
|
||||||
pub use curve25519_dalek::digest::Digest;
|
pub use curve25519_dalek::digest::Digest;
|
||||||
|
|
||||||
#[cfg(all(feature = "batch", any(feature = "std", feature = "alloc")))]
|
use ed25519::signature::{Signer, Verifier};
|
||||||
pub use crate::batch::*;
|
|
||||||
pub use crate::constants::*;
|
use crate::constants::*;
|
||||||
pub use crate::errors::*;
|
use crate::errors::*;
|
||||||
pub use crate::public::*;
|
use crate::public::*;
|
||||||
pub use crate::secret::*;
|
use crate::secret::*;
|
||||||
pub use crate::signature::*;
|
|
||||||
|
|
||||||
/// An ed25519 keypair.
|
/// An ed25519 keypair.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -82,10 +79,10 @@ impl Keypair {
|
||||||
/// is an `SignatureError` describing the error that occurred.
|
/// is an `SignatureError` describing the error that occurred.
|
||||||
pub fn from_bytes<'a>(bytes: &'a [u8]) -> Result<Keypair, SignatureError> {
|
pub fn from_bytes<'a>(bytes: &'a [u8]) -> Result<Keypair, SignatureError> {
|
||||||
if bytes.len() != KEYPAIR_LENGTH {
|
if bytes.len() != KEYPAIR_LENGTH {
|
||||||
return Err(SignatureError(InternalError::BytesLengthError {
|
return Err(InternalError::BytesLengthError {
|
||||||
name: "Keypair",
|
name: "Keypair",
|
||||||
length: KEYPAIR_LENGTH,
|
length: KEYPAIR_LENGTH,
|
||||||
}));
|
}.into());
|
||||||
}
|
}
|
||||||
let secret = SecretKey::from_bytes(&bytes[..SECRET_KEY_LENGTH])?;
|
let secret = SecretKey::from_bytes(&bytes[..SECRET_KEY_LENGTH])?;
|
||||||
let public = PublicKey::from_bytes(&bytes[SECRET_KEY_LENGTH..])?;
|
let public = PublicKey::from_bytes(&bytes[SECRET_KEY_LENGTH..])?;
|
||||||
|
|
@ -136,13 +133,6 @@ impl Keypair {
|
||||||
Keypair{ public: pk, secret: sk }
|
Keypair{ public: pk, secret: sk }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sign a message with this keypair's secret key.
|
|
||||||
pub fn sign(&self, message: &[u8]) -> Signature {
|
|
||||||
let expanded: ExpandedSecretKey = (&self.secret).into();
|
|
||||||
|
|
||||||
expanded.sign(&message, &self.public)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sign a `prehashed_message` with this `Keypair` using the
|
/// Sign a `prehashed_message` with this `Keypair` using the
|
||||||
/// Ed25519ph algorithm defined in [RFC8032 §5.1][rfc8032].
|
/// Ed25519ph algorithm defined in [RFC8032 §5.1][rfc8032].
|
||||||
///
|
///
|
||||||
|
|
@ -241,20 +231,20 @@ impl Keypair {
|
||||||
&self,
|
&self,
|
||||||
prehashed_message: D,
|
prehashed_message: D,
|
||||||
context: Option<&[u8]>,
|
context: Option<&[u8]>,
|
||||||
) -> Signature
|
) -> ed25519::Signature
|
||||||
where
|
where
|
||||||
D: Digest<OutputSize = U64>,
|
D: Digest<OutputSize = U64>,
|
||||||
{
|
{
|
||||||
let expanded: ExpandedSecretKey = (&self.secret).into(); // xxx thanks i hate this
|
let expanded: ExpandedSecretKey = (&self.secret).into(); // xxx thanks i hate this
|
||||||
|
|
||||||
expanded.sign_prehashed(prehashed_message, &self.public, context)
|
expanded.sign_prehashed(prehashed_message, &self.public, context).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify a signature on a message with this keypair's public key.
|
/// Verify a signature on a message with this keypair's public key.
|
||||||
pub fn verify(
|
pub fn verify(
|
||||||
&self,
|
&self,
|
||||||
message: &[u8],
|
message: &[u8],
|
||||||
signature: &Signature
|
signature: &ed25519::Signature
|
||||||
) -> Result<(), SignatureError>
|
) -> Result<(), SignatureError>
|
||||||
{
|
{
|
||||||
self.public.verify(message, signature)
|
self.public.verify(message, signature)
|
||||||
|
|
@ -320,7 +310,7 @@ impl Keypair {
|
||||||
&self,
|
&self,
|
||||||
prehashed_message: D,
|
prehashed_message: D,
|
||||||
context: Option<&[u8]>,
|
context: Option<&[u8]>,
|
||||||
signature: &Signature,
|
signature: &ed25519::Signature,
|
||||||
) -> Result<(), SignatureError>
|
) -> Result<(), SignatureError>
|
||||||
where
|
where
|
||||||
D: Digest<OutputSize = U64>,
|
D: Digest<OutputSize = U64>,
|
||||||
|
|
@ -394,13 +384,28 @@ impl Keypair {
|
||||||
pub fn verify_strict(
|
pub fn verify_strict(
|
||||||
&self,
|
&self,
|
||||||
message: &[u8],
|
message: &[u8],
|
||||||
signature: &Signature,
|
signature: &ed25519::Signature,
|
||||||
) -> Result<(), SignatureError>
|
) -> Result<(), SignatureError>
|
||||||
{
|
{
|
||||||
self.public.verify_strict(message, signature)
|
self.public.verify_strict(message, signature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Signer<ed25519::Signature> for Keypair {
|
||||||
|
/// Sign a message with this keypair's secret key.
|
||||||
|
fn try_sign(&self, message: &[u8]) -> Result<ed25519::Signature, SignatureError> {
|
||||||
|
let expanded: ExpandedSecretKey = (&self.secret).into();
|
||||||
|
Ok(expanded.sign(&message, &self.public).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Verifier<ed25519::Signature> for Keypair {
|
||||||
|
/// Verify a signature on a message with this keypair's public key.
|
||||||
|
fn verify(&self, message: &[u8], signature: &ed25519::Signature) -> Result<(), SignatureError> {
|
||||||
|
self.public.verify(message, signature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl Serialize for Keypair {
|
impl Serialize for Keypair {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
47
src/lib.rs
47
src/lib.rs
|
|
@ -44,9 +44,9 @@
|
||||||
//! # fn main() {
|
//! # fn main() {
|
||||||
//! # use rand::rngs::OsRng;
|
//! # use rand::rngs::OsRng;
|
||||||
//! # use ed25519_dalek::Keypair;
|
//! # use ed25519_dalek::Keypair;
|
||||||
//! # use ed25519_dalek::Signature;
|
|
||||||
//! # let mut csprng = OsRng{};
|
//! # let mut csprng = OsRng{};
|
||||||
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
||||||
|
//! use ed25519_dalek::{Signature, Signer};
|
||||||
//! let message: &[u8] = b"This is a test of the tsunami alert system.";
|
//! let message: &[u8] = b"This is a test of the tsunami alert system.";
|
||||||
//! let signature: Signature = keypair.sign(message);
|
//! let signature: Signature = keypair.sign(message);
|
||||||
//! # }
|
//! # }
|
||||||
|
|
@ -60,12 +60,12 @@
|
||||||
//! # extern crate ed25519_dalek;
|
//! # extern crate ed25519_dalek;
|
||||||
//! # fn main() {
|
//! # fn main() {
|
||||||
//! # use rand::rngs::OsRng;
|
//! # use rand::rngs::OsRng;
|
||||||
//! # use ed25519_dalek::Keypair;
|
//! # use ed25519_dalek::{Keypair, Signature, Signer};
|
||||||
//! # use ed25519_dalek::Signature;
|
|
||||||
//! # let mut csprng = OsRng{};
|
//! # let mut csprng = OsRng{};
|
||||||
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
||||||
//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
|
//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
|
||||||
//! # let signature: Signature = keypair.sign(message);
|
//! # let signature: Signature = keypair.sign(message);
|
||||||
|
//! use ed25519_dalek::Verifier;
|
||||||
//! assert!(keypair.verify(message, &signature).is_ok());
|
//! assert!(keypair.verify(message, &signature).is_ok());
|
||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
@ -80,7 +80,8 @@
|
||||||
//! # use rand::rngs::OsRng;
|
//! # use rand::rngs::OsRng;
|
||||||
//! # use ed25519_dalek::Keypair;
|
//! # use ed25519_dalek::Keypair;
|
||||||
//! # use ed25519_dalek::Signature;
|
//! # use ed25519_dalek::Signature;
|
||||||
//! use ed25519_dalek::PublicKey;
|
//! # use ed25519_dalek::Signer;
|
||||||
|
//! use ed25519_dalek::{PublicKey, Verifier};
|
||||||
//! # let mut csprng = OsRng{};
|
//! # let mut csprng = OsRng{};
|
||||||
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
||||||
//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
|
//! # let message: &[u8] = b"This is a test of the tsunami alert system.";
|
||||||
|
|
@ -104,7 +105,7 @@
|
||||||
//! # extern crate ed25519_dalek;
|
//! # extern crate ed25519_dalek;
|
||||||
//! # fn main() {
|
//! # fn main() {
|
||||||
//! # use rand::rngs::OsRng;
|
//! # use rand::rngs::OsRng;
|
||||||
//! # use ed25519_dalek::{Keypair, Signature, PublicKey};
|
//! # use ed25519_dalek::{Keypair, Signature, Signer, PublicKey};
|
||||||
//! use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
|
//! use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
|
||||||
//! # let mut csprng = OsRng{};
|
//! # let mut csprng = OsRng{};
|
||||||
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
||||||
|
|
@ -124,8 +125,9 @@
|
||||||
//! ```
|
//! ```
|
||||||
//! # extern crate rand;
|
//! # extern crate rand;
|
||||||
//! # extern crate ed25519_dalek;
|
//! # extern crate ed25519_dalek;
|
||||||
|
//! # use std::convert::TryFrom;
|
||||||
//! # use rand::rngs::OsRng;
|
//! # use rand::rngs::OsRng;
|
||||||
//! # use ed25519_dalek::{Keypair, Signature, PublicKey, SecretKey, SignatureError};
|
//! # use ed25519_dalek::{Keypair, Signature, Signer, PublicKey, SecretKey, SignatureError};
|
||||||
//! # use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
|
//! # use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
|
||||||
//! # fn do_test() -> Result<(SecretKey, PublicKey, Keypair, Signature), SignatureError> {
|
//! # fn do_test() -> Result<(SecretKey, PublicKey, Keypair, Signature), SignatureError> {
|
||||||
//! # let mut csprng = OsRng{};
|
//! # let mut csprng = OsRng{};
|
||||||
|
|
@ -140,7 +142,7 @@
|
||||||
//! let public_key: PublicKey = PublicKey::from_bytes(&public_key_bytes)?;
|
//! let public_key: PublicKey = PublicKey::from_bytes(&public_key_bytes)?;
|
||||||
//! let secret_key: SecretKey = SecretKey::from_bytes(&secret_key_bytes)?;
|
//! let secret_key: SecretKey = SecretKey::from_bytes(&secret_key_bytes)?;
|
||||||
//! let keypair: Keypair = Keypair::from_bytes(&keypair_bytes)?;
|
//! let keypair: Keypair = Keypair::from_bytes(&keypair_bytes)?;
|
||||||
//! let signature: Signature = Signature::from_bytes(&signature_bytes)?;
|
//! let signature: Signature = Signature::try_from(&signature_bytes[..])?;
|
||||||
//! #
|
//! #
|
||||||
//! # Ok((secret_key, public_key, keypair, signature))
|
//! # Ok((secret_key, public_key, keypair, signature))
|
||||||
//! # }
|
//! # }
|
||||||
|
|
@ -166,14 +168,14 @@
|
||||||
//! # extern crate rand;
|
//! # extern crate rand;
|
||||||
//! # extern crate ed25519_dalek;
|
//! # extern crate ed25519_dalek;
|
||||||
//! # #[cfg(feature = "serde")]
|
//! # #[cfg(feature = "serde")]
|
||||||
//! extern crate serde;
|
//! # extern crate serde_crate as serde;
|
||||||
//! # #[cfg(feature = "serde")]
|
//! # #[cfg(feature = "serde")]
|
||||||
//! extern crate bincode;
|
//! # extern crate bincode;
|
||||||
//!
|
//!
|
||||||
//! # #[cfg(feature = "serde")]
|
//! # #[cfg(feature = "serde")]
|
||||||
//! # fn main() {
|
//! # fn main() {
|
||||||
//! # use rand::rngs::OsRng;
|
//! # use rand::rngs::OsRng;
|
||||||
//! # use ed25519_dalek::{Keypair, Signature, PublicKey};
|
//! # use ed25519_dalek::{Keypair, Signature, Signer, Verifier, PublicKey};
|
||||||
//! use bincode::{serialize, Infinite};
|
//! use bincode::{serialize, Infinite};
|
||||||
//! # let mut csprng = OsRng{};
|
//! # let mut csprng = OsRng{};
|
||||||
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
||||||
|
|
@ -196,16 +198,16 @@
|
||||||
//! # extern crate rand;
|
//! # extern crate rand;
|
||||||
//! # extern crate ed25519_dalek;
|
//! # extern crate ed25519_dalek;
|
||||||
//! # #[cfg(feature = "serde")]
|
//! # #[cfg(feature = "serde")]
|
||||||
//! # extern crate serde;
|
//! # extern crate serde_crate as serde;
|
||||||
//! # #[cfg(feature = "serde")]
|
//! # #[cfg(feature = "serde")]
|
||||||
//! # extern crate bincode;
|
//! # extern crate bincode;
|
||||||
//! #
|
//! #
|
||||||
//! # #[cfg(feature = "serde")]
|
//! # #[cfg(feature = "serde")]
|
||||||
//! # fn main() {
|
//! # fn main() {
|
||||||
//! # use rand::rngs::OsRng;
|
//! # use rand::rngs::OsRng;
|
||||||
//! # use ed25519_dalek::{Keypair, Signature, PublicKey};
|
//! # use ed25519_dalek::{Keypair, Signature, Signer, Verifier, PublicKey};
|
||||||
//! # use bincode::{serialize, Infinite};
|
//! # use bincode::{serialize, Infinite};
|
||||||
//! use bincode::{deserialize};
|
//! use bincode::deserialize;
|
||||||
//!
|
//!
|
||||||
//! # let mut csprng = OsRng{};
|
//! # let mut csprng = OsRng{};
|
||||||
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
//! # let keypair: Keypair = Keypair::generate(&mut csprng);
|
||||||
|
|
@ -237,6 +239,8 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
||||||
|
pub extern crate ed25519;
|
||||||
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate curve25519_dalek;
|
extern crate curve25519_dalek;
|
||||||
|
|
@ -245,20 +249,29 @@ extern crate merlin;
|
||||||
#[cfg(any(feature = "batch", feature = "std", feature = "alloc", test))]
|
#[cfg(any(feature = "batch", feature = "std", feature = "alloc", test))]
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
extern crate serde;
|
extern crate serde_crate as serde;
|
||||||
extern crate sha2;
|
extern crate sha2;
|
||||||
extern crate zeroize;
|
extern crate zeroize;
|
||||||
|
|
||||||
#[cfg(all(any(feature = "batch", feature = "batch_deterministic"), any(feature = "std", feature = "alloc")))]
|
#[cfg(all(any(feature = "batch", feature = "batch_deterministic"), any(feature = "std", feature = "alloc")))]
|
||||||
mod batch;
|
mod batch;
|
||||||
mod constants;
|
mod constants;
|
||||||
mod ed25519;
|
mod keypair;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod public;
|
mod public;
|
||||||
mod secret;
|
mod secret;
|
||||||
mod signature;
|
mod signature;
|
||||||
|
|
||||||
// Export everything public in ed25519.
|
pub use curve25519_dalek::digest::Digest;
|
||||||
pub use crate::ed25519::*;
|
|
||||||
#[cfg(all(any(feature = "batch", feature = "batch_deterministic"), any(feature = "std", feature = "alloc")))]
|
#[cfg(all(any(feature = "batch", feature = "batch_deterministic"), any(feature = "std", feature = "alloc")))]
|
||||||
pub use crate::batch::*;
|
pub use crate::batch::*;
|
||||||
|
pub use crate::constants::*;
|
||||||
|
pub use crate::errors::*;
|
||||||
|
pub use crate::keypair::*;
|
||||||
|
pub use crate::public::*;
|
||||||
|
pub use crate::secret::*;
|
||||||
|
|
||||||
|
// Re-export the `Signer` and `Verifier` traits from the `signature` crate
|
||||||
|
pub use ed25519::signature::{Signer, Verifier};
|
||||||
|
pub use ed25519::Signature;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
//! ed25519 public keys.
|
//! ed25519 public keys.
|
||||||
|
|
||||||
|
use core::convert::TryFrom;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
use curve25519_dalek::constants;
|
use curve25519_dalek::constants;
|
||||||
|
|
@ -18,6 +19,8 @@ use curve25519_dalek::edwards::CompressedEdwardsY;
|
||||||
use curve25519_dalek::edwards::EdwardsPoint;
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
|
||||||
|
use ed25519::signature::Verifier;
|
||||||
|
|
||||||
pub use sha2::Sha512;
|
pub use sha2::Sha512;
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
|
|
@ -127,10 +130,10 @@ impl PublicKey {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_bytes(bytes: &[u8]) -> Result<PublicKey, SignatureError> {
|
pub fn from_bytes(bytes: &[u8]) -> Result<PublicKey, SignatureError> {
|
||||||
if bytes.len() != PUBLIC_KEY_LENGTH {
|
if bytes.len() != PUBLIC_KEY_LENGTH {
|
||||||
return Err(SignatureError(InternalError::BytesLengthError {
|
return Err(InternalError::BytesLengthError {
|
||||||
name: "PublicKey",
|
name: "PublicKey",
|
||||||
length: PUBLIC_KEY_LENGTH,
|
length: PUBLIC_KEY_LENGTH,
|
||||||
}));
|
}.into());
|
||||||
}
|
}
|
||||||
let mut bits: [u8; 32] = [0u8; 32];
|
let mut bits: [u8; 32] = [0u8; 32];
|
||||||
bits.copy_from_slice(&bytes[..32]);
|
bits.copy_from_slice(&bytes[..32]);
|
||||||
|
|
@ -138,7 +141,7 @@ impl PublicKey {
|
||||||
let compressed = CompressedEdwardsY(bits);
|
let compressed = CompressedEdwardsY(bits);
|
||||||
let point = compressed
|
let point = compressed
|
||||||
.decompress()
|
.decompress()
|
||||||
.ok_or(SignatureError(InternalError::PointDecompressionError))?;
|
.ok_or(InternalError::PointDecompressionError)?;
|
||||||
|
|
||||||
Ok(PublicKey(compressed, point))
|
Ok(PublicKey(compressed, point))
|
||||||
}
|
}
|
||||||
|
|
@ -159,37 +162,6 @@ impl PublicKey {
|
||||||
PublicKey(compressed, point)
|
PublicKey(compressed, point)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify a signature on a message with this keypair's public key.
|
|
||||||
///
|
|
||||||
/// # Return
|
|
||||||
///
|
|
||||||
/// Returns `Ok(())` if the signature is valid, and `Err` otherwise.
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn verify(
|
|
||||||
&self,
|
|
||||||
message: &[u8],
|
|
||||||
signature: &Signature
|
|
||||||
) -> Result<(), SignatureError>
|
|
||||||
{
|
|
||||||
let mut h: Sha512 = Sha512::new();
|
|
||||||
let R: EdwardsPoint;
|
|
||||||
let k: Scalar;
|
|
||||||
let minus_A: EdwardsPoint = -self.1;
|
|
||||||
|
|
||||||
h.input(signature.R.as_bytes());
|
|
||||||
h.input(self.as_bytes());
|
|
||||||
h.input(&message);
|
|
||||||
|
|
||||||
k = Scalar::from_hash(h);
|
|
||||||
R = EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
|
||||||
|
|
||||||
if R.compress() == signature.R {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(SignatureError(InternalError::VerifyError))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm.
|
/// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm.
|
||||||
///
|
///
|
||||||
/// # Inputs
|
/// # Inputs
|
||||||
|
|
@ -213,11 +185,13 @@ impl PublicKey {
|
||||||
&self,
|
&self,
|
||||||
prehashed_message: D,
|
prehashed_message: D,
|
||||||
context: Option<&[u8]>,
|
context: Option<&[u8]>,
|
||||||
signature: &Signature,
|
signature: &ed25519::Signature,
|
||||||
) -> Result<(), SignatureError>
|
) -> Result<(), SignatureError>
|
||||||
where
|
where
|
||||||
D: Digest<OutputSize = U64>,
|
D: Digest<OutputSize = U64>,
|
||||||
{
|
{
|
||||||
|
let signature = InternalSignature::try_from(signature)?;
|
||||||
|
|
||||||
let mut h: Sha512 = Sha512::default();
|
let mut h: Sha512 = Sha512::default();
|
||||||
let R: EdwardsPoint;
|
let R: EdwardsPoint;
|
||||||
let k: Scalar;
|
let k: Scalar;
|
||||||
|
|
@ -241,7 +215,7 @@ impl PublicKey {
|
||||||
if R.compress() == signature.R {
|
if R.compress() == signature.R {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(SignatureError(InternalError::VerifyError))
|
Err(InternalError::VerifyError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -311,9 +285,11 @@ impl PublicKey {
|
||||||
pub fn verify_strict(
|
pub fn verify_strict(
|
||||||
&self,
|
&self,
|
||||||
message: &[u8],
|
message: &[u8],
|
||||||
signature: &Signature,
|
signature: &ed25519::Signature,
|
||||||
) -> Result<(), SignatureError>
|
) -> Result<(), SignatureError>
|
||||||
{
|
{
|
||||||
|
let signature = InternalSignature::try_from(signature)?;
|
||||||
|
|
||||||
let mut h: Sha512 = Sha512::new();
|
let mut h: Sha512 = Sha512::new();
|
||||||
let R: EdwardsPoint;
|
let R: EdwardsPoint;
|
||||||
let k: Scalar;
|
let k: Scalar;
|
||||||
|
|
@ -321,13 +297,13 @@ impl PublicKey {
|
||||||
let signature_R: EdwardsPoint;
|
let signature_R: EdwardsPoint;
|
||||||
|
|
||||||
match signature.R.decompress() {
|
match signature.R.decompress() {
|
||||||
None => return Err(SignatureError(InternalError::VerifyError)),
|
None => return Err(InternalError::VerifyError.into()),
|
||||||
Some(x) => signature_R = x,
|
Some(x) => signature_R = x,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logical OR is fine here as we're not trying to be constant time.
|
// Logical OR is fine here as we're not trying to be constant time.
|
||||||
if signature_R.is_small_order() || self.1.is_small_order() {
|
if signature_R.is_small_order() || self.1.is_small_order() {
|
||||||
return Err(SignatureError(InternalError::VerifyError));
|
return Err(InternalError::VerifyError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
h.input(signature.R.as_bytes());
|
h.input(signature.R.as_bytes());
|
||||||
|
|
@ -340,7 +316,42 @@ impl PublicKey {
|
||||||
if R == signature_R {
|
if R == signature_R {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(SignatureError(InternalError::VerifyError))
|
Err(InternalError::VerifyError.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Verifier<ed25519::Signature> for PublicKey {
|
||||||
|
/// Verify a signature on a message with this keypair's public key.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
///
|
||||||
|
/// Returns `Ok(())` if the signature is valid, and `Err` otherwise.
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn verify(
|
||||||
|
&self,
|
||||||
|
message: &[u8],
|
||||||
|
signature: &ed25519::Signature
|
||||||
|
) -> Result<(), SignatureError>
|
||||||
|
{
|
||||||
|
let signature = InternalSignature::try_from(signature)?;
|
||||||
|
|
||||||
|
let mut h: Sha512 = Sha512::new();
|
||||||
|
let R: EdwardsPoint;
|
||||||
|
let k: Scalar;
|
||||||
|
let minus_A: EdwardsPoint = -self.1;
|
||||||
|
|
||||||
|
h.input(signature.R.as_bytes());
|
||||||
|
h.input(self.as_bytes());
|
||||||
|
h.input(&message);
|
||||||
|
|
||||||
|
k = Scalar::from_hash(h);
|
||||||
|
R = EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
||||||
|
|
||||||
|
if R.compress() == signature.R {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(InternalError::VerifyError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,10 +106,10 @@ impl SecretKey {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, SignatureError> {
|
pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, SignatureError> {
|
||||||
if bytes.len() != SECRET_KEY_LENGTH {
|
if bytes.len() != SECRET_KEY_LENGTH {
|
||||||
return Err(SignatureError(InternalError::BytesLengthError {
|
return Err(InternalError::BytesLengthError {
|
||||||
name: "SecretKey",
|
name: "SecretKey",
|
||||||
length: SECRET_KEY_LENGTH,
|
length: SECRET_KEY_LENGTH,
|
||||||
}));
|
}.into());
|
||||||
}
|
}
|
||||||
let mut bits: [u8; 32] = [0u8; 32];
|
let mut bits: [u8; 32] = [0u8; 32];
|
||||||
bits.copy_from_slice(&bytes[..32]);
|
bits.copy_from_slice(&bytes[..32]);
|
||||||
|
|
@ -383,10 +383,10 @@ impl ExpandedSecretKey {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_bytes(bytes: &[u8]) -> Result<ExpandedSecretKey, SignatureError> {
|
pub fn from_bytes(bytes: &[u8]) -> Result<ExpandedSecretKey, SignatureError> {
|
||||||
if bytes.len() != EXPANDED_SECRET_KEY_LENGTH {
|
if bytes.len() != EXPANDED_SECRET_KEY_LENGTH {
|
||||||
return Err(SignatureError(InternalError::BytesLengthError {
|
return Err(InternalError::BytesLengthError {
|
||||||
name: "ExpandedSecretKey",
|
name: "ExpandedSecretKey",
|
||||||
length: EXPANDED_SECRET_KEY_LENGTH,
|
length: EXPANDED_SECRET_KEY_LENGTH,
|
||||||
}));
|
}.into());
|
||||||
}
|
}
|
||||||
let mut lower: [u8; 32] = [0u8; 32];
|
let mut lower: [u8; 32] = [0u8; 32];
|
||||||
let mut upper: [u8; 32] = [0u8; 32];
|
let mut upper: [u8; 32] = [0u8; 32];
|
||||||
|
|
@ -402,7 +402,7 @@ impl ExpandedSecretKey {
|
||||||
|
|
||||||
/// Sign a message with this `ExpandedSecretKey`.
|
/// Sign a message with this `ExpandedSecretKey`.
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn sign(&self, message: &[u8], public_key: &PublicKey) -> Signature {
|
pub fn sign(&self, message: &[u8], public_key: &PublicKey) -> ed25519::Signature {
|
||||||
let mut h: Sha512 = Sha512::new();
|
let mut h: Sha512 = Sha512::new();
|
||||||
let R: CompressedEdwardsY;
|
let R: CompressedEdwardsY;
|
||||||
let r: Scalar;
|
let r: Scalar;
|
||||||
|
|
@ -423,7 +423,7 @@ impl ExpandedSecretKey {
|
||||||
k = Scalar::from_hash(h);
|
k = Scalar::from_hash(h);
|
||||||
s = &(&k * &self.key) + &r;
|
s = &(&k * &self.key) + &r;
|
||||||
|
|
||||||
Signature { R, s }
|
InternalSignature { R, s }.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sign a `prehashed_message` with this `ExpandedSecretKey` using the
|
/// Sign a `prehashed_message` with this `ExpandedSecretKey` using the
|
||||||
|
|
@ -450,7 +450,7 @@ impl ExpandedSecretKey {
|
||||||
prehashed_message: D,
|
prehashed_message: D,
|
||||||
public_key: &PublicKey,
|
public_key: &PublicKey,
|
||||||
context: Option<&'a [u8]>,
|
context: Option<&'a [u8]>,
|
||||||
) -> Signature
|
) -> ed25519::Signature
|
||||||
where
|
where
|
||||||
D: Digest<OutputSize = U64>,
|
D: Digest<OutputSize = U64>,
|
||||||
{
|
{
|
||||||
|
|
@ -505,7 +505,7 @@ impl ExpandedSecretKey {
|
||||||
k = Scalar::from_hash(h);
|
k = Scalar::from_hash(h);
|
||||||
s = &(&k * &self.key) + &r;
|
s = &(&k * &self.key) + &r;
|
||||||
|
|
||||||
Signature { R, s }
|
InternalSignature { R, s }.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,12 @@
|
||||||
|
|
||||||
//! An ed25519 signature.
|
//! An ed25519 signature.
|
||||||
|
|
||||||
|
use core::convert::TryFrom;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
use curve25519_dalek::edwards::CompressedEdwardsY;
|
use curve25519_dalek::edwards::CompressedEdwardsY;
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
use ed25519::signature::Signature as _;
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::de::Error as SerdeError;
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::de::Visitor;
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::{Deserializer, Serializer};
|
|
||||||
|
|
||||||
use crate::constants::*;
|
use crate::constants::*;
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
|
|
@ -35,7 +28,7 @@ use crate::errors::*;
|
||||||
/// been signed.
|
/// been signed.
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[derive(Copy, Eq, PartialEq)]
|
#[derive(Copy, Eq, PartialEq)]
|
||||||
pub struct Signature {
|
pub(crate) struct InternalSignature {
|
||||||
/// `R` is an `EdwardsPoint`, formed by using an hash function with
|
/// `R` is an `EdwardsPoint`, formed by using an hash function with
|
||||||
/// 512-bits output to produce the digest of:
|
/// 512-bits output to produce the digest of:
|
||||||
///
|
///
|
||||||
|
|
@ -59,13 +52,13 @@ pub struct Signature {
|
||||||
pub(crate) s: Scalar,
|
pub(crate) s: Scalar,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Signature {
|
impl Clone for InternalSignature {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Signature {
|
impl Debug for InternalSignature {
|
||||||
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
||||||
write!(f, "Signature( R: {:?}, s: {:?} )", &self.R, &self.s)
|
write!(f, "Signature( R: {:?}, s: {:?} )", &self.R, &self.s)
|
||||||
}
|
}
|
||||||
|
|
@ -103,12 +96,12 @@ fn check_scalar(bytes: [u8; 32]) -> Result<Scalar, SignatureError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
match Scalar::from_canonical_bytes(bytes) {
|
match Scalar::from_canonical_bytes(bytes) {
|
||||||
None => return Err(SignatureError(InternalError::ScalarFormatError)),
|
None => return Err(InternalError::ScalarFormatError.into()),
|
||||||
Some(x) => return Ok(x),
|
Some(x) => return Ok(x),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Signature {
|
impl InternalSignature {
|
||||||
/// Convert this `Signature` to a byte array.
|
/// Convert this `Signature` to a byte array.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_bytes(&self) -> [u8; SIGNATURE_LENGTH] {
|
pub fn to_bytes(&self) -> [u8; SIGNATURE_LENGTH] {
|
||||||
|
|
@ -170,12 +163,12 @@ impl Signature {
|
||||||
/// only checking the most significant three bits. (See also the
|
/// only checking the most significant three bits. (See also the
|
||||||
/// documentation for `PublicKey.verify_strict`.)
|
/// documentation for `PublicKey.verify_strict`.)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_bytes(bytes: &[u8]) -> Result<Signature, SignatureError> {
|
pub fn from_bytes(bytes: &[u8]) -> Result<InternalSignature, SignatureError> {
|
||||||
if bytes.len() != SIGNATURE_LENGTH {
|
if bytes.len() != SIGNATURE_LENGTH {
|
||||||
return Err(SignatureError(InternalError::BytesLengthError {
|
return Err(InternalError::BytesLengthError {
|
||||||
name: "Signature",
|
name: "Signature",
|
||||||
length: SIGNATURE_LENGTH,
|
length: SIGNATURE_LENGTH,
|
||||||
}));
|
}.into());
|
||||||
}
|
}
|
||||||
let mut lower: [u8; 32] = [0u8; 32];
|
let mut lower: [u8; 32] = [0u8; 32];
|
||||||
let mut upper: [u8; 32] = [0u8; 32];
|
let mut upper: [u8; 32] = [0u8; 32];
|
||||||
|
|
@ -190,45 +183,23 @@ impl Signature {
|
||||||
Err(x) => return Err(x),
|
Err(x) => return Err(x),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Signature {
|
Ok(InternalSignature {
|
||||||
R: CompressedEdwardsY(lower),
|
R: CompressedEdwardsY(lower),
|
||||||
s: s,
|
s: s,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
impl TryFrom<&ed25519::Signature> for InternalSignature {
|
||||||
impl Serialize for Signature {
|
type Error = SignatureError;
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
fn try_from(sig: &ed25519::Signature) -> Result<InternalSignature, SignatureError> {
|
||||||
S: Serializer,
|
InternalSignature::from_bytes(sig.as_bytes())
|
||||||
{
|
|
||||||
serializer.serialize_bytes(&self.to_bytes()[..])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
impl From<InternalSignature> for ed25519::Signature {
|
||||||
impl<'d> Deserialize<'d> for Signature {
|
fn from(sig: InternalSignature) -> ed25519::Signature {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
ed25519::Signature::from_bytes(&sig.to_bytes()).unwrap()
|
||||||
where
|
|
||||||
D: Deserializer<'d>,
|
|
||||||
{
|
|
||||||
struct SignatureVisitor;
|
|
||||||
|
|
||||||
impl<'d> Visitor<'d> for SignatureVisitor {
|
|
||||||
type Value = Signature;
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
|
||||||
formatter.write_str("An ed25519 signature as 64 bytes, as specified in RFC8032.")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Signature, E>
|
|
||||||
where
|
|
||||||
E: SerdeError,
|
|
||||||
{
|
|
||||||
Signature::from_bytes(bytes).or(Err(SerdeError::invalid_length(bytes.len(), &self)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deserializer.deserialize_bytes(SignatureVisitor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ use sha2::Sha512;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod vectors {
|
mod vectors {
|
||||||
|
use ed25519::signature::Signature as _;
|
||||||
|
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::BufRead;
|
use std::io::BufRead;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
@ -219,6 +221,8 @@ mod serialisation {
|
||||||
|
|
||||||
use self::bincode::{serialize, serialized_size, deserialize, Infinite};
|
use self::bincode::{serialize, serialized_size, deserialize, Infinite};
|
||||||
|
|
||||||
|
use ed25519::signature::Signature as _;
|
||||||
|
|
||||||
static PUBLIC_KEY_BYTES: [u8; PUBLIC_KEY_LENGTH] = [
|
static PUBLIC_KEY_BYTES: [u8; PUBLIC_KEY_LENGTH] = [
|
||||||
130, 039, 155, 015, 062, 076, 188, 063,
|
130, 039, 155, 015, 062, 076, 188, 063,
|
||||||
124, 122, 026, 251, 233, 253, 225, 220,
|
124, 122, 026, 251, 233, 253, 225, 220,
|
||||||
|
|
@ -281,7 +285,7 @@ mod serialisation {
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_signature_size() {
|
fn serialize_signature_size() {
|
||||||
let signature: Signature = Signature::from_bytes(&SIGNATURE_BYTES).unwrap();
|
let signature: Signature = Signature::from_bytes(&SIGNATURE_BYTES).unwrap();
|
||||||
assert_eq!(serialized_size(&signature) as usize, 72); // These sizes are specific to bincode==1.0.1
|
assert_eq!(serialized_size(&signature) as usize, 64); // These sizes are specific to bincode==1.0.1
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue