github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/crypto/vrf/vrf.go (about)

     1  // Copyright 2016 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package vrf defines the interface to a verifiable random function.
    16  package vrf
    17  
    18  import (
    19  	"bytes"
    20  	"crypto"
    21  	"crypto/ecdsa"
    22  	"crypto/elliptic"
    23  	"crypto/hmac"
    24  	"crypto/rand"
    25  	"crypto/sha256"
    26  	"crypto/sha512"
    27  	"encoding/binary"
    28  	"errors"
    29  	"github.com/SmartMeshFoundation/Spectrum/crypto/secp256k1"
    30  	"github.com/google/keytransparency/core/crypto/vrf"
    31  	"math/big"
    32  )
    33  
    34  // A VRF is a pseudorandom function f_k from a secret key k, such that that
    35  // knowledge of k not only enables one to evaluate f_k at for any message m,
    36  // but also to provide an NP-proof that the value f_k(m) is indeed correct
    37  // without compromising the unpredictability of f_k for any m' != m.
    38  // http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=814584
    39  
    40  // PrivateKey supports evaluating the VRF function.
    41  type IPrivateKey interface {
    42  	// Evaluate returns the output of H(f_k(m)) and its proof.
    43  	Evaluate(m []byte) (index [32]byte, proof []byte)
    44  	// Public returns the corresponding public key.
    45  	Public() crypto.PublicKey
    46  }
    47  
    48  // PublicKey supports verifying output from the VRF function.
    49  type IPublicKey interface {
    50  	// ProofToHash verifies the NP-proof supplied by Proof and outputs Index.
    51  	ProofToHash(m, proof []byte) (index [32]byte, err error)
    52  }
    53  
    54  var (
    55  	curve  = secp256k1.S256()
    56  	params = curve.Params()
    57  
    58  	// ErrPointNotOnCurve occurs when a public key is not on the curve.
    59  	ErrPointNotOnCurve = errors.New("point is not on the S256 curve")
    60  	// ErrWrongKeyType occurs when a key is not an ECDSA key.
    61  	ErrWrongKeyType = errors.New("not an ECDSA key")
    62  	// ErrNoPEMFound occurs when attempting to parse a non PEM data structure.
    63  	ErrNoPEMFound = errors.New("no PEM block found")
    64  	// ErrInvalidVRF occurs when the VRF does not validate.
    65  	ErrInvalidVRF = errors.New("invalid VRF proof")
    66  )
    67  
    68  // Unmarshal a compressed point in the form specified in section 4.3.6 of ANSI X9.62.
    69  func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) {
    70  	byteLen := (curve.Params().BitSize + 7) >> 3
    71  	if (data[0] &^ 1) != 2 {
    72  		return // unrecognized point encoding
    73  	}
    74  	if len(data) != 1+byteLen {
    75  		return
    76  	}
    77  
    78  	// Based on Routine 2.2.4 in NIST Mathematical routines paper
    79  	params := curve.Params()
    80  	tx := new(big.Int).SetBytes(data[1 : 1+byteLen])
    81  	y2 := y2(params, tx)
    82  	sqrt := defaultSqrt
    83  	ty := sqrt(y2, params.P)
    84  	if ty == nil {
    85  		return // "y^2" is not a square: invalid point
    86  	}
    87  	var y2c big.Int
    88  	y2c.Mul(ty, ty).Mod(&y2c, params.P)
    89  	if y2c.Cmp(y2) != 0 {
    90  		return // sqrt(y2)^2 != y2: invalid point
    91  	}
    92  	if ty.Bit(0) != uint(data[0]&1) {
    93  		ty.Sub(params.P, ty)
    94  	}
    95  
    96  	x, y = tx, ty // valid point: return it
    97  	return
    98  }
    99  
   100  // Use the curve equation to calculate y² given x.
   101  // only applies to curves of the form y² = x³ - 3x + b.
   102  func y2(curve *elliptic.CurveParams, x *big.Int) *big.Int {
   103  
   104  	// y² = x³ - 3x + b
   105  	x3 := new(big.Int).Mul(x, x)
   106  	x3.Mul(x3, x)
   107  
   108  	//threeX := new(big.Int).Lsh(x, 1)
   109  	//threeX.Add(threeX, x)
   110  	//
   111  	//x3.Sub(x3, threeX)
   112  	x3.Add(x3, curve.B)
   113  	x3.Mod(x3, curve.P)
   114  	return x3
   115  }
   116  
   117  func defaultSqrt(x, p *big.Int) *big.Int {
   118  	var r big.Int
   119  	if nil == r.ModSqrt(x, p) {
   120  		return nil // x is not a square
   121  	}
   122  	return &r
   123  }
   124  
   125  // PublicKey holds a public VRF key.
   126  type PublicKey struct {
   127  	*ecdsa.PublicKey
   128  }
   129  
   130  // PrivateKey holds a private VRF key.
   131  type PrivateKey struct {
   132  	*ecdsa.PrivateKey
   133  }
   134  
   135  // GenerateKey generates a fresh keypair for this VRF
   136  func GenerateKey() (IPrivateKey, IPublicKey) {
   137  	key, err := ecdsa.GenerateKey(curve, rand.Reader)
   138  	if err != nil {
   139  		return nil, nil
   140  	}
   141  
   142  	return &PrivateKey{PrivateKey: key}, &PublicKey{PublicKey: &key.PublicKey}
   143  }
   144  
   145  // H1 hashes m to a curve point
   146  func H1(m []byte) (x, y *big.Int) {
   147  	h := sha512.New()
   148  	var i uint32
   149  	byteLen := (params.BitSize + 7) >> 3
   150  	for x == nil && i < 100 {
   151  		// TODO: Use a NIST specified DRBG.
   152  		h.Reset()
   153  		binary.Write(h, binary.BigEndian, i)
   154  		h.Write(m)
   155  		r := []byte{2} // Set point encoding to "compressed", y=0.
   156  		r = h.Sum(r)
   157  		x, y = Unmarshal(curve, r[:byteLen+1])
   158  		i++
   159  	}
   160  	return
   161  }
   162  
   163  var one = big.NewInt(1)
   164  
   165  // H2 hashes to an integer [1,N-1]
   166  func H2(m []byte) *big.Int {
   167  	// NIST SP 800-90A § A.5.1: Simple discard method.
   168  	byteLen := (params.BitSize + 7) >> 3
   169  	h := sha512.New()
   170  	for i := uint32(0); ; i++ {
   171  		// TODO: Use a NIST specified DRBG.
   172  		h.Reset()
   173  		binary.Write(h, binary.BigEndian, i)
   174  		h.Write(m)
   175  		b := h.Sum(nil)
   176  		k := new(big.Int).SetBytes(b[:byteLen])
   177  		if k.Cmp(new(big.Int).Sub(params.N, one)) == -1 {
   178  			return k.Add(k, one)
   179  		}
   180  	}
   181  }
   182  
   183  // Evaluate returns the verifiable unpredictable function evaluated at m
   184  func (k PrivateKey) Evaluate(m []byte) (index [32]byte, proof []byte) {
   185  	nilIndex := [32]byte{}
   186  	// Prover chooses r <-- [1,N-1]
   187  	r, _, _, err := elliptic.GenerateKey(curve, rand.Reader)
   188  	if err != nil {
   189  		return nilIndex, nil
   190  	}
   191  	ri := new(big.Int).SetBytes(r)
   192  
   193  	// H = H1(m)
   194  	Hx, Hy := H1(m)
   195  	if !curve.IsOnCurve(Hx, Hy) {
   196  		panic("not on curve")
   197  	}
   198  	// VRF_k(m) = [k]H
   199  	sHx, sHy := curve.ScalarMult(Hx, Hy, k.D.Bytes())
   200  	if !curve.IsOnCurve(sHx, sHy) {
   201  		panic("not on curve2")
   202  	}
   203  	vrf := elliptic.Marshal(curve, sHx, sHy) // 65 bytes.
   204  	uHx, _ := elliptic.Unmarshal(curve, vrf)
   205  	if uHx == nil {
   206  		panic("333")
   207  	}
   208  	// G is the base point
   209  	// s = H2(G, H, [k]G, VRF, [r]G, [r]H)
   210  	rGx, rGy := curve.ScalarBaseMult(r)
   211  	rHx, rHy := curve.ScalarMult(Hx, Hy, r)
   212  	var b bytes.Buffer
   213  	b.Write(elliptic.Marshal(curve, params.Gx, params.Gy))
   214  	b.Write(elliptic.Marshal(curve, Hx, Hy))
   215  	b.Write(elliptic.Marshal(curve, k.PublicKey.X, k.PublicKey.Y))
   216  	b.Write(vrf)
   217  	b.Write(elliptic.Marshal(curve, rGx, rGy))
   218  	b.Write(elliptic.Marshal(curve, rHx, rHy))
   219  	s := H2(b.Bytes())
   220  
   221  	// t = r−s*k mod N
   222  	t := new(big.Int).Sub(ri, new(big.Int).Mul(s, k.D))
   223  	t.Mod(t, params.N)
   224  
   225  	// Index = H(vrf)
   226  	index = sha256.Sum256(vrf)
   227  
   228  	// Write s, t, and vrf to a proof blob. Also write leading zeros before s and t
   229  	// if needed.
   230  	var buf bytes.Buffer
   231  	buf.Write(make([]byte, 32-len(s.Bytes())))
   232  	buf.Write(s.Bytes())
   233  	buf.Write(make([]byte, 32-len(t.Bytes())))
   234  	buf.Write(t.Bytes())
   235  	buf.Write(vrf)
   236  
   237  	return index, buf.Bytes()
   238  }
   239  
   240  // ProofToHash asserts that proof is correct for m and outputs index.
   241  func (pk *PublicKey) ProofToHash(m, proof []byte) (index [32]byte, err error) {
   242  	nilIndex := [32]byte{}
   243  	// verifier checks that s == H2(m, [t]G + [s]([k]G), [t]H1(m) + [s]VRF_k(m))
   244  	if got, want := len(proof), 64+65; got != want {
   245  		return nilIndex, ErrInvalidVRF
   246  	}
   247  
   248  	// Parse proof into s, t, and vrf.
   249  	s := proof[0:32]
   250  	t := proof[32:64]
   251  	vrf := proof[64 : 64+65]
   252  
   253  	uHx, uHy := elliptic.Unmarshal(curve, vrf)
   254  	if uHx == nil {
   255  		return nilIndex, ErrInvalidVRF
   256  	}
   257  
   258  	// [t]G + [s]([k]G) = [t+ks]G
   259  	tGx, tGy := curve.ScalarBaseMult(t)
   260  	ksGx, ksGy := curve.ScalarMult(pk.X, pk.Y, s)
   261  	tksGx, tksGy := params.Add(tGx, tGy, ksGx, ksGy)
   262  
   263  	// H = H1(m)
   264  	// [t]H + [s]VRF = [t+ks]H
   265  	Hx, Hy := H1(m)
   266  	tHx, tHy := curve.ScalarMult(Hx, Hy, t)
   267  	sHx, sHy := curve.ScalarMult(uHx, uHy, s)
   268  	tksHx, tksHy := params.Add(tHx, tHy, sHx, sHy)
   269  
   270  	//   H2(G, H, [k]G, VRF, [t]G + [s]([k]G), [t]H + [s]VRF)
   271  	// = H2(G, H, [k]G, VRF, [t+ks]G, [t+ks]H)
   272  	// = H2(G, H, [k]G, VRF, [r]G, [r]H)
   273  	var b bytes.Buffer
   274  	b.Write(elliptic.Marshal(curve, params.Gx, params.Gy))
   275  	b.Write(elliptic.Marshal(curve, Hx, Hy))
   276  	b.Write(elliptic.Marshal(curve, pk.X, pk.Y))
   277  	b.Write(vrf)
   278  	b.Write(elliptic.Marshal(curve, tksGx, tksGy))
   279  	b.Write(elliptic.Marshal(curve, tksHx, tksHy))
   280  	h2 := H2(b.Bytes())
   281  
   282  	// Left pad h2 with zeros if needed. This will ensure that h2 is padded
   283  	// the same way s is.
   284  	var buf bytes.Buffer
   285  	buf.Write(make([]byte, 32-len(h2.Bytes())))
   286  	buf.Write(h2.Bytes())
   287  
   288  	if !hmac.Equal(s, buf.Bytes()) {
   289  		return nilIndex, ErrInvalidVRF
   290  	}
   291  	return sha256.Sum256(vrf), nil
   292  }
   293  
   294  // NewVRFSigner creates a signer object from a private key.
   295  func NewVRFSigner(key *ecdsa.PrivateKey) (vrf.PrivateKey, error) {
   296  	if *(key.Params()) != *curve.Params() {
   297  		return nil, ErrPointNotOnCurve
   298  	}
   299  	if !curve.IsOnCurve(key.X, key.Y) {
   300  		return nil, ErrPointNotOnCurve
   301  	}
   302  	return &PrivateKey{PrivateKey: key}, nil
   303  }
   304  
   305  // Public returns the corresponding public key as bytes.
   306  func (k PrivateKey) Public() crypto.PublicKey {
   307  	return &k.PublicKey
   308  }
   309  
   310  // NewVRFVerifier creates a verifier object from a public key.
   311  func NewVRFVerifier(pubkey *ecdsa.PublicKey) (vrf.PublicKey, error) {
   312  	if *(pubkey.Params()) != *curve.Params() {
   313  		return nil, ErrPointNotOnCurve
   314  	}
   315  	if !curve.IsOnCurve(pubkey.X, pubkey.Y) {
   316  		return nil, ErrPointNotOnCurve
   317  	}
   318  	return &PublicKey{PublicKey: pubkey}, nil
   319  }