Skip to content
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

Add bellman and pairing dependencies, implement #3

Merged
merged 2 commits into from
Nov 14, 2023
Merged
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
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ curve25519-dalek = { version = "4.0.0", features = ["digest", "rand_core", "serd
rand_core = "0.6.4"
sha2 = "0.10.8"
pasta_curves = "0.5.1"
bellman = "0.14.0"
pairing = "0.23.0"

[build-dependencies]
tonic-build = "0.10.2"
Expand Down
54 changes: 28 additions & 26 deletions src/bin/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use structopt::StructOpt;
use strum::VariantNames;
use tonic::transport::Server;
use zk_pass::chaum_pedersen::curve25519::Curve25519ChaumPedersen;
use zk_pass::chaum_pedersen::vesta::VestaCurveChaumPedersen;
use zk_pass::chaum_pedersen::discretelog::DiscreteLogChaumPedersen;
use zk_pass::chaum_pedersen::pallas::PallasCurveChaumPedersen;
use zk_pass::chaum_pedersen::vesta::VestaCurveChaumPedersen;
use zk_pass::chaum_pedersen::GroupParams;
use zk_pass::cmdutil::{ChaumPedersenType, EllipticCurveType, RfcModpType};
use zk_pass::service::zkp_auth::auth_server::AuthServer;
Expand Down Expand Up @@ -134,44 +134,46 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.serve(addr)
.await?;
}
ChaumPedersenType::EllipticCurve => match curve {
EllipticCurveType::Ec25519 => {
let params =
ChaumPedersenType::EllipticCurve => {
match curve {
EllipticCurveType::Ec25519 => {
let params =
GroupParams::<RistrettoPoint>::from_str(&curve.to_string()).map_err(|_| {
"Invalid elliptic curve group parameters provided in command-line arguments"
.to_string()
})?;
let auth = ZkAuth::<Curve25519ChaumPedersen, _, _>::new(params);
Server::builder()
.add_service(AuthServer::new(auth))
.serve(addr)
.await?;
}
let auth = ZkAuth::<Curve25519ChaumPedersen, _, _>::new(params);
Server::builder()
.add_service(AuthServer::new(auth))
.serve(addr)
.await?;
}

EllipticCurveType::Pallas => {
let params = GroupParams::<PallasPoint>::from_str(&curve.to_string()).map_err(|_| {
EllipticCurveType::Pallas => {
let params = GroupParams::<PallasPoint>::from_str(&curve.to_string()).map_err(|_| {
"Invalid elliptic curve group parameters provided in command-line arguments"
.to_string()
})?;
let auth = ZkAuth::<PallasCurveChaumPedersen, _, _>::new(params);
Server::builder()
.add_service(AuthServer::new(auth))
.serve(addr)
.await?;
}
let auth = ZkAuth::<PallasCurveChaumPedersen, _, _>::new(params);
Server::builder()
.add_service(AuthServer::new(auth))
.serve(addr)
.await?;
}

EllipticCurveType::Vesta => {
let params = GroupParams::<VestaPoint>::from_str(&curve.to_string()).map_err(|_| {
EllipticCurveType::Vesta => {
let params = GroupParams::<VestaPoint>::from_str(&curve.to_string()).map_err(|_| {
"Invalid elliptic curve group parameters provided in command-line arguments"
.to_string()
})?;
let auth = ZkAuth::<VestaCurveChaumPedersen, _, _>::new(params);
Server::builder()
.add_service(AuthServer::new(auth))
.serve(addr)
.await?;
let auth = ZkAuth::<VestaCurveChaumPedersen, _, _>::new(params);
Server::builder()
.add_service(AuthServer::new(auth))
.serve(addr)
.await?;
}
}
},
}
}

Ok(())
Expand Down
4 changes: 2 additions & 2 deletions src/chaum_pedersen/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
use curve25519_dalek::RistrettoPoint;
use lazy_static::lazy_static;
use num_bigint::BigUint;
use std::str::FromStr;
use pasta_curves::pallas::Point as PallasPoint;
use pasta_curves::vesta::Point as VestaPoint;
use std::str::FromStr;

// RFC5114_GROUP_PARAMETERS are constant Prime Order Subgroups as defined in RFC5114
// Reference: https://www.rfc-editor.org/rfc/rfc5114.html#section-2
Expand Down Expand Up @@ -169,4 +169,4 @@ impl FromStr for GroupParams<VestaPoint> {
_ => Err(()), // Returning an error for unrecognized strings.
}
}
}
}
100 changes: 100 additions & 0 deletions src/chaum_pedersen/curve25519.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use crate::chaum_pedersen::{ChaumPedersen, GroupParams};
use crate::conversion::ByteConvertible;
use crate::rand::RandomGenerator;
use curve25519_dalek::ristretto::CompressedRistretto;
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::RistrettoPoint;
use rand::rngs::OsRng;
use std::error::Error;

/// A struct representing the Chaum-Pedersen protocol specialized for elliptic curve groups.
/// This protocol is used for demonstrating knowledge of a secret in a zero-knowledge manner.
Expand Down Expand Up @@ -120,6 +124,76 @@ impl ChaumPedersen for Curve25519ChaumPedersen {
}
}

/// Implementation of `ByteConvertible` for `Scalar`.
///
/// This implementation provides methods to convert `Scalar` objects to and from
/// byte arrays. Scalars are fundamental in cryptographic operations and being able to
/// serialize and deserialize them is crucial.
impl ByteConvertible<Scalar> for Scalar {
fn convert_to(t: &Scalar) -> Vec<u8> {
t.to_bytes().to_vec()
}

fn convert_from(bytes: &[u8]) -> Result<Scalar, Box<dyn Error>> {
let array: [u8; 32] = bytes.try_into().map_err(|_| {
Box::new(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Invalid bytes length for Scalar",
)) as Box<dyn Error>
})?;
Ok(Scalar::from_bytes_mod_order(array))
}
}

