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 }