github.com/igggame/nebulas-go@v2.1.0+incompatible/crypto/keystore/secp256k1/vrf/secp256k1VRF/secp256k1VRF.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 // Implements a verifiable random function using curve secp256k1. 16 17 package secp256k1VRF 18 19 // Discrete Log based VRF from Appendix A of CONIKS: 20 // http://www.jbonneau.com/doc/MBBFF15-coniks.pdf 21 // based on "Unique Ring Signatures, a Practical Construction" 22 // http://fc13.ifca.ai/proc/5-1.pdf 23 24 import ( 25 "bytes" 26 "crypto" 27 "crypto/ecdsa" 28 "crypto/hmac" 29 "crypto/rand" 30 "crypto/sha256" 31 "crypto/sha512" 32 "encoding/binary" 33 "errors" 34 "io" 35 "math/big" 36 37 "github.com/nebulasio/go-nebulas/crypto/keystore/secp256k1" 38 "github.com/nebulasio/go-nebulas/crypto/keystore/secp256k1/bitelliptic" 39 40 "github.com/nebulasio/go-nebulas/crypto/keystore/secp256k1/vrf" 41 ) 42 43 var ( 44 curve = bitelliptic.S256() 45 params = curve.Params() 46 47 // ErrPointNotOnCurve occurs when a public key is not on the curve. 48 ErrPointNotOnCurve = errors.New("point is not on the P256 curve") 49 // ErrWrongKeyType occurs when a key is not an ECDSA key. 50 ErrWrongKeyType = errors.New("not an ECDSA key") 51 // ErrNoPEMFound occurs when attempting to parse a non PEM data structure. 52 ErrNoPEMFound = errors.New("no PEM block found") 53 // ErrInvalidVRF occurs when the VRF does not validate. 54 ErrInvalidVRF = errors.New("invalid VRF proof") 55 // ErrEvaluateFailed fail 56 ErrEvaluateFailed = errors.New("failed to evaluate VRF") 57 ) 58 59 // PublicKey holds a public VRF key. 60 type PublicKey struct { 61 *ecdsa.PublicKey 62 } 63 64 // PrivateKey holds a private VRF key. 65 type PrivateKey struct { 66 *ecdsa.PrivateKey 67 } 68 69 // GenerateKey generates a fresh keypair for this VRF 70 func GenerateKey() (vrf.PrivateKey, vrf.PublicKey) { 71 key, err := ecdsa.GenerateKey(curve, rand.Reader) 72 if err != nil { 73 return nil, nil 74 } 75 76 return &PrivateKey{key}, &PublicKey{&key.PublicKey} 77 } 78 79 // H1 hashes m to a curve point 80 func H1(m []byte) (x, y *big.Int) { 81 h := sha512.New() 82 var i uint32 83 byteLen := (params.BitSize + 7) >> 3 84 for x == nil && i < 100 { 85 // TODO: Use a NIST specified DRBG. 86 h.Reset() 87 binary.Write(h, binary.BigEndian, i) 88 h.Write(m) 89 r := []byte{2} // Set point encoding to "compressed", y=0. 90 r = h.Sum(r) 91 x, y = Unmarshal(curve, r[:byteLen+1]) 92 i++ 93 } 94 return 95 } 96 97 var one = big.NewInt(1) 98 99 // H2 hashes to an integer [1,N-1] 100 func H2(m []byte) *big.Int { 101 // NIST SP 800-90A § A.5.1: Simple discard method. 102 byteLen := (params.BitSize + 7) >> 3 103 h := sha512.New() 104 for i := uint32(0); ; i++ { 105 // TODO: Use a NIST specified DRBG. 106 h.Reset() 107 binary.Write(h, binary.BigEndian, i) 108 h.Write(m) 109 b := h.Sum(nil) 110 k := new(big.Int).SetBytes(b[:byteLen]) 111 if k.Cmp(new(big.Int).Sub(params.N, one)) == -1 { 112 return k.Add(k, one) 113 } 114 } 115 } 116 117 // Evaluate returns the verifiable unpredictable function evaluated at m 118 func (k PrivateKey) Evaluate(m []byte) (index [32]byte, proof []byte) { 119 nilIndex := [32]byte{} 120 // Prover chooses r <-- [1,N-1] 121 r, _, _, err := generateKeyFromCurve(curve, rand.Reader) 122 if err != nil { 123 return nilIndex, nil 124 } 125 ri := new(big.Int).SetBytes(r) 126 127 // H = H1(m) 128 Hx, Hy := H1(m) 129 130 // VRF_k(m) = [k]H 131 sHx, sHy := curve.ScalarMult(Hx, Hy, k.D.Bytes()) 132 133 // vrf := elliptic.Marshal(curve, sHx, sHy) // 65 bytes. 134 vrf := curve.Marshal(sHx, sHy) // 65 bytes. 135 136 // G is the base point 137 // s = H2(G, H, [k]G, VRF, [r]G, [r]H) 138 rGx, rGy := curve.ScalarBaseMult(r) 139 rHx, rHy := curve.ScalarMult(Hx, Hy, r) 140 var b bytes.Buffer 141 b.Write(curve.Marshal(params.Gx, params.Gy)) 142 b.Write(curve.Marshal(Hx, Hy)) 143 b.Write(curve.Marshal(k.PublicKey.X, k.PublicKey.Y)) 144 b.Write(vrf) 145 b.Write(curve.Marshal(rGx, rGy)) 146 b.Write(curve.Marshal(rHx, rHy)) 147 s := H2(b.Bytes()) 148 149 // t = r−s*k mod N 150 t := new(big.Int).Sub(ri, new(big.Int).Mul(s, k.D)) 151 t.Mod(t, params.N) 152 153 // Index = H(vrf) 154 index = sha256.Sum256(vrf) 155 156 // Write s, t, and vrf to a proof blob. Also write leading zeros before s and t 157 // if needed. 158 var buf bytes.Buffer 159 buf.Write(make([]byte, 32-len(s.Bytes()))) 160 buf.Write(s.Bytes()) 161 buf.Write(make([]byte, 32-len(t.Bytes()))) 162 buf.Write(t.Bytes()) 163 buf.Write(vrf) 164 165 return index, buf.Bytes() 166 } 167 168 // ProofToHash asserts that proof is correct for m and outputs index. 169 func (pk *PublicKey) ProofToHash(m, proof []byte) (index [32]byte, err error) { 170 nilIndex := [32]byte{} 171 // verifier checks that s == H2(m, [t]G + [s]([k]G), [t]H1(m) + [s]VRF_k(m)) 172 if got, want := len(proof), 64+65; got != want { 173 return nilIndex, ErrInvalidVRF 174 } 175 176 // Parse proof into s, t, and vrf. 177 s := proof[0:32] 178 t := proof[32:64] 179 vrf := proof[64 : 64+65] 180 181 // uHx, uHy := elliptic.Unmarshal(curve, vrf) 182 uHx, uHy := curve.Unmarshal(vrf) //////??? 183 if uHx == nil { 184 return nilIndex, ErrInvalidVRF 185 } 186 187 // [t]G + [s]([k]G) = [t+ks]G 188 tGx, tGy := curve.ScalarBaseMult(t) 189 ksGx, ksGy := curve.ScalarMult(pk.X, pk.Y, s) 190 tksGx, tksGy := curve.Add(tGx, tGy, ksGx, ksGy) 191 192 // H = H1(m) 193 // [t]H + [s]VRF = [t+ks]H 194 Hx, Hy := H1(m) 195 tHx, tHy := curve.ScalarMult(Hx, Hy, t) 196 sHx, sHy := curve.ScalarMult(uHx, uHy, s) 197 tksHx, tksHy := curve.Add(tHx, tHy, sHx, sHy) 198 199 // H2(G, H, [k]G, VRF, [t]G + [s]([k]G), [t]H + [s]VRF) 200 // = H2(G, H, [k]G, VRF, [t+ks]G, [t+ks]H) 201 // = H2(G, H, [k]G, VRF, [r]G, [r]H) 202 var b bytes.Buffer 203 b.Write(curve.Marshal(params.Gx, params.Gy)) 204 b.Write(curve.Marshal(Hx, Hy)) 205 b.Write(curve.Marshal(pk.X, pk.Y)) 206 b.Write(vrf) 207 b.Write(curve.Marshal(tksGx, tksGy)) 208 b.Write(curve.Marshal(tksHx, tksHy)) 209 h2 := H2(b.Bytes()) 210 211 // Left pad h2 with zeros if needed. This will ensure that h2 is padded 212 // the same way s is. 213 var buf bytes.Buffer 214 buf.Write(make([]byte, 32-len(h2.Bytes()))) 215 buf.Write(h2.Bytes()) 216 217 if !hmac.Equal(s, buf.Bytes()) { 218 return nilIndex, ErrInvalidVRF 219 } 220 return sha256.Sum256(vrf), nil 221 } 222 223 // NewFromWrappedKey creates a VRF signer object from an encrypted private key. 224 // The opaque private key must resolve to an `ecdsa.PrivateKey` in order to work. 225 // func NewFromWrappedKey(ctx context.Context, wrapped proto.Message) (vrf.PrivateKey, error) { 226 // // Unwrap. 227 // signer, err := keys.NewSigner(ctx, wrapped) 228 // if err != nil { 229 // return nil, err 230 // } 231 232 // switch key := signer.(type) { 233 // case *ecdsa.PrivateKey: 234 // return NewVRFSigner(key) 235 // default: 236 // return nil, fmt.Errorf("NewSigner().type: %T, want ecdsa.PrivateKey", key) 237 // } 238 // } 239 240 // NewVRFSigner creates a signer object from a private key. 241 func NewVRFSigner(key *ecdsa.PrivateKey) (vrf.PrivateKey, error) { 242 if *(key.Params()) != *curve.Params() { 243 return nil, ErrPointNotOnCurve 244 } 245 if !curve.IsOnCurve(key.X, key.Y) { 246 return nil, ErrPointNotOnCurve 247 } 248 return &PrivateKey{key}, nil 249 } 250 251 // Public returns the corresponding public key as bytes. 252 func (k PrivateKey) Public() crypto.PublicKey { 253 return &k.PublicKey 254 } 255 256 // NewVRFVerifier creates a verifier object from a public key. 257 func NewVRFVerifier(pubkey *ecdsa.PublicKey) (vrf.PublicKey, error) { 258 if *(pubkey.Params()) != *curve.Params() { 259 return nil, ErrPointNotOnCurve 260 } 261 if !curve.IsOnCurve(pubkey.X, pubkey.Y) { 262 return nil, ErrPointNotOnCurve 263 } 264 return &PublicKey{pubkey}, nil 265 } 266 267 // NewVRFSignerFromPEM creates a vrf private key from a PEM data structure. 268 // func NewVRFSignerFromPEM(b []byte) (vrf.PrivateKey, error) { 269 // p, _ := pem.Decode(b) 270 // if p == nil { 271 // return nil, ErrNoPEMFound 272 // } 273 // return NewVRFSignerFromRawKey(p.Bytes) 274 // } 275 276 // NewVRFSignerFromRawKey returns the private key from a raw private key bytes. 277 func NewVRFSignerFromRawKey(b []byte) (vrf.PrivateKey, error) { 278 k, err := secp256k1.ToECDSAPrivateKey(b) 279 if err != nil { 280 return nil, err 281 } 282 return NewVRFSigner(k) 283 } 284 285 // NewVRFVerifierFromPEM creates a vrf public key from a PEM data structure. 286 // func NewVRFVerifierFromPEM(b []byte) (vrf.PublicKey, error) { 287 // p, _ := pem.Decode(b) 288 // if p == nil { 289 // return nil, ErrNoPEMFound 290 // } 291 // return NewVRFVerifierFromRawKey(p.Bytes) 292 // } 293 294 // NewVRFVerifierFromRawKey returns the public key from a raw public key bytes. 295 func NewVRFVerifierFromRawKey(b []byte) (vrf.PublicKey, error) { 296 k, err := secp256k1.ToECDSAPublicKey(b) 297 if err != nil { 298 return nil, err 299 } 300 return NewVRFVerifier(k) 301 } 302 303 var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f} 304 305 func generateKeyFromCurve(curve *bitelliptic.BitCurve, rand io.Reader) (priv []byte, x, y *big.Int, err error) { 306 N := curve.Params().N 307 bitSize := N.BitLen() 308 byteLen := (bitSize + 7) >> 3 309 priv = make([]byte, byteLen) 310 311 for x == nil { 312 _, err = io.ReadFull(rand, priv) 313 if err != nil { 314 return 315 } 316 // We have to mask off any excess bits in the case that the size of the 317 // underlying field is not a whole number of bytes. 318 priv[0] &= mask[bitSize%8] 319 // This is because, in tests, rand will return all zeros and we don't 320 // want to get the point at infinity and loop forever. 321 priv[1] ^= 0x42 322 323 // If the scalar is out of range, sample another random number. 324 if new(big.Int).SetBytes(priv).Cmp(N) >= 0 { 325 continue 326 } 327 328 x, y = curve.ScalarBaseMult(priv) 329 } 330 return 331 }