github.com/MetalBlockchain/metalgo@v1.11.9/utils/crypto/bls/secret.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package bls
     5  
     6  import (
     7  	"crypto/rand"
     8  	"errors"
     9  	"runtime"
    10  
    11  	blst "github.com/supranational/blst/bindings/go"
    12  )
    13  
    14  const SecretKeyLen = blst.BLST_SCALAR_BYTES
    15  
    16  var (
    17  	errFailedSecretKeyDeserialize = errors.New("couldn't deserialize secret key")
    18  
    19  	// The ciphersuite is more commonly known as G2ProofOfPossession.
    20  	// There are two digests to ensure that message space for normal
    21  	// signatures and the proof of possession are distinct.
    22  	ciphersuiteSignature         = []byte("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_")
    23  	ciphersuiteProofOfPossession = []byte("BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_")
    24  )
    25  
    26  type SecretKey = blst.SecretKey
    27  
    28  // NewSecretKey generates a new secret key from the local source of
    29  // cryptographically secure randomness.
    30  func NewSecretKey() (*SecretKey, error) {
    31  	var ikm [32]byte
    32  	_, err := rand.Read(ikm[:])
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	sk := blst.KeyGen(ikm[:])
    37  	ikm = [32]byte{} // zero out the ikm
    38  	return sk, nil
    39  }
    40  
    41  // SecretKeyToBytes returns the big-endian format of the secret key.
    42  func SecretKeyToBytes(sk *SecretKey) []byte {
    43  	return sk.Serialize()
    44  }
    45  
    46  // SecretKeyFromBytes parses the big-endian format of the secret key into a
    47  // secret key.
    48  func SecretKeyFromBytes(skBytes []byte) (*SecretKey, error) {
    49  	sk := new(SecretKey).Deserialize(skBytes)
    50  	if sk == nil {
    51  		return nil, errFailedSecretKeyDeserialize
    52  	}
    53  	runtime.SetFinalizer(sk, func(sk *SecretKey) {
    54  		sk.Zeroize()
    55  	})
    56  	return sk, nil
    57  }
    58  
    59  // PublicFromSecretKey returns the public key that corresponds to this secret
    60  // key.
    61  func PublicFromSecretKey(sk *SecretKey) *PublicKey {
    62  	return new(PublicKey).From(sk)
    63  }
    64  
    65  // Sign [msg] to authorize this message from this [sk].
    66  func Sign(sk *SecretKey, msg []byte) *Signature {
    67  	return new(Signature).Sign(sk, msg, ciphersuiteSignature)
    68  }
    69  
    70  // Sign [msg] to prove the ownership of this [sk].
    71  func SignProofOfPossession(sk *SecretKey, msg []byte) *Signature {
    72  	return new(Signature).Sign(sk, msg, ciphersuiteProofOfPossession)
    73  }