github.com/vipernet-xyz/tm@v0.34.24/crypto/sr25519/privkey.go (about)

     1  package sr25519
     2  
     3  import (
     4  	"crypto/subtle"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/vipernet-xyz/tm/crypto"
     9  
    10  	schnorrkel "github.com/ChainSafe/go-schnorrkel"
    11  )
    12  
    13  // PrivKeySize is the number of bytes in an Sr25519 private key.
    14  const PrivKeySize = 32
    15  
    16  // PrivKeySr25519 implements crypto.PrivKey.
    17  type PrivKey []byte
    18  
    19  // Bytes returns the byte representation of the PrivKey.
    20  func (privKey PrivKey) Bytes() []byte {
    21  	return []byte(privKey)
    22  }
    23  
    24  // Sign produces a signature on the provided message.
    25  func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
    26  	var p [PrivKeySize]byte
    27  	copy(p[:], privKey)
    28  	miniSecretKey, err := schnorrkel.NewMiniSecretKeyFromRaw(p)
    29  	if err != nil {
    30  		return []byte{}, err
    31  	}
    32  	secretKey := miniSecretKey.ExpandEd25519()
    33  
    34  	signingContext := schnorrkel.NewSigningContext([]byte{}, msg)
    35  
    36  	sig, err := secretKey.Sign(signingContext)
    37  	if err != nil {
    38  		return []byte{}, err
    39  	}
    40  
    41  	sigBytes := sig.Encode()
    42  	return sigBytes[:], nil
    43  }
    44  
    45  // PubKey gets the corresponding public key from the private key.
    46  func (privKey PrivKey) PubKey() crypto.PubKey {
    47  	var p [PrivKeySize]byte
    48  	copy(p[:], privKey)
    49  	miniSecretKey, err := schnorrkel.NewMiniSecretKeyFromRaw(p)
    50  	if err != nil {
    51  		panic(fmt.Sprintf("Invalid private key: %v", err))
    52  	}
    53  	secretKey := miniSecretKey.ExpandEd25519()
    54  
    55  	pubkey, err := secretKey.Public()
    56  	if err != nil {
    57  		panic(fmt.Sprintf("Could not generate public key: %v", err))
    58  	}
    59  	key := pubkey.Encode()
    60  	return PubKey(key[:])
    61  }
    62  
    63  // Equals - you probably don't need to use this.
    64  // Runs in constant time based on length of the keys.
    65  func (privKey PrivKey) Equals(other crypto.PrivKey) bool {
    66  	if otherEd, ok := other.(PrivKey); ok {
    67  		return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1
    68  	}
    69  	return false
    70  }
    71  
    72  func (privKey PrivKey) Type() string {
    73  	return keyType
    74  }
    75  
    76  // GenPrivKey generates a new sr25519 private key.
    77  // It uses OS randomness in conjunction with the current global random seed
    78  // in tendermint/libs/common to generate the private key.
    79  func GenPrivKey() PrivKey {
    80  	return genPrivKey(crypto.CReader())
    81  }
    82  
    83  // genPrivKey generates a new sr25519 private key using the provided reader.
    84  func genPrivKey(rand io.Reader) PrivKey {
    85  	var seed [64]byte
    86  
    87  	out := make([]byte, 64)
    88  	_, err := io.ReadFull(rand, out)
    89  	if err != nil {
    90  		panic(err)
    91  	}
    92  
    93  	copy(seed[:], out)
    94  
    95  	key := schnorrkel.NewMiniSecretKey(seed).ExpandEd25519().Encode()
    96  	return key[:]
    97  }
    98  
    99  // GenPrivKeyFromSecret hashes the secret with SHA2, and uses
   100  // that 32 byte output to create the private key.
   101  // NOTE: secret should be the output of a KDF like bcrypt,
   102  // if it's derived from user input.
   103  func GenPrivKeyFromSecret(secret []byte) PrivKey {
   104  	seed := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes.
   105  	var bz [PrivKeySize]byte
   106  	copy(bz[:], seed)
   107  	privKey, _ := schnorrkel.NewMiniSecretKeyFromRaw(bz)
   108  	key := privKey.ExpandEd25519().Encode()
   109  	return key[:]
   110  }