-
Notifications
You must be signed in to change notification settings - Fork 5
/
secret_key.go
84 lines (74 loc) · 2.44 KB
/
secret_key.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
//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled
package blst
import (
"crypto/subtle"
"fmt"
blst "github.com/supranational/blst/bindings/go"
"github.com/theQRL/qrysm/v4/config/params"
"github.com/theQRL/qrysm/v4/crypto/bls/common"
"github.com/theQRL/qrysm/v4/crypto/rand"
)
// bls12SecretKey used in the BLS signature scheme.
type bls12SecretKey struct {
p *blst.SecretKey
}
// RandKey creates a new private key using a random method provided as an io.Reader.
func RandKey() (common.SecretKey, error) {
// Generate 32 bytes of randomness
var ikm [32]byte
_, err := rand.NewGenerator().Read(ikm[:])
if err != nil {
return nil, err
}
// Defensive check, that we have not generated a secret key,
secKey := &bls12SecretKey{blst.KeyGen(ikm[:])}
if IsZero(secKey.Marshal()) {
return nil, common.ErrZeroKey
}
return secKey, nil
}
// SecretKeyFromBytes creates a BLS private key from a BigEndian byte slice.
func SecretKeyFromBytes(privKey []byte) (common.SecretKey, error) {
if len(privKey) != params.BeaconConfig().BLSSecretKeyLength {
return nil, fmt.Errorf("secret key must be %d bytes", params.BeaconConfig().BLSSecretKeyLength)
}
secKey := new(blst.SecretKey).Deserialize(privKey)
if secKey == nil {
return nil, common.ErrSecretUnmarshal
}
wrappedKey := &bls12SecretKey{p: secKey}
if IsZero(privKey) {
return nil, common.ErrZeroKey
}
return wrappedKey, nil
}
// PublicKey obtains the public key corresponding to the BLS secret key.
func (s *bls12SecretKey) PublicKey() common.PublicKey {
return &PublicKey{p: new(blstPublicKey).From(s.p)}
}
// IsZero checks if the secret key is a zero key.
func IsZero(sKey []byte) bool {
b := byte(0)
for _, s := range sKey {
b |= s
}
return subtle.ConstantTimeByteEq(b, 0) == 1
}
// Sign a message using a secret key - in a beacon/validator client.
//
// In IETF draft BLS specification:
// Sign(SK, message) -> signature: a signing algorithm that generates
//
// a deterministic signature given a secret key SK and a message.
//
// In Ethereum proof of stake specification:
// def Sign(SK: int, message: Bytes) -> BLSSignature
func (s *bls12SecretKey) Sign(msg []byte) common.Signature {
signature := new(blstSignature).Sign(s.p, msg, dst)
return &Signature{s: signature}
}
// Marshal a secret key into a LittleEndian byte slice.
func (s *bls12SecretKey) Marshal() []byte {
keyBytes := s.p.Serialize()
return keyBytes
}