Skip to content

Commit

Permalink
Add spec for KVAC
Browse files Browse the repository at this point in the history
Signed-off-by: lovesh <[email protected]>
  • Loading branch information
lovesh committed Aug 18, 2023
1 parent 9876abe commit 4e09f77
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ members = [
"secret_sharing_and_dkg",
"legogroth16",
"oblivious_transfer",
"merlin"
"merlin",
"kvac"
]
resolver = "2"

Expand Down
31 changes: 31 additions & 0 deletions kvac/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "kvac"
version = "0.1.0"
edition.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
description = "Keyed-Verification Anonymous Credentials (KVAC) and Algebraic MACs"

[dependencies]
ark-ff.workspace = true
ark-ec.workspace = true
ark-std.workspace = true
ark-serialize.workspace = true
digest.workspace = true
zeroize.workspace = true
dock_crypto_utils = { version = "0.14.0", default-features = false, path = "../utils" }
schnorr_pok = { version = "0.13.0", default-features = false, path = "../schnorr_pok" }
rayon = {workspace = true, optional = true}

[dev-dependencies]
blake2.workspace = true
ark-bls12-381.workspace = true
ark-ed25519 = { version = "^0.4.0", default-features = false }
ark-curve25519 = { version = "^0.4.0", default-features = false }
ark-secp256k1 = { version = "^0.4.0", default-features = false }

[features]
default = [ "parallel"]
std = [ "ark-ff/std", "ark-ec/std", "ark-std/std", "ark-serialize/std"]
parallel = [ "std", "ark-ff/parallel", "ark-ec/parallel", "ark-std/parallel", "rayon"]
11 changes: 11 additions & 0 deletions kvac/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Keyed-Verification Anonymous Credentials (KVAC)

<!-- cargo-rdme start -->