/// Implementation of `ByteConvertible` for `RistrettoPoint`.
///
/// This implementation provides methods to convert `RistrettoPoint` objects to and from
/// byte arrays. It uses the compression and decompression features of the Ristretto group
/// to achieve this.
impl ByteConvertible<RistrettoPoint> for RistrettoPoint {
fn convert_to(t: &RistrettoPoint) -> Vec<u8> {
t.compress().to_bytes().to_vec()
}

fn convert_from(bytes: &[u8]) -> Result<RistrettoPoint, Box<dyn Error>> {
let compressed = CompressedRistretto::from_slice(bytes);
compressed?.decompress().ok_or_else(|| {
Box::new(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Failed to decompress RistrettoPoint",
)) as Box<dyn Error>
})
}
}

// Implementation of `RandomGenerator` trait for `Scalar`.
impl RandomGenerator<Scalar> for Scalar {
/// Generates a random `Scalar`.
///
/// # Returns
/// A `Result` containing the random `Scalar`, or an error if the generation fails.
///
/// # Errors
/// Returns an error if the conversion from bytes to `Scalar` fails.
fn generate_random() -> Result<Scalar, Box<dyn Error>> {
Ok(Scalar::random(&mut OsRng))
}
}

// Implementation of `RandomGenerator` trait for `RistrettoPoint`.
impl RandomGenerator<RistrettoPoint> for RistrettoPoint {
/// Generates a random `RistrettoPoint`.
///
/// # Returns
/// A `Result` containing the random `RistrettoPoint`, or an error if the generation fails.
///
/// # Errors
/// Returns an error if the conversion from bytes to `RistrettoPoint` fails.
fn generate_random() -> Result<RistrettoPoint, Box<dyn std::error::Error>> {
Ok(RistrettoPoint::random(&mut OsRng))
}
}

