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  }