Skip to content

Commit

Permalink
refactor to use reddsa crate (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
conradoplg authored Feb 1, 2023
1 parent 6993b12 commit 96febcf
Show file tree
Hide file tree
Showing 23 changed files with 65 additions and 2,828 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

Entries are listed in reverse chronological order.

## 0.6.0

* Refactor to use `reddsa` (which is a generalization of this crate).
* Remove FROST code. Use The `reddsa` crate directly if you need it.

## 0.5.1

* Remove unneeded `digest` dependency
Expand Down
5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ description = "A standalone implementation of the RedJubjub signature scheme."
features = ["nightly"]

[dependencies]
blake2b_simd = "1"
byteorder = "1.4"
jubjub = "0.9"
reddsa = "0.3.0"
rand_core = "0.6"
serde = { version = "1", optional = true, features = ["derive"] }
thiserror = "1.0"
Expand All @@ -28,7 +26,6 @@ zeroize = { version = "1", default-features = false, features = ["zeroize_derive
[dev-dependencies]
bincode = "1"
criterion = "0.3"
proptest-derive = "0.3"
lazy_static = "1.4"
proptest = "1.0"
rand = "0.8"
Expand Down
152 changes: 9 additions & 143 deletions src/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,45 +18,17 @@
//! and loss of the ability to easily pinpoint failing signatures.
//!
use std::convert::TryFrom;

use jubjub::*;
use rand_core::{CryptoRng, RngCore};

use crate::{private::Sealed, scalar_mul::VartimeMultiscalarMul, *};

// Shim to generate a random 128bit value in a [u64; 4], without
// importing `rand`.
fn gen_128_bits<R: RngCore + CryptoRng>(mut rng: R) -> [u64; 4] {
let mut bytes = [0u64; 4];
bytes[0] = rng.next_u64();
bytes[1] = rng.next_u64();
bytes
}

#[derive(Clone, Debug)]
enum Inner {
SpendAuth {
vk_bytes: VerificationKeyBytes<SpendAuth>,
sig: Signature<SpendAuth>,
c: Scalar,
},
Binding {
vk_bytes: VerificationKeyBytes<Binding>,
sig: Signature<Binding>,
c: Scalar,
},
}
use crate::*;

/// 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.
#[derive(Clone, Debug)]
pub struct Item {
inner: Inner,
}
pub struct Item(reddsa::batch::Item<sapling::SpendAuth, sapling::Binding>);

impl<'msg, M: AsRef<[u8]>>
From<(
Expand All @@ -72,15 +44,7 @@ impl<'msg, M: AsRef<[u8]>>
&'msg M,
),
) -> Self {
// Compute c now to avoid dependency on the msg lifetime.
let c = HStar::default()
.update(&sig.r_bytes[..])
.update(&vk_bytes.bytes[..])
.update(msg)
.finalize();
Self {
inner: Inner::SpendAuth { vk_bytes, sig, c },
}
Self(reddsa::batch::Item::from_spendauth(vk_bytes.0, sig.0, msg))
}
}

Expand All @@ -90,15 +54,7 @@ impl<'msg, M: AsRef<[u8]>> From<(VerificationKeyBytes<Binding>, Signature<Bindin
fn from(
(vk_bytes, sig, msg): (VerificationKeyBytes<Binding>, Signature<Binding>, &'msg M),
) -> Self {
// Compute c now to avoid dependency on the msg lifetime.
let c = HStar::default()
.update(&sig.r_bytes[..])
.update(&vk_bytes.bytes[..])
.update(msg)
.finalize();
Self {
inner: Inner::Binding { vk_bytes, sig, c },
}
Self(reddsa::batch::Item::from_binding(vk_bytes.0, sig.0, msg))
}
}

Expand All @@ -112,23 +68,13 @@ impl Item {
/// the message.
#[allow(non_snake_case)]
pub fn verify_single(self) -> Result<(), Error> {
match self.inner {
Inner::Binding { vk_bytes, sig, c } => VerificationKey::<Binding>::try_from(vk_bytes)
.and_then(|vk| vk.verify_prehashed(&sig, c)),
Inner::SpendAuth { vk_bytes, sig, c } => {
VerificationKey::<SpendAuth>::try_from(vk_bytes)
.and_then(|vk| vk.verify_prehashed(&sig, c))
}
}
self.0.verify_single().map_err(|e| e.into())
}
}

#[derive(Default)]
/// A batch verification context.
pub struct Verifier {
/// Signature data queued for verification.
signatures: Vec<Item>,
}
pub struct Verifier(reddsa::batch::Verifier<sapling::SpendAuth, sapling::Binding>);

impl Verifier {
/// Construct a new batch verifier.
Expand All @@ -138,7 +84,7 @@ impl Verifier {

/// Queue an Item for verification.
pub fn queue<I: Into<Item>>(&mut self, item: I) {
self.signatures.push(item.into());
self.0.queue(item.into().0);
}

/// Perform batch verification, returning `Ok(())` if all signatures were
Expand Down Expand Up @@ -178,87 +124,7 @@ impl Verifier {
///
/// [ps]: https://zips.z.cash/protocol/protocol.pdf#reddsabatchverify
#[allow(non_snake_case)]
pub fn verify<R: RngCore + CryptoRng>(self, mut rng: R) -> Result<(), Error> {
let n = self.signatures.len();

let mut VK_coeffs = Vec::with_capacity(n);
let mut VKs = Vec::with_capacity(n);
let mut R_coeffs = Vec::with_capacity(self.signatures.len());
let mut Rs = Vec::with_capacity(self.signatures.len());
let mut P_spendauth_coeff = Scalar::zero();
let mut P_binding_coeff = Scalar::zero();

for item in self.signatures.iter() {
let (s_bytes, r_bytes, c) = match item.inner {
Inner::SpendAuth { sig, c, .. } => (sig.s_bytes, sig.r_bytes, c),
Inner::Binding { sig, c, .. } => (sig.s_bytes, sig.r_bytes, c),
};

let s = {
// XXX-jubjub: should not use CtOption here
let maybe_scalar = Scalar::from_bytes(&s_bytes);
if maybe_scalar.is_some().into() {
maybe_scalar.unwrap()
} else {
return Err(Error::InvalidSignature);
}
};

let R = {
// XXX-jubjub: should not use CtOption here
// XXX-jubjub: inconsistent ownership in from_bytes
let maybe_point = AffinePoint::from_bytes(r_bytes);
if maybe_point.is_some().into() {
jubjub::ExtendedPoint::from(maybe_point.unwrap())
} else {
return Err(Error::InvalidSignature);
}
};

let VK = match item.inner {
Inner::SpendAuth { vk_bytes, .. } => {
VerificationKey::<SpendAuth>::try_from(vk_bytes.bytes)?.point
}
Inner::Binding { vk_bytes, .. } => {
VerificationKey::<Binding>::try_from(vk_bytes.bytes)?.point
}
};

let z = Scalar::from_raw(gen_128_bits(&mut rng));

let P_coeff = z * s;
match item.inner {
Inner::SpendAuth { .. } => {
P_spendauth_coeff -= P_coeff;
}
Inner::Binding { .. } => {
P_binding_coeff -= P_coeff;
}
};

R_coeffs.push(z);
Rs.push(R);

VK_coeffs.push(Scalar::zero() + (z * c));
VKs.push(VK);
}

use std::iter::once;

let scalars = once(&P_spendauth_coeff)
.chain(once(&P_binding_coeff))
.chain(VK_coeffs.iter())
.chain(R_coeffs.iter());

let basepoints = [SpendAuth::basepoint(), Binding::basepoint()];
let points = basepoints.iter().chain(VKs.iter()).chain(Rs.iter());

let check = ExtendedPoint::vartime_multiscalar_mul(scalars, points);

if check.is_small_order().into() {
Ok(())
} else {
Err(Error::InvalidSignature)
}
pub fn verify<R: RngCore + CryptoRng>(self, rng: R) -> Result<(), Error> {
self.0.verify(rng).map_err(|e| e.into())
}
}
24 changes: 0 additions & 24 deletions src/constants.rs

This file was deleted.

10 changes: 10 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,13 @@ pub enum Error {
#[error("Invalid signature.")]
InvalidSignature,
}

impl From<reddsa::Error> for Error {
fn from(e: reddsa::Error) -> Self {
match e {
reddsa::Error::MalformedSigningKey => Error::MalformedSigningKey,
reddsa::Error::MalformedVerificationKey => Error::MalformedVerificationKey,
reddsa::Error::InvalidSignature => Error::InvalidSignature,
}
}
}
Loading

0 comments on commit 96febcf

Please sign in to comment.