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 }