port improvements from Zebra (#40)
* simplify fmt::Debug impls with new hex_if_possible() * Update src/signature.rs authors Co-authored-by: Deirdre Connolly <deirdre@zfnd.org>
This commit is contained in:
parent
31f29420c8
commit
805ef4b5c0
|
@ -25,6 +25,7 @@ features = ["nightly"]
|
|||
blake2b_simd = { version = "1", default-features = false }
|
||||
byteorder = { version = "1.4", default-features = false }
|
||||
group = { version = "0.12", default-features = false }
|
||||
hex = { version = "0.4", optional = true, default-features = false, features = ["alloc"] }
|
||||
jubjub = { version = "0.9", default-features = false }
|
||||
pasta_curves = { version = "0.4", default-features = false }
|
||||
rand_core = { version = "0.6", default-features = false }
|
||||
|
@ -53,7 +54,7 @@ features = ["alloc"]
|
|||
[features]
|
||||
std = ["blake2b_simd/std", "thiserror", "zeroize", "alloc",
|
||||
"serde"] # conditional compilation for serde not complete (issue #9)
|
||||
alloc = []
|
||||
alloc = ["hex"]
|
||||
nightly = []
|
||||
default = ["std"]
|
||||
|
||||
|
|
16
src/batch.rs
16
src/batch.rs
|
@ -30,8 +30,10 @@ use rand_core::{CryptoRng, RngCore};
|
|||
|
||||
use crate::{private::SealedScalar, scalar_mul::VartimeMultiscalarMul, *};
|
||||
|
||||
// Shim to generate a random 128bit value in a [u64; 4], without
|
||||
// importing `rand`.
|
||||
/// Shim to generate a random 128 bit value in a `[u64; 4]`, without
|
||||
/// importing `rand`.
|
||||
///
|
||||
/// The final 128 bits are zero.
|
||||
fn gen_128_bits<R: RngCore + CryptoRng>(mut rng: R) -> [u64; 4] {
|
||||
let mut bytes = [0u64; 4];
|
||||
bytes[0] = rng.next_u64();
|
||||
|
@ -39,13 +41,23 @@ fn gen_128_bits<R: RngCore + CryptoRng>(mut rng: R) -> [u64; 4] {
|
|||
bytes
|
||||
}
|
||||
|
||||
/// Inner type of a batch verification item.
|
||||
///
|
||||
/// This struct exists to allow batch processing to be decoupled from the
|
||||
/// lifetime of the message. This is useful when using the batch verification
|
||||
/// API in an async context
|
||||
///
|
||||
/// The different enum variants are for the different signature types which use
|
||||
/// different basepoints for computation: SpendAuth and Binding signatures.
|
||||
#[derive(Clone, Debug)]
|
||||
enum Inner<S: SpendAuth, B: Binding<Scalar = S::Scalar, Point = S::Point>> {
|
||||
/// A RedDSA signature using the SpendAuth generator group element.
|
||||
SpendAuth {
|
||||
vk_bytes: VerificationKeyBytes<S>,
|
||||
sig: Signature<S>,
|
||||
c: S::Scalar,
|
||||
},
|
||||
/// A RedDSA signature using the Binding generator group element.
|
||||
Binding {
|
||||
vk_bytes: VerificationKeyBytes<B>,
|
||||
sig: Signature<B>,
|
||||
|
|
12
src/lib.rs
12
src/lib.rs
|
@ -119,3 +119,15 @@ pub(crate) mod private {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the given byte array as a hex-encoded string.
|
||||
#[cfg(feature = "alloc")]
|
||||
pub(crate) fn hex_if_possible(bytes: &[u8]) -> alloc::string::String {
|
||||
hex::encode(bytes)
|
||||
}
|
||||
|
||||
/// Return the given byte array.
|
||||
#[cfg(not(feature = "alloc"))]
|
||||
pub(crate) fn hex_if_possible(bytes: &[u8]) -> &[u8] {
|
||||
bytes
|
||||
}
|
||||
|
|
|
@ -15,13 +15,17 @@ use crate::{private, SigType};
|
|||
#[cfg(feature = "alloc")]
|
||||
use crate::scalar_mul::{LookupTable5, NonAdjacentForm, VartimeMultiscalarMul};
|
||||
|
||||
/// The byte-encoding of the basepoint for `OrchardSpendAuthSig`.
|
||||
/// The byte-encoding of the basepoint for the Orchard `SpendAuthSig` on the [Pallas curve][pallasandvesta].
|
||||
///
|
||||
/// [pallasandvesta]: https://zips.z.cash/protocol/nu5.pdf#pallasandvesta
|
||||
// Reproducible by pallas::Point::hash_to_curve("z.cash:Orchard")(b"G").to_bytes()
|
||||
const ORCHARD_SPENDAUTHSIG_BASEPOINT_BYTES: [u8; 32] = [
|
||||
99, 201, 117, 184, 132, 114, 26, 141, 12, 161, 112, 123, 227, 12, 127, 12, 95, 68, 95, 62, 124,
|
||||
24, 141, 59, 6, 214, 241, 40, 179, 35, 85, 183,
|
||||
];
|
||||
|
||||
/// The byte-encoding of the basepoint for `OrchardBindingSig`.
|
||||
/// The byte-encoding of the basepoint for the Orchard `BindingSig` on the Pallas curve.
|
||||
// Reproducible by pallas::Point::hash_to_curve("z.cash:Orchard-cv")(b"r").to_bytes()
|
||||
const ORCHARD_BINDINGSIG_BASEPOINT_BYTES: [u8; 32] = [
|
||||
145, 90, 60, 136, 104, 198, 195, 14, 47, 128, 144, 238, 69, 215, 110, 64, 72, 32, 141, 234, 91,
|
||||
35, 102, 79, 187, 9, 164, 15, 85, 68, 244, 7,
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
// - Henry de Valence <hdevalence@hdevalence.ca>
|
||||
// - Deirdre Connolly <deirdre@zfnd.org>
|
||||
|
||||
//! Traits and types that support variable-time multiscalar multiplication.
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::{borrow::Borrow, fmt::Debug};
|
||||
|
||||
|
@ -65,7 +67,9 @@ pub trait VartimeMultiscalarMul {
|
|||
impl NonAdjacentForm for jubjub::Scalar {
|
||||
/// Compute a width-\\(w\\) "Non-Adjacent Form" of this scalar.
|
||||
///
|
||||
/// Thanks to curve25519-dalek
|
||||
/// Thanks to [`curve25519-dalek`].
|
||||
///
|
||||
/// [`curve25519-dalek`]: https://github.com/dalek-cryptography/curve25519-dalek/blob/3e189820da03cc034f5fa143fc7b2ccb21fffa5e/src/scalar.rs#L907
|
||||
fn non_adjacent_form(&self, w: usize) -> [i8; 256] {
|
||||
// required by the NAF definition
|
||||
debug_assert!(w >= 2);
|
||||
|
@ -160,6 +164,16 @@ impl VartimeMultiscalarMul for ExtendedPoint {
|
|||
type Scalar = jubjub::Scalar;
|
||||
type Point = ExtendedPoint;
|
||||
|
||||
/// Variable-time multiscalar multiplication using a non-adjacent form of
|
||||
/// width (5).
|
||||
///
|
||||
/// The non-adjacent form has signed, odd digits. Using only odd digits
|
||||
/// halves the table size (since we only need odd multiples), or gives fewer
|
||||
/// additions for the same table size.
|
||||
///
|
||||
/// As the name implies, the runtime varies according to the values of the
|
||||
/// inputs, thus is not safe for computing over secret data, but is great
|
||||
/// for computing over public data, such as validating signatures.
|
||||
#[allow(non_snake_case)]
|
||||
fn optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<ExtendedPoint>
|
||||
where
|
||||
|
|
|
@ -6,14 +6,15 @@
|
|||
//
|
||||
// Authors:
|
||||
// - Henry de Valence <hdevalence@hdevalence.ca>
|
||||
// - Conrado Gouvea <conradoplg@gmail.com>
|
||||
|
||||
//! RedDSA Signatures
|
||||
use core::marker::PhantomData;
|
||||
use core::{fmt, marker::PhantomData};
|
||||
|
||||
use crate::SigType;
|
||||
use crate::{hex_if_possible, SigType};
|
||||
|
||||
/// A RedDSA signature.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Signature<T: SigType> {
|
||||
pub(crate) r_bytes: [u8; 32],
|
||||
|
@ -21,6 +22,15 @@ pub struct Signature<T: SigType> {
|
|||
pub(crate) _marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: SigType> fmt::Debug for Signature<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Signature")
|
||||
.field("r_bytes", &hex_if_possible(&self.r_bytes))
|
||||
.field("s_bytes", &hex_if_possible(&self.s_bytes))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SigType> From<[u8; 64]> for Signature<T> {
|
||||
fn from(bytes: [u8; 64]) -> Signature<T> {
|
||||
let mut r_bytes = [0; 32];
|
||||
|
|
|
@ -10,13 +10,14 @@
|
|||
|
||||
use core::{
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt,
|
||||
hash::Hash,
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
use group::{cofactor::CofactorGroup, ff::PrimeField, GroupEncoding};
|
||||
|
||||
use crate::{Error, Randomizer, SigType, Signature, SpendAuth};
|
||||
use crate::{hex_if_possible, Error, Randomizer, SigType, Signature, SpendAuth};
|
||||
|
||||
/// A refinement type for `[u8; 32]` indicating that the bytes represent
|
||||
/// an encoding of a RedDSA verification key.
|
||||
|
@ -24,13 +25,21 @@ use crate::{Error, Randomizer, SigType, Signature, SpendAuth};
|
|||
/// This is useful for representing a compressed verification key; the
|
||||
/// [`VerificationKey`] type in this library holds other decompressed state
|
||||
/// used in signature verification.
|
||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
|
||||
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct VerificationKeyBytes<T: SigType> {
|
||||
pub(crate) bytes: [u8; 32],
|
||||
pub(crate) _marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: SigType> fmt::Debug for VerificationKeyBytes<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("VerificationKeyBytes")
|
||||
.field("bytes", &hex_if_possible(&self.bytes))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SigType> From<[u8; 32]> for VerificationKeyBytes<T> {
|
||||
fn from(bytes: [u8; 32]) -> VerificationKeyBytes<T> {
|
||||
VerificationKeyBytes {
|
||||
|
|
Loading…
Reference in New Issue