Skip to content

Commit

Permalink
- spec clean up
Browse files Browse the repository at this point in the history
- vrf output
- Pederson setup
  • Loading branch information
drskalman committed Apr 3, 2024
1 parent 960d5fe commit 6b0ef4e
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 144 deletions.
32 changes: 19 additions & 13 deletions dleq_vrf/src/pedersen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Authors:
// - Jeffrey Burdges <jeff@web3.foundation>

//~ ### Pedersen VRF
//~ ## Pedersen VRF
//~
//~ Strictly speaking Pederson VRF is not a VRF. Instead, it proves
//~ that the output has been generated with a secret key associated
Expand Down Expand Up @@ -31,6 +31,12 @@ use crate::{
};


//~ ### Setup
//~
//~ PedersenVRF is initiated for prime subgroup $G < E$ of an elliptic
//~ curve E with $K, B \in G$ are defined to be *key base* and *blinding base*
//~ respectively.
//~
/// Pedersen VRF flavor
#[derive(Debug,Clone,Eq,PartialEq)]
pub struct PedersenVrf<K, H=K, const B: usize=1>
Expand Down Expand Up @@ -398,19 +404,19 @@ where K: AffineRepr, H: AffineRepr<ScalarField = K::ScalarField>,
{
let mut t = t.into_transcript();
let t = t.borrow_mut();
//~ Append(t, "PedersenVRF")
//~ Append$(t, "PedersenVRF")$
t.label(b"PedersenVRF");
let io = vrf::vrfs_merge(t, ios);
//~ Append$(t, ""KeyCommitment")$
//~ Append$(t, compk)$
//~ Append$(t, ""KeyCommitment")$
//~ Append$(t, compk)$
t.label(b"KeyCommitment");
t.append(&signature.compk);
//~ $z1 \leftarrow POrand + c \times PreOut - In \times ks
//~ $z1 \leftarrow POrand + c \times PreOut - In \times ks$

// verify_final
//~ Append$(t, "Pedersen R")$
//~ Append$(t, KBrand || PORand)$
//~ $c \leftarrow Challenge(t, "PedersenVrfChallenge")$
//~ Append$(t, "Pedersen R")$
//~ Append$(t, KBrand || PORand)$
//~ $c \leftarrow Challenge(t, "PedersenVrfChallenge")$
t.label(b"Pedersen R");
t.append(&signature.r);
let c: <K as AffineRepr>::ScalarField = t.challenge(b"PedersenVrfChallenge").read_reduce();
Expand All @@ -420,22 +426,22 @@ where K: AffineRepr, H: AffineRepr<ScalarField = K::ScalarField>,
// &[io.input, io.preoutput],
// &[-signature.s, c],
// ) + signature.r.into_group();
//~ $z1 \leftarrow POrand + c \times preoutput - input \times ks
//~ $z1 \leftarrow POrand + c \times preoutput - input \times ks$
let z1 = signature.r.preoutish.into_group() + io.preoutput.0 * c - io.input.0 * signature.s.keying;
//~ $z1 \leftarrow ClearCofactor(z1$)
//~ **if** $z1 \not \in $O$ **then** **return** False
//~ $z1 \leftarrow ClearCofactor(z1)$
//~ **if** $z1 \neq O$ **then** **return** False
if ! crate::zero_mod_small_cofactor(z1) {
return Err(SignatureError::Invalid);
}
// TODO: Use an MSM here
//~ $z2 \leftarrow KBrand + c \times compk - krand \times K$ - brand \times B$
//~ $z2 \leftarrow KBrand + c \times compk - krand \times K - brand \times B$
let mut z2 = signature.r.keyish.into_group() + signature.compk.0 * c;
z2 -= self.keying_base.mul(signature.s.keying);
for i in 0..B {
z2 -= self.blinding_bases[i].mul(signature.s.blindings[i]);
}
//~ $z2 \leftarrow ClearCofactor(z1)$
//~ **if** $z2 \not \in $O$ **then** **return** False **else** **return** True
//~ **if** $z2 \neq O$ **then** **return** False **else** **return** True
if ! crate::zero_mod_small_cofactor(z2) {
return Err(SignatureError::Invalid);
}
Expand Down
29 changes: 18 additions & 11 deletions dleq_vrf/src/vrf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
// Authors:
// - Jeffrey Burdges <jeff@web3.foundation>

//~ ## VRF
//~
//~ **Definition**: A *verifiable random function with auxiliary data (VRF-AD)* can be described with three functions:
//~
//~ - $VRF.KeyGen: () \mapsto (pk,sk)$ where $pk$ is a public key and $sk$ is its corresponding secret key.
Expand Down Expand Up @@ -32,13 +30,14 @@ use crate::{Transcript,IntoTranscript,transcript::AsLabel,SecretKey};

use core::borrow::{Borrow}; // BorrowMut

//~ For input $msg$ and $aux$ auxilary date first we compute the $VRFInput$ which is a point on elliptic curve $E$ as follows:
//~ For input $msg$ and $aux$ auxilary data first we compute the $VRFInput$ which is a point on elliptic curve $E$ as follows:
//
//~ $$ VRFiput := H2C(ArkTranscript(msg, aux) $$
//~ $$ t \leftarrow Transcript(msg) $$
//~ $$ VRFiput := H2C(challange(t, "vrf-input") $$
//~
//~ where
//~ - $ArkTranscript$ function is described in [[ark-transcript]] section.
//~ - $H2C: B \rightarrow G$ is a hash to curve function correspond to curve $E$ specified in Section [[hash-to-curve]] for the specific choice of $E$
//~ - $transcript$ function is described in [[ark-transcript]] section.
//~ - $H2C: B \rightarrow G$ is a hash to curve function correspond to curve $E$ specified in Section [[hash-to-curve]] for the specific choice of $E$
//~
/// Create VRF input points
///
Expand Down Expand Up @@ -85,8 +84,8 @@ where C: AffineRepr, H2C: HashToCurve<<C as AffineRepr>::Group>,

/// Actual VRF input, consisting of an elliptic curve point.
///
//~ ## EC VRF Input
//~ The EC-VRF input ultimately is a point on the elliptic curve
//~ ### VRF Input
//~ The VRF input ultimately is a point on the elliptic curve
//~ as out put of hash of the transcript using arkworks chosen hash
//~ for the given curve.
//~
Expand Down Expand Up @@ -137,8 +136,10 @@ impl<K: AffineRepr> SecretKey<K> {
}
}

