github.com/platonnetwork/platon-go@v0.7.6/crypto/vrf/vrf_secp256k1.go (about)

     1  // Copyright 2017 The PlatON Authors
     2  // This file is part of the PlatON library.
     3  //
     4  // The PlatON library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The PlatON library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the PlatON library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // +build !nacl,!js,!nocgo
    18  
    19  package vrf
    20  
    21  import (
    22  	"bytes"
    23  	"crypto/sha256"
    24  	"errors"
    25  	"math/big"
    26  
    27  	"github.com/PlatONnetwork/PlatON-Go/crypto/rfc6979"
    28  	"github.com/PlatONnetwork/PlatON-Go/crypto/secp256k1"
    29  )
    30  
    31  const (
    32  	limit = 1000
    33  	N2    = 32 // ceil(log2(q) / 8)
    34  	N     = N2 / 2
    35  )
    36  
    37  var (
    38  	ErrMalformedInput = errors.New("ECVRF: malformed input")
    39  	ErrDecodeError    = errors.New("ECVRF: decode error")
    40  	ErrInternalError  = errors.New("ECVRF: internal error")
    41  	curve             = secp256k1.S256()
    42  	gx, gy            = G()
    43  )
    44  
    45  // assume <pk, sk> were generated by ed25519.GenerateKey()
    46  func eCVRF_prove(pk []byte, sk []byte, m []byte) (pi []byte, err error) {
    47  	hx, hy := ECVRF_hash_to_curve(m, pk)
    48  	r := ECP2OS(curve.ScalarMult(hx, hy, sk))
    49  	k, err := rfc6979.ECVRF_nonce_generation(sk, m)
    50  	if err != nil {
    51  		panic(err)
    52  	}
    53  	kp := ECP2OS(k.PublicKey.X, k.PublicKey.Y)
    54  
    55  	// ECVRF_hash_points(g, h, g^x, h^x, g^k, h^k)
    56  	c := ECVRF_hash_points(ECP2OS(gx, gy), ECP2OS(hx, hy), pk,
    57  		r, kp, ECP2OS(curve.ScalarMult(hx, hy, k.D.Bytes())))
    58  
    59  	// s = k - c*q mod q
    60  	var z big.Int
    61  	var xx = new(big.Int).SetBytes(sk)
    62  	s := z.Mod(z.Sub(k.D, z.Mul(c, xx)), curve.N)
    63  
    64  	// pi = gamma || I2OSP(c, N) || I2OSP(s, 2N)
    65  	var buf bytes.Buffer
    66  	buf.Write(r)            // 2N
    67  	buf.Write(I2OSP(c, N))  //BigEndian
    68  	buf.Write(I2OSP(s, N2)) //BigEndian
    69  	return buf.Bytes(), nil
    70  }
    71  
    72  func eCVRF_proof2hash(pi []byte) []byte {
    73  	return pi[1 : N2+1]
    74  }
    75  
    76  func eCVRF_verify(pk []byte, pi []byte, m []byte) (bool, error) {
    77  	gmx, gmy, c, s, err := ECVRF_decode_proof(pi)
    78  	if err != nil {
    79  		return false, err
    80  	}
    81  
    82  	// u = (g^x)^c * g^s = P^c * g^s
    83  	px, py := OS2ECP(pk)
    84  	if px == nil || py == nil {
    85  		return false, ErrMalformedInput
    86  	}
    87  
    88  	cc := c.Bytes()
    89  	ss := s.Bytes()
    90  
    91  	x1, y1 := curve.ScalarMult(px, py, cc)
    92  	x2, y2 := curve.ScalarBaseMult(ss)
    93  	ux, uy := curve.Add(x1, y1, x2, y2)
    94  
    95  	hx, hy := ECVRF_hash_to_curve(m, pk)
    96  
    97  	// v = gamma^c * h^s
    98  	//	fmt.Printf("c, r, s, h\n%s%s%s%s\n", hex.Dump(c[:]), hex.Dump(ECP2OS(r)), hex.Dump(s[:]), hex.Dump(ECP2OS(h)))
    99  	x3, y3 := curve.ScalarMult(gmx, gmy, cc)
   100  	x4, y4 := curve.ScalarMult(hx, hy, ss)
   101  	vx, vy := curve.Add(x3, y3, x4, y4)
   102  
   103  	// c' = ECVRF_hash_points(g, h, g^x, gamma, u, v)
   104  	c2 := ECVRF_hash_points(ECP2OS(gx, gy), ECP2OS(hx, hy), pk, ECP2OS(gmx, gmy), ECP2OS(ux, uy), ECP2OS(vx, vy))
   105  
   106  	return c2.Cmp(c) == 0, nil
   107  }
   108  
   109  func ECVRF_decode_proof(pi []byte) (x *big.Int, y *big.Int, c *big.Int, s *big.Int, err error) {
   110  	i := 0
   111  	x, y = OS2ECP(pi[0 : N2+1])
   112  	i += N2 + 1
   113  	if x == nil || y == nil {
   114  		return nil, nil, nil, nil, ErrDecodeError
   115  	}
   116  
   117  	c = OS2IP(pi[i : i+N])
   118  	i += N
   119  	s = OS2IP(pi[i : i+N2])
   120  	return
   121  }
   122  
   123  func ECVRF_hash_points(ps ...[]byte) *big.Int {
   124  	h := sha256.New()
   125  	//	fmt.Printf("hash_points:\n")
   126  	for _, p := range ps {
   127  		h.Write(p)
   128  		//		fmt.Printf("%s\n", hex.Dump(p))
   129  	}
   130  	v := h.Sum(nil)
   131  	return OS2IP(v[:N])
   132  }
   133  
   134  func ECVRF_hash_to_curve(m []byte, pk []byte) (x, y *big.Int) {
   135  	hash := sha256.New()
   136  	for i := int64(0); i < limit; i++ {
   137  		ctr := I2OSP(big.NewInt(i), 4)
   138  		hash.Write(m)
   139  		hash.Write(pk)
   140  		hash.Write(ctr)
   141  		h := hash.Sum(nil)
   142  		hash.Reset()
   143  		var buf [33]byte
   144  		buf[0] = 0x2
   145  		copy(buf[1:], h)
   146  		x, y = OS2ECP(buf[:])
   147  		if x != nil || y != nil {
   148  			return
   149  		}
   150  	}
   151  	panic("ECVRF_hash_to_curve: couldn't make a point on curve")
   152  }
   153  
   154  func OS2ECP(os []byte) (Bx, By *big.Int) {
   155  	return secp256k1.DecompressPubkey(os)
   156  }
   157  
   158  func ECP2OS(Bx, By *big.Int) []byte {
   159  	return secp256k1.CompressPubkey(Bx, By)
   160  }
   161  
   162  func I2OSP(b *big.Int, n int) []byte {
   163  	os := b.Bytes()
   164  	if n > len(os) {
   165  		var buf bytes.Buffer
   166  		buf.Write(make([]byte, n-len(os))) // prepend 0s
   167  		buf.Write(os)
   168  		return buf.Bytes()
   169  	} else {
   170  		return os[:n]
   171  	}
   172  }
   173  
   174  func OS2IP(os []byte) *big.Int {
   175  	return new(big.Int).SetBytes(os)
   176  }
   177  
   178  func G() (x, y *big.Int) {
   179  	var one = new(big.Int).SetInt64(1)
   180  	x, y = curve.ScalarBaseMult(one.Bytes()) // g = g^1
   181  	return
   182  }