#[cfg(test)]
mod test {
use super::*;
Expand All @@ -129,6 +203,15 @@ mod test {
use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
use curve25519_dalek::ristretto::CompressedRistretto;

// Test case to ensure round-trip conversion for `RistrettoPoint`.
#[test]
fn ristretto_point_conversion_round_trip() {
let original = RISTRETTO_BASEPOINT_POINT * Scalar::generate_random().unwrap();
let bytes = RistrettoPoint::convert_to(&original);
let recovered = RistrettoPoint::convert_from(&bytes).unwrap();
assert_eq!(original, recovered);
}

fn serialize_ristretto_point(point: &RistrettoPoint) -> String {
// Compress the RistrettoPoint
let compressed_point = point.compress();
Expand Down Expand Up @@ -265,4 +348,21 @@ mod test {
// Asserting that the received point is equal to the original compressed point.
assert_eq!(received_point, compressed_point);
}

// Test case to ensure round-trip conversion for `Scalar`.
#[test]
fn scalar_conversion_round_trip() {
let original = Scalar::generate_random().unwrap();
let bytes = Scalar::convert_to(&original);
let recovered = Scalar::convert_from(&bytes).unwrap();
assert_eq!(original, recovered);
}

// Test case to check for proper error handling with invalid byte length for `Scalar`.
#[test]
fn scalar_invalid_bytes_length() {
let bytes: Vec<u8> = vec![0; 64]; // Invalid length for Scalar conversion
let result = Scalar::convert_from(&bytes);
assert!(result.is_err());
}
}
48 changes: 46 additions & 2 deletions src/chaum_pedersen/discretelog.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::chaum_pedersen::{ChaumPedersen, GroupParams};
use crate::conversion::ByteConvertible;
use crate::rand::RandomGenerator;
use num_bigint::{BigUint, RandBigInt};
use num_traits::One;
use rand::rngs::OsRng;

use crate::chaum_pedersen::{ChaumPedersen, GroupParams};
use std::error::Error;

/// A struct representing the Chaum-Pedersen protocol specialized for discrete logarithm-based groups.
/// This protocol is used for demonstrating knowledge of a secret in a zero-knowledge manner.
Expand Down Expand Up @@ -116,6 +118,38 @@ impl ChaumPedersen for DiscreteLogChaumPedersen {
}
}

/// Implementation of `ByteConvertible` for `BigUint`.
///
/// This implementation provides methods to convert `BigUint` objects to and from
/// byte arrays, using big-endian byte order.
impl ByteConvertible<BigUint> for BigUint {
fn convert_to(t: &BigUint) -> Vec<u8> {
t.to_bytes_be()
}

fn convert_from(bytes: &[u8]) -> Result<BigUint, Box<dyn Error>> {
Ok(BigUint::from_bytes_be(bytes))
}
}

// Implementation of `RandomGenerator` trait for `BigUint`.
impl RandomGenerator<BigUint> for BigUint {
/// Generates a random `BigUint`.
///
/// # Returns
/// A `Result` containing the random `BigUint`, or an error if the generation fails.
///
/// # Errors
/// Returns an error if the conversion from bytes to `BigUint` fails.
fn generate_random() -> Result<BigUint, Box<dyn std::error::Error>> {
use rand::RngCore;
let mut rng = OsRng;
let mut bytes = [0u8; 32];
rng.fill_bytes(&mut bytes);
Ok(BigUint::from_bytes_be(&bytes))
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -125,6 +159,16 @@ mod tests {
};
use crate::chaum_pedersen::test::test_execute_protocol;
use crate::rand::RandomGenerator;
use num_bigint::ToBigUint;

// Test case to ensure round-trip conversion for `BigUint`.
#[test]
fn biguint_conversion_round_trip() {
let original = 123456789u64.to_biguint().unwrap();
let bytes = BigUint::convert_to(&original);
let recovered = BigUint::convert_from(&bytes).unwrap();
assert_eq!(original, recovered);
}

#[test]
fn test_discrete_log_commitment() {
Expand Down
Loading