github.com/turingchain2020/turingchain@v1.1.21/common/vrf/secp256k1/secp256k1.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Copyright 2016 Google Inc. All Rights Reserved.
     6  //
     7  // Licensed under the Apache License, Version 2.0 (the "License");
     8  // you may not use this file except in compliance with the License.
     9  // You may obtain a copy of the License at
    10  //
    11  //     http://www.apache.org/licenses/LICENSE-2.0
    12  //
    13  // Unless required by applicable law or agreed to in writing, software
    14  // distributed under the License is distributed on an "AS IS" BASIS,
    15  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  // See the License for the specific language governing permissions and
    17  // limitations under the License.
    18  
    19  // Package secp256k1 implements a verifiable random function using curve secp256k1.
    20  package secp256k1
    21  
    22  import (
    23  	"bytes"
    24  	"crypto"
    25  	"crypto/ecdsa"
    26  	"crypto/elliptic"
    27  	"crypto/hmac"
    28  	"crypto/rand"
    29  	"crypto/sha256"
    30  	"crypto/sha512"
    31  	"encoding/binary"
    32  	"errors"
    33  	"math/big"
    34  
    35  	vrfp "github.com/turingchain2020/turingchain/common/vrf"
    36  	"github.com/btcsuite/btcd/btcec"
    37  )
    38  
    39  var (
    40  	curve = btcec.S256()
    41  	// ErrInvalidVRF err
    42  	ErrInvalidVRF = errors.New("invalid VRF proof")
    43  )
    44  
    45  // PublicKey holds a public VRF key.
    46  type PublicKey struct {
    47  	*ecdsa.PublicKey
    48  }
    49  
    50  // PrivateKey holds a private VRF key.
    51  type PrivateKey struct {
    52  	*ecdsa.PrivateKey
    53  }
    54  
    55  // GenerateKey generates a fresh keypair for this VRF
    56  func GenerateKey() (vrfp.PrivateKey, vrfp.PublicKey) {
    57  	key, err := ecdsa.GenerateKey(curve, rand.Reader)
    58  	if err != nil {
    59  		return nil, nil
    60  	}
    61  
    62  	return &PrivateKey{PrivateKey: key}, &PublicKey{PublicKey: &key.PublicKey}
    63  }
    64  
    65  // H1 hashes m to a curve point
    66  func H1(m []byte) (x, y *big.Int) {
    67  	h := sha512.New()
    68  	var i uint32
    69  	byteLen := (curve.BitSize + 7) >> 3
    70  	for x == nil && i < 100 {
    71  		// TODO: Use a NIST specified DRBG.
    72  		h.Reset()
    73  		if err := binary.Write(h, binary.BigEndian, i); err != nil {
    74  			panic(err)
    75  		}
    76  		if _, err := h.Write(m); err != nil {
    77  			panic(err)
    78  		}
    79  		r := []byte{2} // Set point encoding to "compressed", y=0.
    80  		r = h.Sum(r)
    81  		x, y = Unmarshal(curve, r[:byteLen+1])
    82  		i++
    83  	}
    84  	return
    85  }
    86  
    87  var one = big.NewInt(1)
    88  
    89  // H2 hashes to an integer [1,N-1]
    90  func H2(m []byte) *big.Int {
    91  	// NIST SP 800-90A § A.5.1: Simple discard method.
    92  	byteLen := (curve.BitSize + 7) >> 3
    93  	h := sha512.New()
    94  	for i := uint32(0); ; i++ {
    95  		// TODO: Use a NIST specified DRBG.
    96  		h.Reset()
    97  		if err := binary.Write(h, binary.BigEndian, i); err != nil {
    98  			panic(err)
    99  		}
   100  		if _, err := h.Write(m); err != nil {
   101  			panic(err)
   102  		}
   103  		b := h.Sum(nil)
   104  		k := new(big.Int).SetBytes(b[:byteLen])
   105  		if k.Cmp(new(big.Int).Sub(curve.N, one)) == -1 {
   106  			return k.Add(k, one)
   107  		}
   108  	}
   109  }
   110  
   111  // Evaluate returns the verifiable unpredictable function evaluated at m
   112  func (k PrivateKey) Evaluate(m []byte) (index [32]byte, proof []byte) {
   113  	nilIndex := [32]byte{}
   114  	// Prover chooses r <-- [1,N-1]
   115  	r, _, _, err := elliptic.GenerateKey(curve, rand.Reader)
   116  	if err != nil {
   117  		return nilIndex, nil
   118  	}
   119  	ri := new(big.Int).SetBytes(r)
   120  
   121  	// H = H1(m)
   122  	Hx, Hy := H1(m)
   123  
   124  	// VRF_k(m) = [k]H
   125  	sHx, sHy := curve.ScalarMult(Hx, Hy, k.D.Bytes())
   126  	vrf := elliptic.Marshal(curve, sHx, sHy) // 65 bytes.
   127  
   128  	// G is the base point
   129  	// s = H2(G, H, [k]G, VRF, [r]G, [r]H)
   130  	rGx, rGy := curve.ScalarBaseMult(r)
   131  	rHx, rHy := curve.ScalarMult(Hx, Hy, r)
   132  	var b bytes.Buffer
   133  	if _, err := b.Write(elliptic.Marshal(curve, curve.Gx, curve.Gy)); err != nil {
   134  		panic(err)
   135  	}
   136  	if _, err := b.Write(elliptic.Marshal(curve, Hx, Hy)); err != nil {
   137  		panic(err)
   138  	}
   139  	if _, err := b.Write(elliptic.Marshal(curve, k.PublicKey.X, k.PublicKey.Y)); err != nil {
   140  		panic(err)
   141  	}
   142  	if _, err := b.Write(vrf); err != nil {
   143  		panic(err)
   144  	}
   145  	if _, err := b.Write(elliptic.Marshal(curve, rGx, rGy)); err != nil {
   146  		panic(err)
   147  	}
   148  	if _, err := b.Write(elliptic.Marshal(curve, rHx, rHy)); err != nil {
   149  		panic(err)
   150  	}
   151  	s := H2(b.Bytes())
   152  
   153  	// t = r−s*k mod N
   154  	t := new(big.Int).Sub(ri, new(big.Int).Mul(s, k.D))
   155  	t.Mod(t, curve.N)
   156  
   157  	// Index = H(vrf)
   158  	index = sha256.Sum256(vrf)
   159  
   160  	// Write s, t, and vrf to a proof blob. Also write leading zeros before s and t
   161  	// if needed.
   162  	var buf bytes.Buffer
   163  	if _, err := buf.Write(make([]byte, 32-len(s.Bytes()))); err != nil {
   164  		panic(err)
   165  	}
   166  	if _, err := buf.Write(s.Bytes()); err != nil {
   167  		panic(err)
   168  	}
   169  	if _, err := buf.Write(make([]byte, 32-len(t.Bytes()))); err != nil {
   170  		panic(err)
   171  	}
   172  	if _, err := buf.Write(t.Bytes()); err != nil {
   173  		panic(err)
   174  	}
   175  	if _, err := buf.Write(vrf); err != nil {
   176  		panic(err)
   177  	}
   178  
   179  	return index, buf.Bytes()
   180  }
   181  
   182  // ProofToHash asserts that proof is correct for m and outputs index.
   183  func (pk *PublicKey) ProofToHash(m, proof []byte) (index [32]byte, err error) {
   184  	nilIndex := [32]byte{}
   185  	// verifier checks that s == H2(m, [t]G + [s]([k]G), [t]H1(m) + [s]VRF_k(m))
   186  	if got, want := len(proof), 64+65; got != want {
   187  		return nilIndex, ErrInvalidVRF
   188  	}
   189  
   190  	// Parse proof into s, t, and vrf.
   191  	s := proof[0:32]
   192  	t := proof[32:64]
   193  	vrf := proof[64 : 64+65]
   194  
   195  	uHx, uHy := elliptic.Unmarshal(curve, vrf)
   196  	if uHx == nil {
   197  		return nilIndex, ErrInvalidVRF
   198  	}
   199  
   200  	// [t]G + [s]([k]G) = [t+ks]G
   201  	tGx, tGy := curve.ScalarBaseMult(t)
   202  	ksGx, ksGy := curve.ScalarMult(pk.X, pk.Y, s)
   203  	tksGx, tksGy := curve.Add(tGx, tGy, ksGx, ksGy)
   204  
   205  	// H = H1(m)
   206  	// [t]H + [s]VRF = [t+ks]H
   207  	Hx, Hy := H1(m)
   208  	tHx, tHy := curve.ScalarMult(Hx, Hy, t)
   209  	sHx, sHy := curve.ScalarMult(uHx, uHy, s)
   210  	tksHx, tksHy := curve.Add(tHx, tHy, sHx, sHy)
   211  
   212  	//   H2(G, H, [k]G, VRF, [t]G + [s]([k]G), [t]H + [s]VRF)
   213  	// = H2(G, H, [k]G, VRF, [t+ks]G, [t+ks]H)
   214  	// = H2(G, H, [k]G, VRF, [r]G, [r]H)
   215  	var b bytes.Buffer
   216  	if _, err := b.Write(elliptic.Marshal(curve, curve.Gx, curve.Gy)); err != nil {
   217  		panic(err)
   218  	}
   219  	if _, err := b.Write(elliptic.Marshal(curve, Hx, Hy)); err != nil {
   220  		panic(err)
   221  	}
   222  	if _, err := b.Write(elliptic.Marshal(curve, pk.X, pk.Y)); err != nil {
   223  		panic(err)
   224  	}
   225  	if _, err := b.Write(vrf); err != nil {
   226  		panic(err)
   227  	}
   228  	if _, err := b.Write(elliptic.Marshal(curve, tksGx, tksGy)); err != nil {
   229  		panic(err)
   230  	}
   231  	if _, err := b.Write(elliptic.Marshal(curve, tksHx, tksHy)); err != nil {
   232  		panic(err)
   233  	}
   234  	h2 := H2(b.Bytes())
   235  
   236  	// Left pad h2 with zeros if needed. This will ensure that h2 is padded
   237  	// the same way s is.
   238  	var buf bytes.Buffer
   239  	if _, err := buf.Write(make([]byte, 32-len(h2.Bytes()))); err != nil {
   240  		panic(err)
   241  	}
   242  	if _, err := buf.Write(h2.Bytes()); err != nil {
   243  		panic(err)
   244  	}
   245  
   246  	if !hmac.Equal(s, buf.Bytes()) {
   247  		return nilIndex, ErrInvalidVRF
   248  	}
   249  	return sha256.Sum256(vrf), nil
   250  }
   251  
   252  // Public returns the corresponding public key as bytes.
   253  func (k PrivateKey) Public() crypto.PublicKey {
   254  	return &k.PublicKey
   255  }