//~ **Definition**: *VRF pre-output* is defined to be a point in $G$ in serialized affine representation
/// VRF pre-output, possibly unverified.
//~ ### VRF Preoutput and Output
//~ **Definition**: *VRF pre-output* is defined to be a point in $E$ in serialized affine representation.
//~
/// VRF pre-output, possibly unverified.
#[derive(Debug,Copy,Clone,PartialEq,Eq,CanonicalSerialize,CanonicalDeserialize)] // Copy, Default, PartialOrd, Ord, Hash
#[repr(transparent)]
pub struct VrfPreOut<C: AffineRepr>(pub C);
Expand Down Expand Up @@ -191,7 +192,7 @@ pub fn collect_preoutputs_vec<C: AffineRepr>(ios: &[VrfInOut<C>]) -> Vec<VrfPreO
).collect::<Vec<VrfPreOut<C>>>()
}

//~ ** Definition **: *VRF InOut* is defined as a pair as follows:
//~ **Definition**: *VRF InOut* is defined as a pair as follows:
//~ $$(VRF Input, VRF Preoutput)$$
/// VRF input and pre-output paired together, possibly unverified.
///
Expand All @@ -205,6 +206,12 @@ pub struct VrfInOut<C: AffineRepr> {
}

impl<C: AffineRepr> VrfInOut<C> {
//~ **Definition**: *VRF output* is generated using VRF preoutput:
//~ $$ t \leftarrow Transcript(Domain) $$
//~ $$ append(t, "VrfOutput") $$
//~ $$ append(t, cofactor * VRFpreout) $$
//~ $$ VRFoutput \leftarrow t.challenge("") $$

/// Append to VRF output transcript, suitable for producing VRF output.
///
/// We incorporate both the input and output to provide the 2Hash-DH
Expand Down
125 changes: 51 additions & 74 deletions spec/specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@
**Definition**: For an elliptic curve $E$ defined over finite field $F$ with large prime subgroup $G$ generated by point $g$, we call a VRF, EC-VRF is VRF-AD where $pk = sk.g$ and $VRF.Sign$ is an elliptic curve signature scheme.

All VRFs described in this specification are EC-VRF.
For input $msg$ and $aux$ auxilary date first we compute the $VRFInput$ which is a point on elliptic curve $E$ as follows:
$$ VRFiput := H2C(ArkTranscript(msg, aux) $$
For input $msg$ and $aux$ auxilary data first we compute the $VRFInput$ which is a point on elliptic curve $E$ as follows:
$$ t \leftarrow Transcript(msg) $$
$$ VRFiput := H2C(challange(t, "vrf-input") $$

where
- $ArkTranscript$ function is described in [[ark-transcript]] section.
- $H2C: B \rightarrow G$ is a hash to curve function correspond to curve $E$ specified in Section [[hash-to-curve]] for the specific choice of $E$
- $transcript$ function is described in [[ark-transcript]] section.
- $H2C: B \rightarrow G$ is a hash to curve function correspond to curve $E$ specified in Section [[hash-to-curve]] for the specific choice of $E$

## EC VRF Input
The EC-VRF input ultimately is a point on the elliptic curve
### VRF Input
The VRF input ultimately is a point on the elliptic curve
as out put of hash of the transcript using arkworks chosen hash
for the given curve.

Expand All @@ -29,13 +30,17 @@ output of the transcripto or ocasionally some base point.
It should never be sent over the wire nor deserialized???Do you mean serialized?


**Definition**: *VRF pre-output* is defined to be a point in $G$ in serialized affine representation
** Definition **: *VRF InOut* is defined as a pair as follows:
$$(VRF Input, VRF Preoutput)$$

### VRF Preoutput and Output
**Definition**: *VRF pre-output* is defined to be a point in $E$ in serialized affine representation.

**Definition**: *VRF InOut* is defined as a pair as follows:
$$(VRF Input, VRF Preoutput)$$
**Definition**: *VRF output* is generated using VRF preoutput:
$$ t \leftarrow Transcript(Domain) $$
$$ append(t, "VrfOutput") $$
$$ append(t, cofactor * VRFpreout) $$
$$ VRFoutput \leftarrow t.challenge("") $$

### Preliminaries


### VRF Key
Expand All @@ -47,60 +52,12 @@ Public key is represented in Affine form and is serialized using Arkwork compres
format.


### VRF input

Procedure to map arbitrary user input to a point follows the `hash_to_curve`
procedure described by RFC9380.

Suite_ID: "bandersnatch_XMD:SHA-512_ELL2_RO_"

See [ArkTranscript](TODO) for details.

#### From transcript to point

You need to call challenge and add b"vrf-input" to it. getting random byte (some hash?)
then hash to curve it.

## DELQ VRF

### Preliminaries

Implements the two relevant verifiable random functions (VRFs) with
associated data (VRF-ADs) which arise from Chaum-Pedersen DLEQ proofs,
polymorphic over Arkworks' elliptic curves.

Thin VRF aka `ThinVrf` provides a regular VRF similar but broadly superior
to ["EC VRF"](https://www.ietf.org/id/draft-irtf-cfrg-vrf-15.html).
Thin VRF support batch verification or half-aggregation exactly like
Schnorr signatures, but which ECVRF lacks.
In essence, thin VRF *is* a Schnorr signature with base point given by
a pseudo-random (Fiat-Shamir) linear combination of base points, while
EC VRF is two linked Schnorr signatures on distinct base points.
Thin VRF should be slightly faster than EC VRF, be similarly sized on
typical Edwards curves, but slightly larger on larger BLS12 curves.
As a rule, new applications should always prefer thin VRF over EC VRF.

Pedersen VRF aka `PedersenVRF` resembles EC VRF but replaces the
### Pedersen VRF
Pedersen VRF resembles EC VRF but replaces the
public key by a Pedersen commitment to the secret key, which makes the
Pedersen VRF useful in anonymized ring VRFs, or perhaps group VRFs.
We provide both batchable and nonbatchable forms of the Pedresen VRF.
We favor the batchable form because our blinding factors enlarge our
signatures anyways, making the batchable form less significant
proportionally than batchable forms of EV VRF.

As the Pedersen VRF needs two verification equations, we support
DLEQ proofs between two distinct curves provided both have the same
subgroup order. Around this, we support omitting the blinding factors
for cross curve DLEQ proofs, like proving public keys on G1 and G2
of a BLS12 curve have the same secret key.



### Thin VRF

### Pedersen VRF

### Pedersen VRF
## Pedersen VRF

Strictly speaking Pederson VRF is not a VRF. Instead, it proves
that the output has been generated with a secret key associated
Expand All @@ -109,6 +66,12 @@ key is a cryptographic commitement to the public key. And it could
unblinded to prove that the output of the VRF is corresponds to
the public key of the signer.

### Setup

PedersenVRF is initiated for prime subgroup $G < E$ of an elliptic
curve E with $K, B \in G$ are defined to be *key base* and *blinding base*
respectively.

### PedersenVRF.Sign
**Inputs**:
- Transcript $t$ of `ArkTranscript` type\
Expand Down Expand Up @@ -149,25 +112,39 @@ the public key of the signer.

---

Append(t, "PedersenVRF")
Append$(t, ""KeyCommitment")$
Append$(t, compk)$
$z1 \leftarrow POrand + c \times PreOut - In \times ks
Append$(t, "Pedersen R")$
Append$(t, KBrand || PORand)$
$c \leftarrow Challenge(t, "PedersenVrfChallenge")$
$z1 \leftarrow POrand + c \times preoutput - input \times ks
$z1 \leftarrow ClearCofactor(z1$)
**if** $z1 \not \in $O$ **then** **return** False
$z2 \leftarrow KBrand + c \times compk - krand \times K$ - brand \times B$
Append$(t, "PedersenVRF")$
Append$(t, ""KeyCommitment")$
Append$(t, compk)$
$z1 \leftarrow POrand + c \times PreOut - In \times ks$
Append$(t, "Pedersen R")$
Append$(t, KBrand || PORand)$
$c \leftarrow Challenge(t, "PedersenVrfChallenge")$
$z1 \leftarrow POrand + c \times preoutput - input \times ks$
$z1 \leftarrow ClearCofactor(z1)$
**if** $z1 \neq O$ **then** **return** False
$z2 \leftarrow KBrand + c \times compk - krand \times K - brand \times B$
$z2 \leftarrow ClearCofactor(z1)$
**if** $z2 \not \in $O$ **then** **return** False **else** **return** True
**if** $z2 \neq O$ **then** **return** False **else** **return** True

---


## Bandersnatch VRF

### VRF input

Procedure to map arbitrary user input to a point follows the `hash_to_curve`
procedure described by RFC9380.

Suite_ID: "bandersnatch_XMD:SHA-512_ELL2_RO_"

See [ArkTranscript](TODO) for details.

#### From transcript to point

You need to call challenge and add b"vrf-input" to it. getting random byte (some hash?)
then hash to curve it.

## Transcript

A Shake-128 based transcript construction which implements the Fiat-Shamir
Expand Down
Loading

0 comments on commit 6b0ef4e

Please sign in to comment.