github.com/Finschia/finschia-sdk@v0.48.1/crypto/keys/secp256k1/secp256k1.go (about)

     1  package secp256k1
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/sha256"
     6  	"crypto/subtle"
     7  	"fmt"
     8  	"io"
     9  	"math/big"
    10  
    11  	secp256k1 "github.com/btcsuite/btcd/btcec"
    12  	"golang.org/x/crypto/ripemd160" //nolint: staticcheck // necessary for Bitcoin address format
    13  
    14  	"github.com/Finschia/ostracon/crypto"
    15  
    16  	"github.com/Finschia/finschia-sdk/codec"
    17  	cryptotypes "github.com/Finschia/finschia-sdk/crypto/types"
    18  	"github.com/Finschia/finschia-sdk/types/errors"
    19  )
    20  
    21  var (
    22  	_ cryptotypes.PrivKey  = &PrivKey{}
    23  	_ codec.AminoMarshaler = &PrivKey{}
    24  )
    25  
    26  const (
    27  	PrivKeySize = 32
    28  	keyType     = "secp256k1"
    29  	PrivKeyName = "tendermint/PrivKeySecp256k1"
    30  	PubKeyName  = "tendermint/PubKeySecp256k1"
    31  )
    32  
    33  // Bytes returns the byte representation of the Private Key.
    34  func (privKey *PrivKey) Bytes() []byte {
    35  	return privKey.Key
    36  }
    37  
    38  // PubKey performs the point-scalar multiplication from the privKey on the
    39  // generator point to get the pubkey.
    40  func (privKey *PrivKey) PubKey() cryptotypes.PubKey {
    41  	_, pubkeyObject := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey.Key)
    42  	pk := pubkeyObject.SerializeCompressed()
    43  	return &PubKey{Key: pk}
    44  }
    45  
    46  // Equals - you probably don't need to use this.
    47  // Runs in constant time based on length of the
    48  func (privKey *PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
    49  	return privKey.Type() == other.Type() && subtle.ConstantTimeCompare(privKey.Bytes(), other.Bytes()) == 1
    50  }
    51  
    52  func (privKey *PrivKey) Type() string {
    53  	return keyType
    54  }
    55  
    56  // MarshalAmino overrides Amino binary marshalling.
    57  func (privKey PrivKey) MarshalAmino() ([]byte, error) {
    58  	return privKey.Key, nil
    59  }
    60  
    61  // UnmarshalAmino overrides Amino binary marshalling.
    62  func (privKey *PrivKey) UnmarshalAmino(bz []byte) error {
    63  	if len(bz) != PrivKeySize {
    64  		return fmt.Errorf("invalid privkey size")
    65  	}
    66  	privKey.Key = bz
    67  
    68  	return nil
    69  }
    70  
    71  // MarshalAminoJSON overrides Amino JSON marshalling.
    72  func (privKey PrivKey) MarshalAminoJSON() ([]byte, error) {
    73  	// When we marshal to Amino JSON, we don't marshal the "key" field itself,
    74  	// just its contents (i.e. the key bytes).
    75  	return privKey.MarshalAmino()
    76  }
    77  
    78  // UnmarshalAminoJSON overrides Amino JSON marshalling.
    79  func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error {
    80  	return privKey.UnmarshalAmino(bz)
    81  }
    82  
    83  // GenPrivKey generates a new ECDSA private key on curve secp256k1 private key.
    84  // It uses OS randomness to generate the private key.
    85  func GenPrivKey() *PrivKey {
    86  	return &PrivKey{Key: genPrivKey(crypto.CReader())}
    87  }
    88  
    89  // genPrivKey generates a new secp256k1 private key using the provided reader.
    90  func genPrivKey(rand io.Reader) []byte {
    91  	var privKeyBytes [PrivKeySize]byte
    92  	d := new(big.Int)
    93  	for {
    94  		privKeyBytes = [PrivKeySize]byte{}
    95  		_, err := io.ReadFull(rand, privKeyBytes[:])
    96  		if err != nil {
    97  			panic(err)
    98  		}
    99  
   100  		d.SetBytes(privKeyBytes[:])
   101  		// break if we found a valid point (i.e. > 0 and < N == curverOrder)
   102  		isValidFieldElement := 0 < d.Sign() && d.Cmp(secp256k1.S256().N) < 0
   103  		if isValidFieldElement {
   104  			break
   105  		}
   106  	}
   107  
   108  	return privKeyBytes[:]
   109  }
   110  
   111  var one = new(big.Int).SetInt64(1)
   112  
   113  // GenPrivKeyFromSecret hashes the secret with SHA2, and uses
   114  // that 32 byte output to create the private key.
   115  //
   116  // It makes sure the private key is a valid field element by setting:
   117  //
   118  // c = sha256(secret)
   119  // k = (c mod (n − 1)) + 1, where n = curve order.
   120  //
   121  // NOTE: secret should be the output of a KDF like bcrypt,
   122  // if it's derived from user input.
   123  func GenPrivKeyFromSecret(secret []byte) *PrivKey {
   124  	secHash := sha256.Sum256(secret)
   125  	// to guarantee that we have a valid field element, we use the approach of:
   126  	// "Suite B Implementer’s Guide to FIPS 186-3", A.2.1
   127  	// https://apps.nsa.gov/iaarchive/library/ia-guidance/ia-solutions-for-classified/algorithm-guidance/suite-b-implementers-guide-to-fips-186-3-ecdsa.cfm
   128  	// see also https://github.com/golang/go/blob/0380c9ad38843d523d9c9804fe300cb7edd7cd3c/src/crypto/ecdsa/ecdsa.go#L89-L101
   129  	fe := new(big.Int).SetBytes(secHash[:])
   130  	n := new(big.Int).Sub(secp256k1.S256().N, one)
   131  	fe.Mod(fe, n)
   132  	fe.Add(fe, one)
   133  
   134  	feB := fe.Bytes()
   135  	privKey32 := make([]byte, PrivKeySize)
   136  	// copy feB over to fixed 32 byte privKey32 and pad (if necessary)
   137  	copy(privKey32[32-len(feB):32], feB)
   138  
   139  	return &PrivKey{Key: privKey32}
   140  }
   141  
   142  //-------------------------------------
   143  
   144  var (
   145  	_ cryptotypes.PubKey   = &PubKey{}
   146  	_ codec.AminoMarshaler = &PubKey{}
   147  )
   148  
   149  // PubKeySize is comprised of 32 bytes for one field element
   150  // (the x-coordinate), plus one byte for the parity of the y-coordinate.
   151  const PubKeySize = 33
   152  
   153  // Address returns a Bitcoin style addresses: RIPEMD160(SHA256(pubkey))
   154  func (pubKey *PubKey) Address() crypto.Address {
   155  	if len(pubKey.Key) != PubKeySize {
   156  		panic("length of pubkey is incorrect")
   157  	}
   158  
   159  	sha := sha256.Sum256(pubKey.Key)
   160  	hasherRIPEMD160 := ripemd160.New()
   161  	hasherRIPEMD160.Write(sha[:]) // does not error
   162  	return crypto.Address(hasherRIPEMD160.Sum(nil))
   163  }
   164  
   165  // Bytes returns the pubkey byte format.
   166  func (pubKey *PubKey) Bytes() []byte {
   167  	return pubKey.Key
   168  }
   169  
   170  func (pubKey *PubKey) String() string {
   171  	return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey.Key)
   172  }
   173  
   174  func (pubKey *PubKey) Type() string {
   175  	return keyType
   176  }
   177  
   178  func (pubKey *PubKey) Equals(other cryptotypes.PubKey) bool {
   179  	return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes())
   180  }
   181  
   182  // MarshalAmino overrides Amino binary marshalling.
   183  func (pubKey PubKey) MarshalAmino() ([]byte, error) {
   184  	return pubKey.Key, nil
   185  }
   186  
   187  // UnmarshalAmino overrides Amino binary marshalling.
   188  func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
   189  	if len(bz) != PubKeySize {
   190  		return errors.Wrap(errors.ErrInvalidPubKey, "invalid pubkey size")
   191  	}
   192  	pubKey.Key = bz
   193  
   194  	return nil
   195  }
   196  
   197  // MarshalAminoJSON overrides Amino JSON marshalling.
   198  func (pubKey PubKey) MarshalAminoJSON() ([]byte, error) {
   199  	// When we marshal to Amino JSON, we don't marshal the "key" field itself,
   200  	// just its contents (i.e. the key bytes).
   201  	return pubKey.MarshalAmino()
   202  }
   203  
   204  // UnmarshalAminoJSON overrides Amino JSON marshalling.
   205  func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error {
   206  	return pubKey.UnmarshalAmino(bz)
   207  }