github.com/amazechain/amc@v0.1.3/common/crypto/bls/blst/secret_key.go (about)

     1  //go:build (android || (linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled
     2  
     3  package blst
     4  
     5  import (
     6  	"crypto/subtle"
     7  	"fmt"
     8  
     9  	"github.com/amazechain/amc/common/crypto/bls/common"
    10  	"github.com/amazechain/amc/common/crypto/rand"
    11  
    12  	blst "github.com/supranational/blst/bindings/go"
    13  )
    14  
    15  const BLSSecretKeyLength = 32
    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  // SecretKeyFromRandom32Byte creates a new private key using random 32 bytes
    39  func SecretKeyFromRandom32Byte(ikm [32]byte) (common.SecretKey, error) {
    40  	// Defensive check, that we have not generated a secret key,
    41  	secKey := &bls12SecretKey{blst.KeyGen(ikm[:])}
    42  	if IsZero(secKey.Marshal()) {
    43  		return nil, common.ErrZeroKey
    44  	}
    45  	return secKey, nil
    46  }
    47  
    48  // SecretKeyFromBytes creates a BLS private key from a BigEndian byte slice.
    49  func SecretKeyFromBytes(privKey []byte) (common.SecretKey, error) {
    50  	if len(privKey) != BLSSecretKeyLength {
    51  		return nil, fmt.Errorf("secret key must be %d bytes", BLSSecretKeyLength)
    52  	}
    53  	secKey := new(blst.SecretKey).Deserialize(privKey)
    54  	if secKey == nil {
    55  		return nil, common.ErrSecretUnmarshal
    56  	}
    57  	wrappedKey := &bls12SecretKey{p: secKey}
    58  	if IsZero(privKey) {
    59  		return nil, common.ErrZeroKey
    60  	}
    61  	return wrappedKey, nil
    62  }
    63  
    64  // PublicKey obtains the public key corresponding to the BLS secret key.
    65  func (s *bls12SecretKey) PublicKey() common.PublicKey {
    66  	return &PublicKey{p: new(blstPublicKey).From(s.p)}
    67  }
    68  
    69  // IsZero checks if the secret key is a zero key.
    70  func IsZero(sKey []byte) bool {
    71  	b := byte(0)
    72  	for _, s := range sKey {
    73  		b |= s
    74  	}
    75  	return subtle.ConstantTimeByteEq(b, 0) == 1
    76  }
    77  
    78  // Sign a message using a secret key - in a beacon/validator client.
    79  //
    80  // In IETF draft BLS specification:
    81  // Sign(SK, message) -> signature: a signing algorithm that generates
    82  //
    83  //	a deterministic signature given a secret key SK and a message.
    84  //
    85  // In Ethereum proof of stake specification:
    86  // def Sign(SK: int, message: Bytes) -> BLSSignature
    87  func (s *bls12SecretKey) Sign(msg []byte) common.Signature {
    88  	signature := new(blstSignature).Sign(s.p, msg, dst)
    89  	return &Signature{s: signature}
    90  }
    91  
    92  // Marshal a secret key into a LittleEndian byte slice.
    93  func (s *bls12SecretKey) Marshal() []byte {
    94  	keyBytes := s.p.Serialize()
    95  	return keyBytes
    96  }