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 }