github.com/prysmaticlabs/prysm@v1.4.4/shared/bls/blst/secret_key.go (about) 1 // +build linux,amd64 linux,arm64 darwin,amd64 windows,amd64 2 // +build !blst_disabled 3 4 package blst 5 6 import ( 7 "crypto/subtle" 8 "fmt" 9 10 "github.com/prysmaticlabs/prysm/shared/bls/common" 11 "github.com/prysmaticlabs/prysm/shared/featureconfig" 12 "github.com/prysmaticlabs/prysm/shared/params" 13 "github.com/prysmaticlabs/prysm/shared/rand" 14 blst "github.com/supranational/blst/bindings/go" 15 ) 16 17 // bls12SecretKey used in the BLS signature scheme. 18 type bls12SecretKey struct { 19 p *blst.SecretKey 20 } 21 22 // RandKey creates a new private key using a random method provided as an io.Reader. 23 func RandKey() (common.SecretKey, error) { 24 // Generate 32 bytes of randomness 25 var ikm [32]byte 26 _, err := rand.NewGenerator().Read(ikm[:]) 27 if err != nil { 28 return nil, err 29 } 30 // Defensive check, that we have not generated a secret key, 31 secKey := &bls12SecretKey{blst.KeyGen(ikm[:])} 32 if IsZero(secKey.Marshal()) { 33 return nil, common.ErrZeroKey 34 } 35 return secKey, nil 36 } 37 38 // SecretKeyFromBytes creates a BLS private key from a BigEndian byte slice. 39 func SecretKeyFromBytes(privKey []byte) (common.SecretKey, error) { 40 if len(privKey) != params.BeaconConfig().BLSSecretKeyLength { 41 return nil, fmt.Errorf("secret key must be %d bytes", params.BeaconConfig().BLSSecretKeyLength) 42 } 43 secKey := new(blst.SecretKey).Deserialize(privKey) 44 if secKey == nil { 45 return nil, common.ErrSecretUnmarshal 46 } 47 wrappedKey := &bls12SecretKey{p: secKey} 48 if IsZero(privKey) { 49 return nil, common.ErrZeroKey 50 } 51 return wrappedKey, nil 52 } 53 54 // PublicKey obtains the public key corresponding to the BLS secret key. 55 func (s *bls12SecretKey) PublicKey() common.PublicKey { 56 return &PublicKey{p: new(blstPublicKey).From(s.p)} 57 } 58 59 // IsZero checks if the secret key is a zero key. 60 func IsZero(sKey []byte) bool { 61 b := byte(0) 62 for _, s := range sKey { 63 b |= s 64 } 65 return subtle.ConstantTimeByteEq(b, 0) == 1 66 } 67 68 // Sign a message using a secret key - in a beacon/validator client. 69 // 70 // In IETF draft BLS specification: 71 // Sign(SK, message) -> signature: a signing algorithm that generates 72 // a deterministic signature given a secret key SK and a message. 73 // 74 // In Ethereum proof of stake specification: 75 // def Sign(SK: int, message: Bytes) -> BLSSignature 76 func (s *bls12SecretKey) Sign(msg []byte) common.Signature { 77 if featureconfig.Get().SkipBLSVerify { 78 return &Signature{} 79 } 80 signature := new(blstSignature).Sign(s.p, msg, dst) 81 return &Signature{s: signature} 82 } 83 84 // Marshal a secret key into a LittleEndian byte slice. 85 func (s *bls12SecretKey) Marshal() []byte { 86 keyBytes := s.p.Serialize() 87 return keyBytes 88 }