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 }