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

     1  package ed25519
     2  
     3  import (
     4  	"crypto/ed25519"
     5  	"crypto/subtle"
     6  	"fmt"
     7  	"io"
     8  
     9  	"github.com/Finschia/ostracon/crypto"
    10  	"github.com/Finschia/ostracon/crypto/tmhash"
    11  	"github.com/hdevalence/ed25519consensus"
    12  
    13  	"github.com/Finschia/finschia-sdk/codec"
    14  	cryptotypes "github.com/Finschia/finschia-sdk/crypto/types"
    15  	"github.com/Finschia/finschia-sdk/types/errors"
    16  )
    17  
    18  //-------------------------------------
    19  
    20  const (
    21  	PrivKeyName = "tendermint/PrivKeyEd25519"
    22  	PubKeyName  = "tendermint/PubKeyEd25519"
    23  	// PubKeySize is is the size, in bytes, of public keys as used in this package.
    24  	PubKeySize = 32
    25  	// PrivKeySize is the size, in bytes, of private keys as used in this package.
    26  	PrivKeySize = 64
    27  	// Size of an Edwards25519 signature. Namely the size of a compressed
    28  	// Edwards25519 point, and a field element. Both of which are 32 bytes.
    29  	SignatureSize = 64
    30  	// SeedSize is the size, in bytes, of private key seeds. These are the
    31  	// private key representations used by RFC 8032.
    32  	SeedSize = 32
    33  
    34  	keyType = "ed25519"
    35  )
    36  
    37  var (
    38  	_ cryptotypes.PrivKey  = &PrivKey{}
    39  	_ codec.AminoMarshaler = &PrivKey{}
    40  )
    41  
    42  // Bytes returns the privkey byte format.
    43  func (privKey *PrivKey) Bytes() []byte {
    44  	return privKey.Key
    45  }
    46  
    47  // Sign produces a signature on the provided message.
    48  // This assumes the privkey is wellformed in the golang format.
    49  // The first 32 bytes should be random,
    50  // corresponding to the normal ed25519 private key.
    51  // The latter 32 bytes should be the compressed public key.
    52  // If these conditions aren't met, Sign will panic or produce an
    53  // incorrect signature.
    54  func (privKey *PrivKey) Sign(msg []byte) ([]byte, error) {
    55  	return ed25519.Sign(privKey.Key, msg), nil
    56  }
    57  
    58  // PubKey gets the corresponding public key from the private key.
    59  //
    60  // Panics if the private key is not initialized.
    61  func (privKey *PrivKey) PubKey() cryptotypes.PubKey {
    62  	// If the latter 32 bytes of the privkey are all zero, privkey is not
    63  	// initialized.
    64  	initialized := false
    65  	for _, v := range privKey.Key[32:] {
    66  		if v != 0 {
    67  			initialized = true
    68  			break
    69  		}
    70  	}
    71  
    72  	if !initialized {
    73  		panic("Expected ed25519 PrivKey to include concatenated pubkey bytes")
    74  	}
    75  
    76  	pubkeyBytes := make([]byte, PubKeySize)
    77  	copy(pubkeyBytes, privKey.Key[32:])
    78  	return &PubKey{Key: pubkeyBytes}
    79  }
    80  
    81  // Equals - you probably don't need to use this.
    82  // Runs in constant time based on length of the keys.
    83  func (privKey *PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
    84  	if privKey.Type() != other.Type() {
    85  		return false
    86  	}
    87  
    88  	return subtle.ConstantTimeCompare(privKey.Bytes(), other.Bytes()) == 1
    89  }
    90  
    91  func (privKey *PrivKey) Type() string {
    92  	return keyType
    93  }
    94  
    95  // MarshalAmino overrides Amino binary marshalling.
    96  func (privKey PrivKey) MarshalAmino() ([]byte, error) {
    97  	return privKey.Key, nil
    98  }
    99  
   100  // UnmarshalAmino overrides Amino binary marshalling.
   101  func (privKey *PrivKey) UnmarshalAmino(bz []byte) error {
   102  	if len(bz) != PrivKeySize {
   103  		return fmt.Errorf("invalid privkey size")
   104  	}
   105  	privKey.Key = bz
   106  
   107  	return nil
   108  }
   109  
   110  // MarshalAminoJSON overrides Amino JSON marshalling.
   111  func (privKey PrivKey) MarshalAminoJSON() ([]byte, error) {
   112  	// When we marshal to Amino JSON, we don't marshal the "key" field itself,
   113  	// just its contents (i.e. the key bytes).
   114  	return privKey.MarshalAmino()
   115  }
   116  
   117  // UnmarshalAminoJSON overrides Amino JSON marshalling.
   118  func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error {
   119  	return privKey.UnmarshalAmino(bz)
   120  }
   121  
   122  // GenPrivKey generates a new ed25519 private key. These ed25519 keys must not
   123  // be used in SDK apps except in a tendermint validator context.
   124  // It uses OS randomness in conjunction with the current global random seed
   125  // in tendermint/libs/common to generate the private key.
   126  func GenPrivKey() *PrivKey {
   127  	return genPrivKey(crypto.CReader())
   128  }
   129  
   130  // genPrivKey generates a new ed25519 private key using the provided reader.
   131  func genPrivKey(rand io.Reader) *PrivKey {
   132  	seed := make([]byte, SeedSize)
   133  
   134  	_, err := io.ReadFull(rand, seed)
   135  	if err != nil {
   136  		panic(err)
   137  	}
   138  
   139  	return &PrivKey{Key: ed25519.NewKeyFromSeed(seed)}
   140  }
   141  
   142  // GenPrivKeyFromSecret hashes the secret with SHA2, and uses
   143  // that 32 byte output to create the private key.
   144  // NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context.
   145  // NOTE: secret should be the output of a KDF like bcrypt,
   146  // if it's derived from user input.
   147  func GenPrivKeyFromSecret(secret []byte) *PrivKey {
   148  	seed := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes.
   149  
   150  	return &PrivKey{Key: ed25519.NewKeyFromSeed(seed)}
   151  }
   152  
   153  //-------------------------------------
   154  
   155  var (
   156  	_ cryptotypes.PubKey   = &PubKey{}
   157  	_ codec.AminoMarshaler = &PubKey{}
   158  )
   159  
   160  // Address is the SHA256-20 of the raw pubkey bytes.
   161  // It doesn't implement ADR-28 addresses and it must not be used
   162  // in SDK except in a tendermint validator context.
   163  func (pubKey *PubKey) Address() crypto.Address {
   164  	if len(pubKey.Key) != PubKeySize {
   165  		panic("pubkey is incorrect size")
   166  	}
   167  	// For ADR-28 compatible address we would need to
   168  	// return address.Hash(proto.MessageName(pubKey), pubKey.Key)
   169  	return crypto.Address(tmhash.SumTruncated(pubKey.Key))
   170  }
   171  
   172  // Bytes returns the PubKey byte format.
   173  func (pubKey *PubKey) Bytes() []byte {
   174  	return pubKey.Key
   175  }
   176  
   177  func (pubKey *PubKey) VerifySignature(msg []byte, sig []byte) bool {
   178  	// make sure we use the same algorithm to sign
   179  	if len(sig) != SignatureSize {
   180  		return false
   181  	}
   182  
   183  	// uses https://github.com/hdevalence/ed25519consensus.Verify to comply with zip215 verification rules
   184  	return ed25519consensus.Verify(pubKey.Key, msg, sig)
   185  }
   186  
   187  // String returns Hex representation of a pubkey with it's type
   188  func (pubKey *PubKey) String() string {
   189  	return fmt.Sprintf("PubKeyEd25519{%X}", pubKey.Key)
   190  }
   191  
   192  func (pubKey *PubKey) Type() string {
   193  	return keyType
   194  }
   195  
   196  func (pubKey *PubKey) Equals(other cryptotypes.PubKey) bool {
   197  	if pubKey.Type() != other.Type() {
   198  		return false
   199  	}
   200  
   201  	return subtle.ConstantTimeCompare(pubKey.Bytes(), other.Bytes()) == 1
   202  }
   203  
   204  // MarshalAmino overrides Amino binary marshalling.
   205  func (pubKey PubKey) MarshalAmino() ([]byte, error) {
   206  	return pubKey.Key, nil
   207  }
   208  
   209  // UnmarshalAmino overrides Amino binary marshalling.
   210  func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
   211  	if len(bz) != PubKeySize {
   212  		return errors.Wrap(errors.ErrInvalidPubKey, "invalid pubkey size")
   213  	}
   214  	pubKey.Key = bz
   215  
   216  	return nil
   217  }
   218  
   219  // MarshalAminoJSON overrides Amino JSON marshalling.
   220  func (pubKey PubKey) MarshalAminoJSON() ([]byte, error) {
   221  	// When we marshal to Amino JSON, we don't marshal the "key" field itself,
   222  	// just its contents (i.e. the key bytes).
   223  	return pubKey.MarshalAmino()
   224  }
   225  
   226  // UnmarshalAminoJSON overrides Amino JSON marshalling.
   227  func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error {
   228  	return pubKey.UnmarshalAmino(bz)
   229  }