github.com/stafiprotocol/go-substrate-rpc-client@v1.4.7/sr25519/sr25519.go (about)

     1  package sr25519
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	sr25519 "github.com/ChainSafe/go-schnorrkel"
     8  	"github.com/gtank/merlin"
     9  	"github.com/stafiprotocol/go-substrate-rpc-client/subkey"
    10  )
    11  
    12  const (
    13  	miniSecretKeyLength = 32
    14  
    15  	secretKeyLength = 64
    16  
    17  	signatureLength = 64
    18  )
    19  
    20  type keyRing struct {
    21  	seed   []byte
    22  	secret *sr25519.SecretKey
    23  	pub    *sr25519.PublicKey
    24  }
    25  
    26  func (kr keyRing) Sign(msg []byte) (signature []byte, err error) {
    27  	sig, err := kr.secret.Sign(signingContext(msg))
    28  	if err != nil {
    29  		return signature, err
    30  	}
    31  
    32  	s := sig.Encode()
    33  	return s[:], nil
    34  }
    35  
    36  func (kr keyRing) Verify(msg []byte, signature []byte) bool {
    37  	var sigs [signatureLength]byte
    38  	copy(sigs[:], signature)
    39  	sig := new(sr25519.Signature)
    40  	if err := sig.Decode(sigs); err != nil {
    41  		return false
    42  	}
    43  	return kr.pub.Verify(sig, signingContext(msg))
    44  }
    45  
    46  func signingContext(msg []byte) *merlin.Transcript {
    47  	return sr25519.NewSigningContext([]byte("substrate"), msg)
    48  }
    49  
    50  // Public returns the public key in bytes
    51  func (kr keyRing) Public() []byte {
    52  	bytes := kr.pub.Encode()
    53  	return bytes[:]
    54  }
    55  
    56  func (kr keyRing) Seed() []byte {
    57  	return kr.seed
    58  }
    59  
    60  func (kr keyRing) AccountID() []byte {
    61  	return kr.Public()
    62  }
    63  
    64  func (kr keyRing) SS58Address(network uint16) string {
    65  	return subkey.SS58Encode(kr.AccountID(), network)
    66  }
    67  
    68  func deriveKeySoft(secret *sr25519.SecretKey, cc [32]byte) (*sr25519.SecretKey, error) {
    69  	t := merlin.NewTranscript("SchnorrRistrettoHDKD")
    70  	t.AppendMessage([]byte("sign-bytes"), nil)
    71  	ek, err := secret.DeriveKey(t, cc)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  	return ek.Secret()
    76  }
    77  
    78  func deriveKeyHard(secret *sr25519.SecretKey, cc [32]byte) (*sr25519.MiniSecretKey, error) {
    79  	t := merlin.NewTranscript("SchnorrRistrettoHDKD")
    80  	t.AppendMessage([]byte("sign-bytes"), nil)
    81  	t.AppendMessage([]byte("chain-code"), cc[:])
    82  	s := secret.Encode()
    83  	t.AppendMessage([]byte("secret-key"), s[:])
    84  	mskb := t.ExtractBytes([]byte("HDKD-hard"), miniSecretKeyLength)
    85  	msk := [miniSecretKeyLength]byte{}
    86  	copy(msk[:], mskb)
    87  	return sr25519.NewMiniSecretKeyFromRaw(msk)
    88  }
    89  
    90  type Scheme struct{}
    91  
    92  func (s Scheme) String() string {
    93  	return "Sr25519"
    94  }
    95  
    96  func (s Scheme) Generate() (subkey.KeyPair, error) {
    97  	ms, err := sr25519.GenerateMiniSecretKey()
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  
   102  	secret := ms.ExpandEd25519()
   103  	pub, err := secret.Public()
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	seed := ms.Encode()
   109  	return keyRing{
   110  		seed:   seed[:],
   111  		secret: secret,
   112  		pub:    pub,
   113  	}, nil
   114  }
   115  
   116  func (s Scheme) FromSeed(seed []byte) (subkey.KeyPair, error) {
   117  	switch len(seed) {
   118  	case miniSecretKeyLength:
   119  		var mss [32]byte
   120  		copy(mss[:], seed)
   121  		ms, err := sr25519.NewMiniSecretKeyFromRaw(mss)
   122  		if err != nil {
   123  			return nil, err
   124  		}
   125  
   126  		return keyRing{
   127  			seed:   seed,
   128  			secret: ms.ExpandEd25519(),
   129  			pub:    ms.Public(),
   130  		}, nil
   131  
   132  	case secretKeyLength:
   133  		var key, nonce [32]byte
   134  		copy(key[:], seed[0:32])
   135  		copy(nonce[:], seed[32:64])
   136  		secret := sr25519.NewSecretKey(key, nonce)
   137  		pub, err := secret.Public()
   138  		if err != nil {
   139  			return nil, err
   140  		}
   141  
   142  		return keyRing{
   143  			seed:   seed,
   144  			secret: secret,
   145  			pub:    pub,
   146  		}, nil
   147  	}
   148  
   149  	return nil, errors.New("invalid seed length")
   150  }
   151  
   152  func (s Scheme) FromPhrase(phrase, pwd string) (subkey.KeyPair, error) {
   153  	ms, err := sr25519.MiniSecretFromMnemonic(phrase, pwd)
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  
   158  	secret := ms.ExpandEd25519()
   159  	pub, err := secret.Public()
   160  	if err != nil {
   161  		return nil, err
   162  	}
   163  
   164  	seed := ms.Encode()
   165  	return keyRing{
   166  		seed:   seed[:],
   167  		secret: secret,
   168  		pub:    pub,
   169  	}, nil
   170  }
   171  
   172  func (s Scheme) Derive(pair subkey.KeyPair, djs []subkey.DeriveJunction) (subkey.KeyPair, error) {
   173  	kr := pair.(keyRing)
   174  	secret := kr.secret
   175  	seed := kr.seed
   176  	var err error
   177  	for _, dj := range djs {
   178  		if dj.IsHard {
   179  			ms, err := deriveKeyHard(secret, dj.ChainCode)
   180  			if err != nil {
   181  				return nil, err
   182  			}
   183  
   184  			secret = ms.ExpandEd25519()
   185  			if seed != nil {
   186  				es := ms.Encode()
   187  				seed = es[:]
   188  			}
   189  			continue
   190  		}
   191  
   192  		secret, err = deriveKeySoft(secret, dj.ChainCode)
   193  		if err != nil {
   194  			return nil, err
   195  		}
   196  		seed = nil
   197  	}
   198  
   199  	pub, err := secret.Public()
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  
   204  	return &keyRing{seed: seed, secret: secret, pub: pub}, nil
   205  }
   206  
   207  func (s Scheme) FromPublicKey(bytes []byte) (subkey.PublicKey, error) {
   208  	if len(bytes) != 32 {
   209  		return nil, fmt.Errorf("expected 32 bytes")
   210  	}
   211  	arr := [32]byte{}
   212  	copy(arr[:], bytes[:32])
   213  	key := sr25519.NewPublicKey(arr)
   214  	return &keyRing{pub: key}, nil
   215  }