Skip to content

Update dependencies and add public point bug fix #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

Entries are listed in reverse chronological order.

## 0.8.0
* update `curve25519-dalek` dependency to 4.0
* update `merlin` dependency to 3
* update `rand` dependency to 0.8
* update `sha2` dependency to 0.10
* remove backend features to be consistent with upstream dalek-cryptography
* fix bug that occurs when public point is the identity

## 0.7.0

* Update `curve25519-dalek`, `merlin` dependencies to 2.0.
Expand Down
15 changes: 5 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "zkp"
version = "0.7.0"
version = "0.8.0"
authors = ["Henry de Valence <[email protected]>"]
edition = "2018"
license = "CC0-1.0"
Expand All @@ -18,23 +18,18 @@ exclude = [
features = ["nightly"]

[dependencies]
merlin = "2"
rand = "0.7"
merlin = "3"
rand = { version = "0.8", features = ["std"] }
serde = "1"
serde_derive = "1"
thiserror = "1"
# Disable default features to deselect a backend, then select one below
curve25519-dalek = { version = "2", default-features = false, features = ["serde", "std"] }
curve25519-dalek = { version = "4", default-features = false, features = ["serde", "rand_core", "alloc", "digest", "precomputed-tables"] }

[dev-dependencies]
bincode = "1"
sha2 = "0.8"
sha2 = "0.10"

[features]
nightly = ["curve25519-dalek/nightly"]
debug-transcript = ["merlin/debug-transcript"]
bench = []
default = ["u64_backend"]
u32_backend = ["curve25519-dalek/u32_backend"]
u64_backend = ["curve25519-dalek/u64_backend"]
simd_backend = ["curve25519-dalek/simd_backend"]
9 changes: 0 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,6 @@ extern crate zkp;
The `nightly` feature enables nightly-specific features. It is required
to build the documentation.

#### Backend selection

`zkp` provides the following pass-through features to select a
`curve25519-dalek` backend:

* `u32_backend`
* `u64_backend`
* `simd_backend`

#### Transcript debugging

The `debug-transcript` feature is for development and testing, and
Expand Down
2 changes: 1 addition & 1 deletion src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ macro_rules! define_proof {

let public_vars = PublicVars {
$(
$instance_var: verifier.allocate_point(
$instance_var: verifier.allocate_public_point(
TRANSCRIPT_LABELS.$instance_var.as_bytes(),
*assignments.$instance_var,
)?,
Expand Down
2 changes: 1 addition & 1 deletion src/toolbox/batch_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl<'a> BatchVerifier<'a> {
let num_i = self.instance_points.len();
let num_c = self.constraints.len();

let mut static_coeffs = vec![Scalar::zero(); num_s];
let mut static_coeffs = vec![Scalar::ZERO; num_s];
let mut instance_coeffs = Matrix::<Scalar>::new(num_i + num_c, self.batch_size);

for i in 0..num_c {
Expand Down
17 changes: 16 additions & 1 deletion src/toolbox/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,21 @@ impl<'a> Verifier<'a> {
ScalarVar(self.num_scalars - 1)
}

/// Attempt to allocate a public point variable, or fail verification if
/// the assignment is invalid. This function allows for public points being the identity.
pub fn allocate_public_point(
&mut self,
label: &'static [u8],
assignment: CompressedRistretto,
) -> Result<PointVar, ProofError> {
let encoding = assignment.decompress();
self.transcript
.append_point_var(label, &encoding.unwrap());
self.points.push(assignment);
self.point_labels.push(label);
Ok(PointVar(self.points.len() - 1))
}

/// Attempt to allocate a point variable, or fail verification if
/// the assignment is invalid.
pub fn allocate_point(
Expand Down Expand Up @@ -144,7 +159,7 @@ impl<'a> Verifier<'a> {
let commitments_offset = self.points.len();
let combined_points = self.points.iter().chain(proof.commitments.iter());

let mut coeffs = vec![Scalar::zero(); self.points.len() + proof.commitments.len()];
let mut coeffs = vec![Scalar::ZERO; self.points.len() + proof.commitments.len()];
// For each constraint of the form Q = sum(P_i, x_i),
// we want to ensure Q_com = sum(P_i, resp_i) - c * Q,
// so add the check rand*( sum(P_i, resp_i) - c * Q - Q_com ) == 0
Expand Down
2 changes: 1 addition & 1 deletion tests/sig_and_vrf_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub struct PublicKey(RistrettoPoint, CompressedRistretto);

impl<'a> From<&'a SecretKey> for PublicKey {
fn from(sk: &'a SecretKey) -> PublicKey {
let pk = &sk.0 * &dalek_constants::RISTRETTO_BASEPOINT_TABLE;
let pk = &sk.0 * dalek_constants::RISTRETTO_BASEPOINT_TABLE;
PublicKey(pk, pk.compress())
}
}
Expand Down
98 changes: 98 additions & 0 deletions tests/vrf_public_zero.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// We really want points to be capital letters and scalars to be
// lowercase letters
#![allow(non_snake_case)]

#[macro_use]
extern crate zkp;

use curve25519_dalek::constants as dalek_constants;
use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar;

use zkp::Transcript;

define_proof! {
testproof,
"Test Proof",
(s, a, b, c),
(W, X, Y, Z),
(B):
Z = (s*B + a*W + b*X + c*Y)
}

// Test the generation and verification of the proof where (W,X,Y) =
// (w*B, x*B, y*B) and B is the Ristretto generator. This situation
// comes up in the issuing protocol of CMZ14 credentials, where w, x,
// and y are the (public) attributes on the credential being issued.
pub fn test_issue(w: &Scalar, x: &Scalar, y: &Scalar) {
let B: RistrettoPoint = dalek_constants::RISTRETTO_BASEPOINT_POINT;

// Public points based on the public attributes
let (W, X, Y) = (w*B, x*B, y*B);

let mut rng = rand::thread_rng();
// Private coefficients (the prover's MAC key)
let a = Scalar::random(&mut rng);
let b = Scalar::random(&mut rng);
let c = Scalar::random(&mut rng);
let s = Scalar::random(&mut rng);

// (Part of the) public MAC
let Z = s*B + a*W + b*X + c*Y;

// Construct the proof
let mut prv_transcript = Transcript::new(b"test transcript");
let pi = testproof::prove_compact(
&mut prv_transcript,
testproof::ProveAssignments {
B: &B,
W: &W,
X: &X,
Y: &Y,
Z: &Z,
a: &a,
b: &b,
c: &c,
s: &s,
},
)
.0;

// Send (Z, pi) to the verifier

// The verifier will recompute W, Y, Z as above and then verify:

let mut vrf_transcript = Transcript::new(b"test transcript");
let result = testproof::verify_compact(
&pi,
&mut vrf_transcript,
testproof::VerifyAssignments {
B: &B.compress(),
W: &W.compress(),
X: &X.compress(),
Y: &Y.compress(),
Z: &Z.compress(),
},
);

assert!(result.is_ok());
}

#[test]
fn test_nozero() {
let mut rng = rand::thread_rng();
let w = Scalar::random(&mut rng);
let x = Scalar::random(&mut rng);
let y = Scalar::random(&mut rng);
test_issue(&w, &x, &y);
}

#[test]
fn test_zero() {
let mut rng = rand::thread_rng();
let w = Scalar::random(&mut rng);
let x = Scalar::ZERO;
let y = Scalar::random(&mut rng);
test_issue(&w, &x, &y);
}

6 changes: 3 additions & 3 deletions tests/zkp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn create_and_verify_compact() {
let (proof, points) = {
let H = RistrettoPoint::hash_from_bytes::<Sha512>(b"A VRF input, for instance");
let x = Scalar::from(89327492234u64).invert();
let A = &x * &dalek_constants::RISTRETTO_BASEPOINT_TABLE;
let A = &x * dalek_constants::RISTRETTO_BASEPOINT_TABLE;
let B = &x * &H;

let mut transcript = Transcript::new(b"DLEQTest");
Expand Down Expand Up @@ -76,7 +76,7 @@ fn create_and_verify_batchable() {
let (proof, points) = {
let H = RistrettoPoint::hash_from_bytes::<Sha512>(b"A VRF input, for instance");
let x = Scalar::from(89327492234u64).invert();
let A = &x * &dalek_constants::RISTRETTO_BASEPOINT_TABLE;
let A = &x * dalek_constants::RISTRETTO_BASEPOINT_TABLE;
let B = &x * &H;

let mut transcript = Transcript::new(b"DLEQTest");
Expand Down Expand Up @@ -129,7 +129,7 @@ fn create_batch_and_batch_verify() {
for (i, message) in messages.iter().enumerate() {
let H = RistrettoPoint::hash_from_bytes::<Sha512>(message.as_bytes());
let x = Scalar::from(89327492234u64) * Scalar::from((i + 1) as u64);
let A = &x * &dalek_constants::RISTRETTO_BASEPOINT_TABLE;
let A = &x * dalek_constants::RISTRETTO_BASEPOINT_TABLE;
let B = &x * &H;

let mut transcript = Transcript::new(b"DLEQTest");
Expand Down