diff --git a/Specification.toml b/Specification.toml index 51cee2a..07e03db 100644 --- a/Specification.toml +++ b/Specification.toml @@ -7,16 +7,9 @@ authors = ["Alistair, Davide, Jeff, Syed, Sergey"] template = "specification_template.md" [sections] -# DLEQ VRF -dleq-vrf-preliminaries = "dleq_vrf/src/lib.rs" ## VRF vrf = "dleq_vrf/src/vrf.rs" -### VRF Keys -vrf-keys = "dleq_vrf/src/keys.rs" - -## Thin VRF - +# DLEQ VRF +dleq-vrf-preliminaries = "dleq_vrf/src/lib.rs" ## Pedersen VRF pedersen-vrf = "dleq_vrf/src/pedersen.rs" - -# Bandersnatch VRF diff --git a/dleq_vrf/src/keys.rs b/dleq_vrf/src/keys.rs index e195ce6..5e9d537 100644 --- a/dleq_vrf/src/keys.rs +++ b/dleq_vrf/src/keys.rs @@ -24,10 +24,7 @@ use crate::{ }; -//~ #### Public key \ -//~ \ -//~ A Public key of a VRF is a point on an Elliptic Curve $E$. \ -#[derive(Debug,Clone,Eq,Hash,CanonicalSerialize,CanonicalDeserialize)] // Copy, PartialOrd, Ord, Hash, +#[derive(Debug, Clone, Eq, Hash, CanonicalSerialize, CanonicalDeserialize)] // Copy, PartialOrd, Ord, Hash, #[repr(transparent)] pub struct PublicKey(pub C); @@ -37,9 +34,6 @@ impl PartialEq for PublicKey { } } -//~ Public key is represented in Affine form and is serialized using Arkwork compressed serialized -//~ format. -// /// Arkworks' own serialization traits should be preferred over these. impl PublicKey { pub fn update_digest(&self, h: &mut impl Update) { @@ -259,4 +253,3 @@ impl SecretKey { } */ } - diff --git a/dleq_vrf/src/vrf.rs b/dleq_vrf/src/vrf.rs index 1f2f562..c4dde11 100644 --- a/dleq_vrf/src/vrf.rs +++ b/dleq_vrf/src/vrf.rs @@ -3,18 +3,27 @@ // Authors: // - Jeffrey Burdges -//~ **Definition**: A *verifiable random function with auxiliary data (VRF-AD)* can be described with three functions: +//~ **Definition**: A *verifiable random function with additional data (VRF-AD)* +//~ can be described with four functions: //~ -//~ - $VRF.KeyGen: () \mapsto (pk,sk)$ where $pk$ is a public key and $sk$ is its corresponding secret key. -//~ - $VRF.Sign : (sk,msg,aux) \mapsto \sigma$ takes a secret key $sk$, an input $msg$, and auxiliary data $aux$, and then returns a VRF signature $\sigma$. -//~ - $VRF.Eval : (sk, msg) \mapsto Out$ takes a secret key $sk$ and an input $msg$, and then returns a VRF output $Out$. -//~ - $VRF.Verify: (pk,msg,aux,\sigma)\mapsto (Out|prep)$ for a public key pk, an input msg, and auxiliary data aux, and then returns either an output $Out$ or else failure $perp$. -//~ -//~ **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. +//~ - $VRF.KeyGen: () \mapsto (pk,sk)$ where $pk$ is a public key and $sk$ is +//~ its corresponding secret key. +//~ - $VRF.Sign : (sk,msg,ad) \mapsto \pi$ takes a secret key $sk$, an input $msg$, +//~ and additional data $ad$, and returns a VRF signature $\pi$. +//~ - $VRF.Eval : (sk, msg) \mapsto Out$ takes a secret key $sk$ and an input $msg$, +//~ and returns a VRF output $out$. +//~ - $VRF.Verify: (pk,msg,aux,\pi) \mapsto (out|prep)$ for a public key $pk$, +//~ an input $msg$, and additional data $ad$, and then returns either an output +//~ $out$ or else failure $perp$. +//~ +//~ **Definition**: For an elliptic curve $E$ defined over finite field $F$ with +//~ large prime subgroup $G$ generated by point $g$, an EC-VRF is VRF-AD +//~ where $pk = sk \cdot g$ and $VRF.Sign$ is based on an elliptic curve signature +//~ scheme. //~ //~ All VRFs described in this specification are EC-VRF. - -//! All VRFs expect a point on the curve as their input. +//~ +//! All VRFs expect a point on the curve as their input. //! ### VRF input and output handling //! //! We caution that ring VRFs based upon DLEQ proofs like ours require @@ -30,20 +39,23 @@ use crate::{Transcript,IntoTranscript,transcript::AsLabel,SecretKey}; use core::borrow::{Borrow}; // BorrowMut -//~ For input $msg$ and $aux$ auxilary data first we compute the $VRFInput$ which is a point on elliptic curve $E$ as follows: +//~ For input $msg$ and $ad$ additional 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") $$ +//~ $$ t \leftarrow Transcript(msg) $$ +//~ $$ VRFInput := H2C(challange(t, "vrf-input") $$ //~ -//~ where -//~ - $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$ +//~ +//~ Where: +//~ - $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 /// /// You select your own hash-to-curve by implementing this trait /// upon your own wrapper type. -/// +/// /// Instead of our method being polymorphic, we impose the type parameter /// in the trait because doing so simplifies the type annotations. pub trait IntoVrfInput { @@ -81,28 +93,25 @@ where C: AffineRepr, H2C: HashToCurve<::Group>, Ok(VrfInput( H2C::new(domain.as_label())?.hash(message)? )) } - /// Actual VRF input, consisting of an elliptic curve point. /// //~ ### 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. -//~ -//~ VRF Input point should always be created locally, either as a hash-to-cuve -//~ output of the transcripto or ocasionally some base point. -//~ It should never be sent over the wire nor deserialized???Do you mean serialized? //~ +//~ The VRF Input is a point on the elliptic curve E and generated +//~ as output of the Elligator 2 hash-to-curve algorithm +//~ as described by section 6.8.2 of [RFC9380](https://datatracker.ietf.org/doc/rfc9380/). +//~ The algorithm yields a point which is inside the prime order +//~ subgroup of E. //~ /// `VrfInput` should always be consructed inside the prime order /// subgroup, as otherwise risks leaking secret key material. -/// +/// /// We do not enforce that key material be hashed in hash-to-curve, /// so our VRF pre-outputs and signatures reveal VRF outputs for /// algebraically related secret keys. We need this for ring VRFs /// but this makes insecure the soft derivations in hierarchical /// key derivation (HDKD) schemes. -/// +/// /// As a defense in depth, we suggest thin VRF usages hash their /// public, given some broken applications might do soft derivations /// anyways. @@ -137,8 +146,11 @@ impl SecretKey { } //~ ### VRF Preoutput and Output -//~ **Definition**: *VRF pre-output* is defined to be a point in $E$ in serialized affine representation. -//~ +//~ +//~ **Definition**: *VRF pre-output* is generated using VRF input point as: +//~ +//~ $$ PreOutput \leftarrow sk \cdot VrfInput $$ +//~ /// VRF pre-output, possibly unverified. #[derive(Debug,Copy,Clone,PartialEq,Eq,CanonicalSerialize,CanonicalDeserialize)] // Copy, Default, PartialOrd, Ord, Hash #[repr(transparent)] @@ -192,11 +204,7 @@ pub fn collect_preoutputs_vec(ios: &[VrfInOut]) -> Vec>>() } -//~ **Definition**: *VRF InOut* is defined as a pair as follows: -//~ $$(VRF Input, VRF Preoutput)$$ /// VRF input and pre-output paired together, possibly unverified. -/// -/// #[derive(Debug,Copy,Clone,CanonicalSerialize)] // CanonicalDeserialize, PartialEq,Eq, PartialOrd, Ord, Hash pub struct VrfInOut { /// VRF input point @@ -206,11 +214,9 @@ pub struct VrfInOut { } impl VrfInOut { - //~ **Definition**: *VRF output* is generated using VRF preoutput: - //~ $$ t \leftarrow Transcript(Domain) $$ - //~ $$ append(t, "VrfOutput") $$ - //~ $$ append(t, cofactor * VRFpreout) $$ - //~ $$ VRFoutput \leftarrow t.challenge("") $$ + //~ **Definition**: *VRF output* is generated using *VRF pre-output* point as: + //~ $$ VrfOutput \leftarrow Hash("vrfoutput", Encode(PreOutput)) $$ + //~ /// Append to VRF output transcript, suitable for producing VRF output. /// @@ -338,6 +344,3 @@ where #[cfg(test)] mod tests { } - - - diff --git a/spec/specification.md b/spec/specification.md index 36206cd..7e82f3d 100644 --- a/spec/specification.md +++ b/spec/specification.md @@ -1,59 +1,66 @@ # Bandersnatch VRFs -## VRF +## Introduction + +**Definition**: A *verifiable random function with additional data (VRF-AD)* +can be described with four functions: + +- $VRF.KeyGen: () \mapsto (pk,sk)$ where $pk$ is a public key and $sk$ is + its corresponding secret key. +- $VRF.Sign : (sk,msg,ad) \mapsto \pi$ takes a secret key $sk$, an input $msg$, + and additional data $ad$, and returns a VRF signature $\pi$. +- $VRF.Eval : (sk, msg) \mapsto Out$ takes a secret key $sk$ and an input $msg$, + and returns a VRF output $out$. +- $VRF.Verify: (pk,msg,aux,\pi) \mapsto (out|prep)$ for a public key $pk$, + an input $msg$, and additional data $ad$, and then returns either an output + $out$ or else failure $perp$. + +**Definition**: For an elliptic curve $E$ defined over finite field $F$ with +large prime subgroup $G$ generated by point $g$, an EC-VRF is VRF-AD +where $pk = sk \cdot g$ and $VRF.Sign$ is based on an elliptic curve signature +scheme. -**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. -- $VRF.Sign : (sk,msg,aux) \mapsto \sigma$ takes a secret key $sk$, an input $msg$, and auxiliary data $aux$, and then returns a VRF signature $\sigma$. -- $VRF.Eval : (sk, msg) \mapsto Out$ takes a secret key $sk$ and an input $msg$, and then returns a VRF output $Out$. -- $VRF.Verify: (pk,msg,aux,\sigma)\mapsto (Out|prep)$ for a public key pk, an input msg, and auxiliary data aux, and then returns either an output $Out$ or else failure $perp$. +All VRFs described in this specification are EC-VRF. -**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. +For input $msg$ and $ad$ additional data first we compute the $VRFInput$ +which is a point on elliptic curve $E$ as follows: +$$ t \leftarrow Transcript(msg) $$ +$$ VRFInput := H2C(challange(t, "vrf-input") $$ -All VRFs described in this specification are EC-VRF. -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 -- $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$ +Where: +- $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$ ### 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. - -VRF Input point should always be created locally, either as a hash-to-cuve -output of the transcripto or ocasionally some base point. -It should never be sent over the wire nor deserialized???Do you mean serialized? +The VRF Input is a point on the elliptic curve E and generated +as output of the Elligator 2 hash-to-curve algorithm +as described by section 6.8.2 of [RFC9380](https://datatracker.ietf.org/doc/rfc9380/). +The algorithm yields a point which is inside the prime order +subgroup of E. ### 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("") $$ +**Definition**: *VRF pre-output* is generated using VRF input point as: +$$ PreOutput \leftarrow sk \cdot VrfInput $$ -### VRF Key +**Definition**: *VRF output* is generated using *VRF pre-output* point as: +$$ VrfOutput \leftarrow Hash("vrfoutput", Encode(PreOutput)) $$ -#### Public key \ -\ -A Public key of a VRF is a point on an Elliptic Curve $E$. \ -Public key is represented in Affine form and is serialized using Arkwork compressed serialized -format. ## IETF VRF -Refer to [RFC-9381](https://www.rfc-editor.org/rfc/rfc9381) for the details. +Definition of a VRF based on the IETF [RFC-9381](https://www.rfc-editor.org/rfc/rfc9381). + +All the details specified by the RFC applies with the additional capability to add additional +data (`ad`) as per definition of EC-VRF we've given. In particular the step 5 of section +5.4.3 is defined as: + + str = str || ad || challenge_generation_domain_separator_back ### Bandersnatch Cipher Suite Configuration @@ -100,9 +107,10 @@ Configuration follows the RFC-9381 suite specification guidelines. * The hash function Hash is SHA-512 as specified in [RFC6234](https://www.rfc-editor.org/rfc/rfc6234), with hLen = 64. -* The ECVRF_encode_to_curve function is as specified in - Section 5.4.1.2, with `h2c_suite_ID_string` = `"BANDERSNATCH_XMD:BLAKE2b_ELL2_RO_"`. - The suite is defined in Section 8.5 of [RFC9380](https://datatracker.ietf.org/doc/rfc9380/). +* The `ECVRF_encode_to_curve` function (*Elligator2*) is as specified in + Section 5.4.1.2, with `h2c_suite_ID_string` = `"BANDERSNATCH_XMD:SHA-512_ELL2_RO_"`. + The suite must be interpreted as defined by Section 8.5 of [RFC9380](https://datatracker.ietf.org/doc/rfc9380/) + and using the domain separation tag `DST = "ECVRF_" || h2c_suite_ID_string || suite_string`. ## Pedersen VRF @@ -181,36 +189,3 @@ $z2 \leftarrow ClearCofactor(z1)$ --- - -## 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 -transform procedure. - -We do basic domain separation using postfix writes of the lengths of written -data (as opposed to the prefix writes by [Merlin](https://merlin.cool) -`TupleHash` from [SP 800-185](https://csrc.nist.gov/pubs/sp/800/185/final)). - - H(item_1, item_2, ..., item_n) - -Represents the application of shake-128 to the concatenation of the serialization of each item -followed by the serialization of the length of each objects, as a 32-bit unsigned integer. - - bytes = encode(item_1) || encode(length(item_1)) || .. || encode(item_n) || encode(length(item_n)) - Shake128(bytes) - -The length of each item should be less than 2^31. diff --git a/spec/specification.pdf b/spec/specification.pdf index 7afd10a..b228394 100644 Binary files a/spec/specification.pdf and b/spec/specification.pdf differ diff --git a/spec/specification.tex b/spec/specification.tex index 6bd5415..366f2b3 100644 --- a/spec/specification.tex +++ b/spec/specification.tex @@ -55,11 +55,11 @@ \hypertarget{bandersnatch-vrfs}{% \section{Bandersnatch VRFs}\label{bandersnatch-vrfs}} -\hypertarget{vrf}{% -\subsection{VRF}\label{vrf}} +\hypertarget{introduction}{% +\subsection{Introduction}\label{introduction}} -\textbf{Definition}: A \emph{verifiable random function with auxiliary -data (VRF-AD)} can be described with three functions: +\textbf{Definition}: A \emph{verifiable random function with additional +data (VRF-AD)} can be described with four functions: \begin{itemize} \tightlist @@ -67,76 +67,70 @@ \subsection{VRF}\label{vrf}} \(VRF.KeyGen: () \mapsto (pk,sk)\) where \(pk\) is a public key and \(sk\) is its corresponding secret key. \item - \(VRF.Sign : (sk,msg,aux) \mapsto \sigma\) takes a secret key \(sk\), - an input \(msg\), and auxiliary data \(aux\), and then returns a VRF - signature \(\sigma\). + \(VRF.Sign : (sk,msg,ad) \mapsto \pi\) takes a secret key \(sk\), an + input \(msg\), and additional data \(ad\), and returns a VRF signature + \(\pi\). \item \(VRF.Eval : (sk, msg) \mapsto Out\) takes a secret key \(sk\) and an - input \(msg\), and then returns a VRF output \(Out\). + input \(msg\), and returns a VRF output \(out\). \item - \(VRF.Verify: (pk,msg,aux,\sigma)\mapsto (Out|prep)\) for a public key - pk, an input msg, and auxiliary data aux, and then returns either an - output \(Out\) or else failure \(perp\). + \(VRF.Verify: (pk,msg,aux,\pi) \mapsto (out|prep)\) for a public key + \(pk\), an input \(msg\), and additional data \(ad\), and then returns + either an output \(out\) or else failure \(perp\). \end{itemize} \textbf{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 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 - \(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\) +field \(F\) with large prime subgroup \(G\) generated by point \(g\), an +EC-VRF is VRF-AD where \(pk = sk \cdot g\) and \(VRF.Sign\) is based on +an elliptic curve signature scheme. + +All VRFs described in this specification are EC-VRF. + +For input \(msg\) and \(ad\) additional data first we compute the +\(VRFInput\) which is a point on elliptic curve \(E\) as follows: +\[ t \leftarrow Transcript(msg) \] +\[ VRFInput := H2C(challange(t, "vrf-input") \] + +Where: - \(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\) \hypertarget{vrf-input}{% \subsubsection{VRF Input}\label{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. - -VRF Input point should always be created locally, either as a -hash-to-cuve output of the transcripto or ocasionally some base point. -It should never be sent over the wire nor deserialized???Do you mean -serialized? +The VRF Input is a point on the elliptic curve E and generated as output +of the Elligator 2 hash-to-curve algorithm as described by section 6.8.2 +of \href{https://datatracker.ietf.org/doc/rfc9380/}{RFC9380}. The +algorithm yields a point which is inside the prime order subgroup of E. \hypertarget{vrf-preoutput-and-output}{% \subsubsection{VRF Preoutput and Output}\label{vrf-preoutput-and-output}} -\textbf{Definition}: \emph{VRF pre-output} is defined to be a point in -\(E\) in serialized affine representation. +\textbf{Definition}: \emph{VRF pre-output} is generated using VRF input +point as: -\textbf{Definition}: \emph{VRF InOut} is defined as a pair as follows: -\[(VRF Input, VRF Preoutput)\] \textbf{Definition}: \emph{VRF output} is -generated using VRF preoutput: \[ t \leftarrow Transcript(Domain) \] -\[ append(t, "VrfOutput") \] \[ append(t, cofactor * VRFpreout) \] -\[ VRFoutput \leftarrow t.challenge("") \] +\[ PreOutput \leftarrow sk \cdot VrfInput \] -\hypertarget{vrf-key}{% -\subsubsection{VRF Key}\label{vrf-key}} - -\hypertarget{public-key}{% -\paragraph{\texorpdfstring{Public key\\ -}{Public key }}\label{public-key}} - -\hfill\break -A Public key of a VRF is a point on an Elliptic Curve \(E\).\\ -Public key is represented in Affine form and is serialized using Arkwork -compressed serialized format. +\textbf{Definition}: \emph{VRF output} is generated using \emph{VRF +pre-output} point as: +\[ VrfOutput \leftarrow Hash("vrfoutput", Encode(PreOutput)) \] \hypertarget{ietf-vrf}{% \subsection{IETF VRF}\label{ietf-vrf}} -Refer to \href{https://www.rfc-editor.org/rfc/rfc9381}{RFC-9381} for the -details. +Definition of a VRF based on the IETF +\href{https://www.rfc-editor.org/rfc/rfc9381}{RFC-9381}. + +All the details specified by the RFC applies with the additional +capability to add additional data (\texttt{ad}) as per definition of +EC-VRF we've given. In particular the step 5 of section 5.4.3 is defined +as: + +\begin{verbatim} +str = str || ad || challenge_generation_domain_separator_back +\end{verbatim} \hypertarget{bandersnatch-cipher-suite-configuration}{% \subsubsection{Bandersnatch Cipher Suite @@ -203,11 +197,13 @@ \subsubsection{Bandersnatch Cipher Suite \href{https://www.rfc-editor.org/rfc/rfc6234}{RFC6234}, with hLen = 64. \item - The ECVRF\_encode\_to\_curve function is as specified in Section - 5.4.1.2, with \texttt{h2c\_suite\_ID\_string} = - \texttt{"BANDERSNATCH\_XMD:BLAKE2b\_ELL2\_RO\_"}. The suite is defined - in Section 8.5 of - \href{https://datatracker.ietf.org/doc/rfc9380/}{RFC9380}. + The \texttt{ECVRF\_encode\_to\_curve} function (\emph{Elligator2}) is + as specified in Section 5.4.1.2, with \texttt{h2c\_suite\_ID\_string} + = \texttt{"BANDERSNATCH\_XMD:SHA-512\_ELL2\_RO\_"}. The suite must be + interpreted as defined by Section 8.5 of + \href{https://datatracker.ietf.org/doc/rfc9380/}{RFC9380} and using + the domain separation tag + \texttt{DST\ =\ "ECVRF\_"\ \textbar{}\textbar{}\ h2c\_suite\_ID\_string\ \textbar{}\textbar{}\ suite\_string}. \end{itemize} \hypertarget{pedersen-vrf}{% @@ -313,49 +309,4 @@ \subsubsection{PedersenVRF.Verify}\label{pedersenvrf.verify}} \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{vrf-input-1}{% -\subsection{VRF input}\label{vrf-input-1}} - -Procedure to map arbitrary user input to a point follows the -\texttt{hash\_to\_curve} procedure described by RFC9380. - -\begin{verbatim} -Suite_ID: "bandersnatch_XMD:SHA-512_ELL2_RO_" -\end{verbatim} - -See \href{TODO}{ArkTranscript} for details. - -\hypertarget{from-transcript-to-point}{% -\subsubsection{From transcript to -point}\label{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. - -\hypertarget{transcript}{% -\subsection{Transcript}\label{transcript}} - -A Shake-128 based transcript construction which implements the -Fiat-Shamir transform procedure. - -We do basic domain separation using postfix writes of the lengths of -written data (as opposed to the prefix writes by -\href{https://merlin.cool}{Merlin} \texttt{TupleHash} from -\href{https://csrc.nist.gov/pubs/sp/800/185/final}{SP 800-185}). - -\begin{verbatim} -H(item_1, item_2, ..., item_n) -\end{verbatim} - -Represents the application of shake-128 to the concatenation of the -serialization of each item followed by the serialization of the length -of each objects, as a 32-bit unsigned integer. - -\begin{verbatim} -bytes = encode(item_1) || encode(length(item_1)) || .. || encode(item_n) || encode(length(item_n)) -Shake128(bytes) -\end{verbatim} - -The length of each item should be less than 2\^{}31. - \end{document} diff --git a/specification_template.md b/specification_template.md index 4f4af1f..83c20c1 100644 --- a/specification_template.md +++ b/specification_template.md @@ -1,16 +1,18 @@ # Bandersnatch VRFs -## VRF +## Introduction {sections.vrf} -### VRF Key +## IETF VRF -{sections.vrf-keys} +Definition of a VRF based on the IETF [RFC-9381](https://www.rfc-editor.org/rfc/rfc9381). -## IETF VRF +All the details specified by the RFC applies with the additional capability to add additional +data (`ad`) as per definition of EC-VRF we've given. In particular the step 5 of section +5.4.3 is defined as: -Refer to [RFC-9381](https://www.rfc-editor.org/rfc/rfc9381) for the details. + str = str || ad || challenge_generation_domain_separator_back ### Bandersnatch Cipher Suite Configuration @@ -57,9 +59,10 @@ Configuration follows the RFC-9381 suite specification guidelines. * The hash function Hash is SHA-512 as specified in [RFC6234](https://www.rfc-editor.org/rfc/rfc6234), with hLen = 64. -* The ECVRF_encode_to_curve function is as specified in - Section 5.4.1.2, with `h2c_suite_ID_string` = `"BANDERSNATCH_XMD:BLAKE2b_ELL2_RO_"`. - The suite is defined in Section 8.5 of [RFC9380](https://datatracker.ietf.org/doc/rfc9380/). +* The `ECVRF_encode_to_curve` function (*Elligator2*) is as specified in + Section 5.4.1.2, with `h2c_suite_ID_string` = `"BANDERSNATCH_XMD:SHA-512_ELL2_RO_"`. + The suite must be interpreted as defined by Section 8.5 of [RFC9380](https://datatracker.ietf.org/doc/rfc9380/) + and using the domain separation tag `DST = "ECVRF_" || h2c_suite_ID_string || suite_string`. ## Pedersen VRF @@ -68,36 +71,3 @@ public key by a Pedersen commitment to the secret key, which makes the Pedersen VRF useful in anonymized ring VRFs, or perhaps group VRFs. {sections.pedersen-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 -transform procedure. - -We do basic domain separation using postfix writes of the lengths of written -data (as opposed to the prefix writes by [Merlin](https://merlin.cool) -`TupleHash` from [SP 800-185](https://csrc.nist.gov/pubs/sp/800/185/final)). - - H(item_1, item_2, ..., item_n) - -Represents the application of shake-128 to the concatenation of the serialization of each item -followed by the serialization of the length of each objects, as a 32-bit unsigned integer. - - bytes = encode(item_1) || encode(length(item_1)) || .. || encode(item_n) || encode(length(item_n)) - Shake128(bytes) - -The length of each item should be less than 2^31.