github.com/Evanesco-Labs/go-evanesco@v1.0.1/zkpminer/vrf/vrf.go (about)

     1  package vrf
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/elliptic"
     6  	"crypto/hmac"
     7  	"crypto/rand"
     8  	"crypto/sha256"
     9  	"errors"
    10  	"github.com/Evanesco-Labs/go-evanesco/zkpminer/keypair"
    11  	"math/big"
    12  )
    13  
    14  var (
    15  	ErrInvalidVRF = errors.New("invalid VRF proof")
    16  )
    17  
    18  // Evaluate returns the verifiable unpredictable function evaluated at m
    19  func Evaluate(k *keypair.PrivateKey, m []byte) (index [32]byte, proof []byte) {
    20  	nilIndex := [32]byte{}
    21  	// Prover chooses r <-- [1,N-1]
    22  	r, _, _, err := elliptic.GenerateKey(keypair.Curve, rand.Reader)
    23  	if err != nil {
    24  		return nilIndex, nil
    25  	}
    26  	ri := new(big.Int).SetBytes(r)
    27  
    28  	// H = HashToCurve(m)
    29  	Hx, Hy := keypair.HashToCurve(m)
    30  	// VRF_k(m) = [k]H
    31  	sHx, sHy := keypair.Curve.ScalarMult(Hx, Hy, k.D.Bytes())
    32  	vrf := elliptic.Marshal(keypair.Curve, sHx, sHy) // 65 bytes.
    33  
    34  	// G is the base point
    35  	// s = HashToField(G, H, [k]G, VRF, [r]G, [r]H)
    36  	rGx, rGy := keypair.Curve.ScalarBaseMult(r)
    37  	rHx, rHy := keypair.Curve.ScalarMult(Hx, Hy, r)
    38  	var b bytes.Buffer
    39  	b.Write(elliptic.Marshal(keypair.Curve, keypair.Params.Gx, keypair.Params.Gy))
    40  	b.Write(elliptic.Marshal(keypair.Curve, Hx, Hy))
    41  	b.Write(elliptic.Marshal(keypair.Curve, k.PublicKey.X, k.PublicKey.Y))
    42  	b.Write(vrf)
    43  	b.Write(elliptic.Marshal(keypair.Curve, rGx, rGy))
    44  	b.Write(elliptic.Marshal(keypair.Curve, rHx, rHy))
    45  	s := keypair.HashToField(b.Bytes())
    46  
    47  	// t = r−s*k mod N
    48  	t := new(big.Int).Sub(ri, new(big.Int).Mul(s, k.D))
    49  	t.Mod(t, keypair.Params.N)
    50  
    51  	// Index = H(vrf)
    52  	index = sha256.Sum256(vrf)
    53  
    54  	// Write s, t, and vrf to a proof blob. Also write leading zeros before s and t
    55  	// if needed.
    56  	var buf bytes.Buffer
    57  	buf.Write(make([]byte, 32-len(s.Bytes())))
    58  	buf.Write(s.Bytes())
    59  	buf.Write(make([]byte, 32-len(t.Bytes())))
    60  	buf.Write(t.Bytes())
    61  	buf.Write(vrf)
    62  
    63  	p := buf.Bytes()
    64  
    65  	//self verify
    66  	hash, err := ProofToHash(k.Public(), m, p)
    67  	if err != nil {
    68  		return nilIndex, nil
    69  	}
    70  	if hash != index {
    71  		return nilIndex, nil
    72  	}
    73  
    74  	return index, p
    75  }
    76  
    77  // ProofToHash asserts that proof is correct for m and outputs index.
    78  func ProofToHash(pk *keypair.PublicKey, m, proof []byte) (index [32]byte, err error) {
    79  	nilIndex := [32]byte{}
    80  
    81  	if got, want := len(proof), 64+65; got != want {
    82  		return nilIndex, ErrInvalidVRF
    83  	}
    84  
    85  	s := proof[0:32]
    86  	t := proof[32:64]
    87  	vrf := proof[64 : 64+65]
    88  
    89  	uHx, uHy := elliptic.Unmarshal(keypair.Curve, vrf)
    90  	if uHx == nil {
    91  		return nilIndex, ErrInvalidVRF
    92  	}
    93  
    94  	tGx, tGy := keypair.Curve.ScalarBaseMult(t)
    95  	ksGx, ksGy := keypair.Curve.ScalarMult(pk.X, pk.Y, s)
    96  	tksGx, tksGy := keypair.Curve.Add(tGx, tGy, ksGx, ksGy)
    97  
    98  	Hx, Hy := keypair.HashToCurve(m)
    99  	tHx, tHy := keypair.Curve.ScalarMult(Hx, Hy, t)
   100  	sHx, sHy := keypair.Curve.ScalarMult(uHx, uHy, s)
   101  	tksHx, tksHy := keypair.Curve.Add(tHx, tHy, sHx, sHy)
   102  
   103  	var b bytes.Buffer
   104  	b.Write(elliptic.Marshal(keypair.Curve, keypair.Params.Gx, keypair.Params.Gy))
   105  	b.Write(elliptic.Marshal(keypair.Curve, Hx, Hy))
   106  	b.Write(elliptic.Marshal(keypair.Curve, pk.X, pk.Y))
   107  	b.Write(vrf)
   108  	b.Write(elliptic.Marshal(keypair.Curve, tksGx, tksGy))
   109  	b.Write(elliptic.Marshal(keypair.Curve, tksHx, tksHy))
   110  	h2 := keypair.HashToField(b.Bytes())
   111  
   112  	var buf bytes.Buffer
   113  	buf.Write(make([]byte, 32-len(h2.Bytes())))
   114  	buf.Write(h2.Bytes())
   115  
   116  	if !hmac.Equal(s, buf.Bytes()) {
   117  		return nilIndex, ErrInvalidVRF
   118  	}
   119  	return sha256.Sum256(vrf), nil
   120  }