/
bls_vrf.go
101 lines (80 loc) · 2.37 KB
/
bls_vrf.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package blsvrf
import (
"crypto"
"crypto/sha256"
"errors"
"github.com/PositionExchange/bls/ffi/go/bls"
"github.com/PositionExchange/posichain/crypto/vrf"
)
var (
// ErrInvalidVRF occurs when the VRF does not validate.
ErrInvalidVRF = errors.New("invalid VRF proof")
)
// PublicKey holds a public VRF key.
type PublicKey struct {
*bls.PublicKey
}
// PrivateKey holds a private VRF key.
type PrivateKey struct {
*bls.SecretKey
}
func init() {
bls.Init(bls.BLS12_381)
}
// Public returns the corresponding public key as bytes.
func (k *PrivateKey) Public() crypto.PublicKey {
return *k.SecretKey.GetPublicKey()
}
// Serialize serialize the public key into bytes
func (pk *PublicKey) Serialize() []byte {
return pk.Serialize()
}
// Deserialize de-serialize bytes into public key
func (pk *PublicKey) Deserialize(data []byte) {
pk.Deserialize(data)
}
// NewVRFVerifier creates a verifier object from a public key.
func NewVRFVerifier(pubkey *bls.PublicKey) vrf.PublicKey {
return &PublicKey{pubkey}
}
// NewVRFSigner creates a signer object from a private key.
func NewVRFSigner(seck *bls.SecretKey) vrf.PrivateKey {
return &PrivateKey{seck}
}
// Evaluate returns the verifiable unpredictable function evaluated using alpha
// verifiable unpredictable function using BLS
// reference: https://tools.ietf.org/html/draft-goldbe-vrf-01
// properties of VRF-BLS:
// 1) Full Uniqueness : satisfied, it is deterministic
// 2) Full Pseudorandomness : satisfied through sha256
// 3) Full Collison Resistance : satisfied through sha256
func (k *PrivateKey) Evaluate(alpha []byte) ([32]byte, []byte) {
//get the BLS signature of the message
//pi = VRF_prove(SK, alpha)
msgHash := sha256.Sum256(alpha)
pi := k.SignHash(msgHash[:])
if pi == nil {
return [32]byte{}, nil
}
//hash the signature and output as VRF beta
//beta = VRF_proof2hash(pi)
beta := sha256.Sum256(pi.Serialize())
return beta, pi.Serialize()
}
// ProofToHash asserts that proof is correct for input alpha and output VRF hash
func (pk *PublicKey) ProofToHash(alpha, pi []byte) ([32]byte, error) {
nilIndex := [32]byte{}
if len(pi) == 0 {
return nilIndex, ErrInvalidVRF
}
msgSig := bls.Sign{}
err := msgSig.Deserialize(pi)
if err != nil {
return nilIndex, err
}
msgHash := sha256.Sum256(alpha)
if !msgSig.VerifyHash(pk.PublicKey, msgHash[:]) {
return nilIndex, ErrInvalidVRF
}
return sha256.Sum256(pi), nil
}