diff --git a/.github/changelog.sh b/.github/changelog.sh new file mode 100755 index 0000000..c13efe4 --- /dev/null +++ b/.github/changelog.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +m_branch=m; + +# fetch master since we might be in a shallow clone +git fetch origin "$m_branch:$m_branch" --depth=1 + +changed=0; +dir=.; +# check if version changed +if git diff "$m_branch" -- "Cargo.toml" | grep -q "^-version = "; then + # check if changelog updated + if git diff --exit-code --no-patch "$m_branch" -- "CHANGELOG.md"; then + echo "$dir version changed, but CHANGELOG.md is not updated" + changed=1; + fi +fi + +exit "$changed"; diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 918a518..7992319 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -9,24 +9,69 @@ env: CARGO_NET_GIT_FETCH_WITH_CLI: true jobs: - build: + check-serde: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: "true" + - name: Check with serde support + run: cargo check --features serde + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: "true" + - name: Check + run: cargo check + tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 with: cache-on-failure: "true" - - name: Build with serde support - run: cargo build --release --features serde - - name: Build - run: cargo build --release - name: Run tests run: cargo test --release --lib + doc-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: "true" - name: Run doc tests - run: cargo test --doc --features __internal_doctest + run: cargo test --release --doc --features __internal_doctest + fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 - name: Check formatting run: cargo fmt --all -- --check + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: "true" + - name: Run clippy + run: cargo clippy --lib -- -D clippy::all + clippy-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: "true" - name: Run clippy - run: cargo clippy --all --lib -- --no-deps -D clippy::all -D clippy::unwrap_used -D clippy::expect_used - - name: Run clippy tests run: cargo clippy --tests -- -D clippy::all + check-changelog: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check changelogs + run: ./.github/changelog.sh diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..573cfc2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +## v0.3.0 +* Update `generic-ec` dep to v0.3 [#48] + +[#48]: https://github.com/dfns/paillier-zk/pull/48 + +## v0.2.0 + +All changes prior to this version were not documented diff --git a/Cargo.lock b/Cargo.lock index a0aba02..cd361b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -344,10 +344,11 @@ dependencies = [ [[package]] name = "generic-ec" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f315ffeaae6a05691c5a27028b4ae960d3a430e406d0109ff8502e2f84ae97b" +checksum = "5c35601473af37794b53e8c7dc4a540a659d8de54c957990e88715b4037597d1" dependencies = [ + "curve25519-dalek", "generic-ec-core", "generic-ec-curves", "hex", @@ -361,9 +362,9 @@ dependencies = [ [[package]] name = "generic-ec-core" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cab102fc88bfc017c16e69d21edae6f41ab58bfe69eed09ed0a2cf10ec923f" +checksum = "f156564cc8aa47456da807826b1a0aa9cf420474d9f41593ffbdde65133d4bea" dependencies = [ "generic-array", "rand_core", @@ -374,11 +375,10 @@ dependencies = [ [[package]] name = "generic-ec-curves" -version = "0.1.4" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a133d38cde4fef7aea4e367ca51f291db0248495a424ec4208cdace08ba59f4" +checksum = "b5926949b758d01801c7edd75357495fe54c5fc25580a193de4c994c94d22307" dependencies = [ - "crypto-bigint", "curve25519-dalek", "elliptic-curve", "generic-ec-core", @@ -517,7 +517,7 @@ dependencies = [ [[package]] name = "paillier-zk" -version = "0.1.0" +version = "0.3.0" dependencies = [ "anyhow", "digest", diff --git a/Cargo.toml b/Cargo.toml index 111310a..d7477c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "paillier-zk" -version = "0.2.0" +version = "0.3.0" edition = "2021" license = "MIT OR Apache-2.0" description = "ZK-proofs for Paillier encryption scheme" @@ -11,7 +11,7 @@ keywords = ["paillier", "zk-proofs", "zero-knowledge"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -generic-ec = "0.2" +generic-ec = "0.3" rand_core = { version = "0.6", default-features = false } digest = "0.10" fast-paillier = "0.1" @@ -23,7 +23,7 @@ serde = { version = "1", features = ["derive"], optional = true } serde_with = { version = "3", default-features = false, features = ["macros"], optional = true } [dev-dependencies] -generic-ec = { version = "0.2", features = ["all-curves"] } +generic-ec = { version = "0.3", features = ["all-curves"] } rand_dev = { version = "0.1.0", default-features = false } sha2 = { version = "0.10", default-features = false } diff --git a/src/curve.rs b/src/curve.rs index e82c7c3..192accc 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -225,12 +225,29 @@ impl generic_ec::core::IntegerEncoding for Scalar { self.0.to_le_bytes() } - fn from_be_bytes(bytes: &Self::Bytes) -> Self { - u64::from_be_bytes(*bytes).into() + fn from_be_bytes_mod_order(bytes: &[u8]) -> Self { + use generic_ec::core::{Additive, Multiplicative}; + + let scalar_0x100 = Scalar::from(0x100); + bytes + .iter() + .map(|i| Scalar::from(u64::from(*i))) + .fold(Scalar::default(), |acc, i| { + Scalar::add(&Scalar::mul(&acc, &scalar_0x100), &i) + }) } - fn from_le_bytes(bytes: &Self::Bytes) -> Self { - u64::from_le_bytes(*bytes).into() + fn from_le_bytes_mod_order(bytes: &[u8]) -> Self { + use generic_ec::core::{Additive, Multiplicative}; + + let scalar_0x100 = Scalar::from(0x100); + bytes + .iter() + .rev() + .map(|i| Scalar::from(u64::from(*i))) + .fold(Scalar::default(), |acc, i| { + Scalar::add(&Scalar::mul(&acc, &scalar_0x100), &i) + }) } fn from_be_bytes_exact(bytes: &Self::Bytes) -> Option { @@ -254,37 +271,3 @@ impl generic_ec::Curve for C { type ScalarArray = [u8; 8]; type CoordinateArray = [u8; 8]; } - -impl generic_ec::core::hash_to_curve::HashToCurve for C { - fn hash_to_curve( - tag: generic_ec::hash_to_curve::Tag, - msgs: &[&[u8]], - ) -> Result { - use sha2::Digest; - let mut digest = sha2::Sha256::new(); - digest.update(tag.as_bytes()); - for msg in msgs { - digest.update(msg); - } - let bytes = digest.finalize(); - let bytes = bytes.as_slice()[0..8].try_into().unwrap(); - let x = u64::from_be_bytes(bytes) % MODULO; - Ok(MillionRing(x)) - } - - fn hash_to_scalar( - tag: generic_ec::hash_to_curve::Tag, - msgs: &[&[u8]], - ) -> Result { - use sha2::Digest; - let mut digest = sha2::Sha256::new(); - digest.update(tag.as_bytes()); - for msg in msgs { - digest.update(msg); - } - let bytes = digest.finalize(); - let bytes = bytes.as_slice()[0..8].try_into().unwrap(); - let x = u64::from_be_bytes(bytes); - Ok(Scalar(x)) - } -} diff --git a/src/group_element_vs_paillier_encryption_in_range.rs b/src/group_element_vs_paillier_encryption_in_range.rs index ce6471d..fbea4a7 100644 --- a/src/group_element_vs_paillier_encryption_in_range.rs +++ b/src/group_element_vs_paillier_encryption_in_range.rs @@ -314,7 +314,7 @@ pub mod non_interactive { /// deriving determenistic challenge. /// /// Obtained from the above interactive proof via Fiat-Shamir heuristic. - pub fn prove( + pub fn prove( shared_state: D, aux: &Aux, data: Data, @@ -332,7 +332,7 @@ pub mod non_interactive { } /// Verify the proof, deriving challenge independently from same data - pub fn verify( + pub fn verify( shared_state: D, aux: &Aux, data: Data, @@ -355,10 +355,7 @@ pub mod non_interactive { data: Data, commitment: &Commitment, security: &SecurityParams, - ) -> Challenge - where - D: Digest, - { + ) -> Challenge { let shared_state = shared_state.finalize(); let hash = |d: D| { let order = rug::integer::Order::Msf; diff --git a/src/lib.rs b/src/lib.rs index 90ef2be..66791ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,9 @@ #![doc = include_str!("../README.md")] #![deny(clippy::disallowed_methods)] +#![cfg_attr( + not(test), + deny(clippy::panic, clippy::unwrap_used, clippy::expect_used) +)] use thiserror::Error; diff --git a/src/paillier_affine_operation_in_range.rs b/src/paillier_affine_operation_in_range.rs index 1ea3091..4db2fb0 100644 --- a/src/paillier_affine_operation_in_range.rs +++ b/src/paillier_affine_operation_in_range.rs @@ -464,7 +464,7 @@ pub mod non_interactive { } /// Verify the proof, deriving challenge independently from same data - pub fn verify( + pub fn verify( shared_state: D, aux: &Aux, data: Data, @@ -480,7 +480,7 @@ pub mod non_interactive { } /// Deterministically compute challenge based on prior known values in protocol - pub fn challenge( + pub fn challenge( shared_state: D, aux: &Aux, data: Data,