Implements Keyed-Verification Anonymous Credentials (KVAC) schemes from the following papers.
KVACs are supposed to be verified by the issuer only (or anyone who shares the issuer's key)

1. [Improved Algebraic MACs and Practical Keyed-Verification Anonymous Credentials](https://link.springer.com/chapter/10.1007/978-3-319-69453-5_20) is [here](./src/bbdt_2016)
2. [Fast Keyed-Verification Anonymous Credentials on Standard Smart Cards](https://eprint.iacr.org/2019/460) is [here](./src/cddh_2019)

<!-- cargo-rdme end -->
54 changes: 54 additions & 0 deletions kvac/src/bddt_2016/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//! Implements KVAC from [Improved Algebraic MACs and Practical Keyed-Verification Anonymous Credentials](https://link.springer.com/chapter/10.1007/978-3-319-69453-5_20)
//!
//! MAC_BB - Follows section 3.2 of the paper
//! - All parties have access to `MACParams`, i.e. random G1 element `f, h, g, g_0, g_1, g_2, ..., g_n`. `MACParams` are like `SignatureParams` in BBS+.
//! - Signer creates secret key as a random field element `y` and public key `Y = g_0 * y` in group G1.
//! - MAC `generate` and `verify` work as mentioned in the paper.
//! - `MAC::generate` should accept `messages`, `sk` and `MACParams`
//! - `MAC::generate_with_committed_messages` should accept an additional commitment to messages. These are similar to `SignatureG1::new` and `SignatureG1::new_with_committed_messages`
//!
//! Signature - Follows Fig.2 (1) with some changes mentioned below.
//! - The signing API is almost same as BBS+ but unlike BBS+, signature will always be in group G1
//! - Like BBS+, signer might not know all attribute or might only some and receive a commitment to the the hidden attributes.
//! - Deviating from the paper, the user only generates his own `s` during blind signing, same as in BBS+. Also the signer
//! does not send the proof `pi_2` with the signature and user stores only `A`, `s` and `r` but not `C_m` as that can be
//! computed because he knows all `m`.
//! - The user does not send proof `pi_1` as this is created using `proof_system` crate, just like with BBS+. Its assumed that
//! signer has verified that proof before calling sign.
//! - User unblinds the signature like in BBS+ when received a blind signature
//! - Uses MAC_BB from above
//!
//! Proof of knowledge of signature - Follows Fig.2 (2)
//! - Proof generation follow similar API as `PoKOfSignatureG1Protocol` - `init`, `challenge_contribution` and `gen_proof`.
//! - In `init`
//! - Given signature `A`, `s` and `r` and accept blindings for hidden messages like `PoKOfSignatureG1Protocol::init`
//! - Pick random field elements `l` and `t`
//! - Compute `C_m = \sum_i(g_i * m_i) + g * s + h` for all messages `m_i` regardless of them being revealed or not.
//! - Compute `B_0 = A * l` and `C = C_m * l + B_0 * -r`
//! - 3 Schnorr's PoK will be created for relations
//! 1. `E = C * 1/l + f * t`
//! 2. `C = E * l + f * -l*t`
//! 3. `E - h = g * s + B_0 * -r/l + f * t + \sum_j(g_j * m_j)` for messages `m_j` not being revealed
//! - 3 `SchnorrCommitment` and witness sets will be created as below, 1 for each of the above relation. Blindings `r_*` are randomly picked
//! 1. Create `SchnorrCommitment` with bases `[C, f]` and blindings `[r_1, r_2]`. Set its witness as `[1/l, t]`
//! 2. Create `SchnorrCommitment` with bases `[E, f]` and blindings `[r_3, r_4]`. Set its witness as `[l, -l*t]`
//! 3. Create `SchnorrCommitment` with bases `[g, B_0, f, <all g_j, ..>]`. `<all g_j, ..>` correspond to `g_*` for messages that are not revealed.
//! Set blindings as `[r_5, r_6, r_2, <all r_j, ...>]` where `<all r_j, ...>` correspond to blindings for hidden messages. These are randomly generated
//! if not provided to `init`. Set its witness as `[s, -r/l, t, <all m_j, ...>]` where `<all m_j, ...>` are the messages not revealed
//! - In `challenge_contribution`, serialize the following for challenge
//! - `E`, `C`, `f`, `h`, `g`, `B_0` and all `g_j` corresponding to all `m_j` not revealed.
//! - `\sum_i(g_i * m_i)` for all revealed messages `m_i`
//! - In `gen_proof`
//! - Generate responses for all 3 `SchnorrCommitment` above
//! - The proof struct will contains above 3 responses, `t` from all 3 Schnorr commitments and `B_0`, `C` and `E`
//! - In `Proof::verify`
//! 1. Check if `C == B_0 * y`
//! 2. Verify 1st Schnorr response by passing bases mentioned above, `E` and challenge
//! 3. Verify 2nd Schnorr response by passing bases mentioned above, `C` and challenge
//! 4. For 3rd Schnorr response, create bases as above and for argument `y` of `SchnorrResponse::is_valid`, pass `E - h - \sum_i{g_i * m_i}` for all `m_i` that are revealed
//! - Add a function called `Proof::verify_schnorr_proofs` which is same as `Proof::verify` except it does not do check 1.
//! - Add a function called `Proof::verify_except_schnorr_proofs` which does check 1 from `Proof::verify`
//! - The purpose of above 2 functions is to split the signer's/verifier's task into 2 parts where `Proof::verify_schnorr_proofs`
//! can be done by an untrusted helper who does not know secret key `y` but `Proof::verify_except_schnorr_proofs` requires knowing
//! secret key
//! - Add a function `get_resp_for_message` to get Schnorr responses for the hidden messages
45 changes: 45 additions & 0 deletions kvac/src/cddh_2019/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! Implements KVAC from [Fast Keyed-Verification Anonymous Credentials on Standard Smart Cards](https://eprint.iacr.org/2019/460)
//!
//! MAC_wBB - Follows section 3 of the paper
//! - Setup params contain a random G1 group element `g`. Creating by hashing a label.
//! - Secret key contains random field elements `x_i` and public key has same number of `X_i = g * x_i`.
//! `i` would be an upper bound on number of supported messages and passed as an argument like PS sig
//! - Signing and verification work as described in the paper.
//!
//! Signature - Follows section 4.
//! - Does not support blind signing (for now) so the signer has to know all messages.
//! - Signer returns 2 objects, the signature composed of all `sigma`s and the proof composed of `2*n` Schnorr proofs
//! for total `2*n` relations, each pair of the form `sigma_{x_i} = sigma * x_i` and `X_i = g * x_i`. For each `i`,
//! - Generate random field element `r_i`
//! - Use `impl_proof_of_knowledge_of_discrete_log` to create a Schnorr protocol and call its `init` with witness `x_i`, blinding `r_i` and base `sigma`.
//! - Use `impl_proof_of_knowledge_of_discrete_log` to create a Schnorr protocol and call its `init` with witness `x_i`, blinding `r_i` and base `g`.
//! For each of the above `2*n`, protocols generate their challenge contribution, hash to create the challenge and then generate `2*n` proofs.
//! - Use above MAC to generate `sigma` and `sigma_{x_i}` for `i` = 0 to `n`.
//! - User on getting signature verifies the `2*n` proofs and checks that the response for each of the `i` pairs above is same so `n` different responses in total.
//! - After verifying, user discards the proof but keeps `sigma` and all `sigma_{x_i}`
//! - The above can be made efficient by combining `2*n` relations into 1 using a challenge but thats an optimization for later.
//!
//! Proof of knowledge of signature - Follows section 4.2
//! - Proof generation follow similar API as `PoKOfSignatureG1Protocol` - `init`, `challenge_contribution` and `gen_proof`.
//! - In `init`
//! - Given signature `sigma` and `sigma_{x_i}`, accept blindings for hidden messages like `PoKOfSignatureG1Protocol::init`
//! - Generate random field element `r` and `sigma_hat = sigma * r`.
//! - The existing Schnorr protocol abstraction can't be used because the verifier can himself create bases for the commitment.
//! - Get `k+1` random blindings where `k` is the number of hidden attributes. blindings = `[rho_r, <rho_k, ...>]`. Here `<rho_k, ...>`
//! correspond to the blindings for hidden attributes and are either generated randomly or passed as argument.
//! - Use an MSM to create `t = g * rho_r + \sum_k{sigma_{x_k} * rho_k * r}` for all hidden message `m_k`
//! - Set witness as `[r, <m_k, ...>]` for all hidden attributes `m_k`.
//! - In `challenge_contribution`, serialize the following for challenge
//! - `t`, `g`, `sigma_hat` and `sigma_{x_k}` for all hidden message `m_k`
//! - `\sum_i(sigma_{x_i} * m_i)` for all revealed messages `m_i`
//! - In `gen_proof`
//! - Generate responses `s_rho = rho_r + c * r` and `s_k = rho_k - c * m_k` for challenge `c` and for hidden message `m_k`
//! - The proof contains above responses and `sigma_hat`
//! - In `Proof::verify`
//! - Accepts revealed messages `m_i` and challenge `c`
//! - Check if `t == g * s_rho + sigma_hat * (\sum_k(x_k * s_k) - c * (\sum_i(x_i * m_i) - x_0))` for revealed messages `m_i` and hidden messages `m_k`.
//! - Add a function called `Proof::verify_given_commitment_to_known_message` that accepts `sigma_hat * c * (\sum_i(x_i * m_i) - x_0)` instead
//! of revealed messages `m_i` and challenge `c`. Objective is to hide the revealed messages from this function.
//! - Add a function `Proof::split` to split the proof into a struct that can be verified in `verify_given_commitment_to_known_message`. Or maybe
//! add a separate struct for just delegated proofs.
//! - Add a function `get_resp_for_message` to get Schnorr responses for the hidden messages
10 changes: 10 additions & 0 deletions kvac/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![cfg_attr(not(feature = "std"), no_std)]

//! Implements Keyed-Verification Anonymous Credentials (KVAC) schemes from the following papers.
//! KVACs are supposed to be verified by the issuer only (or anyone who shares the issuer's key)
//!
//! 1. [Improved Algebraic MACs and Practical Keyed-Verification Anonymous Credentials](https://link.springer.com/chapter/10.1007/978-3-319-69453-5_20) is [here](./src/bbdt_2016)
//! 2. [Fast Keyed-Verification Anonymous Credentials on Standard Smart Cards](https://eprint.iacr.org/2019/460) is [here](./src/cddh_2019)

pub mod bddt_2016;
pub mod cddh_2019;

0 comments on commit 4e09f77

Please sign in to comment.