1717package signature
1818
1919import (
20- "encoding/hex"
21- "encoding/json"
20+ "errors"
2221 "fmt"
2322 "os"
24- "os/exec"
25- "strings"
23+ "strconv"
2624
25+ "github.com/vedhavyas/go-subkey"
26+ "github.com/vedhavyas/go-subkey/sr25519"
2727 "golang.org/x/crypto/blake2b"
2828)
2929
30- const subkeyCmd = "subkey"
31-
3230type KeyringPair struct {
3331 // URI is the derivation path for the private key in subkey
3432 URI string
@@ -38,52 +36,25 @@ type KeyringPair struct {
3836 PublicKey []byte
3937}
4038
41- // InspectKeyInfo type is used as target from `subkey` inspect JSON output
42- type InspectKeyInfo struct {
43- AccountID string `json:"accountId"`
44- PublicKey string `json:"publicKey"`
45- SecretPhrase string `json:"secretPhrase"`
46- SecretSeed string `json:"secretSeed"`
47- SS58Address string `json:"ss58Address"`
48- }
49-
5039// KeyringPairFromSecret creates KeyPair based on seed/phrase and network
5140// Leave network empty for default behavior
52- func KeyringPairFromSecret (seedOrPhrase , network string ) (KeyringPair , error ) {
53- var args []string
54- if network != "" {
55- args = []string {"--network" , network }
56- }
57- args = append ([]string {"inspect" , "--output-type" , "Json" , seedOrPhrase }, args ... )
58-
59- // use "subkey" command for creation of public key and address
60- cmd := exec .Command (subkeyCmd , args ... )
61-
62- // execute the command, get the output
63- out , err := cmd .Output ()
41+ func KeyringPairFromSecret (seedOrPhrase string , network uint8 ) (KeyringPair , error ) {
42+ scheme := sr25519.Scheme {}
43+ kyr , err := subkey .DeriveKeyPair (scheme , seedOrPhrase )
6444 if err != nil {
65- return KeyringPair {}, fmt . Errorf ( "failed to generate keyring pair from secret: %v" , err . Error ())
45+ return KeyringPair {}, err
6646 }
6747
68- if string (out ) == "Invalid phrase/URI given" {
69- return KeyringPair {}, fmt .Errorf ("failed to generate keyring pair from secret: invalid phrase/URI given" )
70- }
71-
72- var keyInfo InspectKeyInfo
73- err = json .Unmarshal (out , & keyInfo )
48+ ss58Address , err := kyr .SS58Address (network )
7449 if err != nil {
75- return KeyringPair {}, fmt . Errorf ( "failed to deserialize key info JSON output: %v" , err . Error ())
50+ return KeyringPair {}, err
7651 }
7752
78- pk , err := hex .DecodeString (strings .Replace (keyInfo .PublicKey , "0x" , "" , 1 ))
79- if err != nil {
80- return KeyringPair {}, fmt .Errorf ("failed to generate keyring pair from secret, could not hex decode pubkey: " +
81- "%v with error: %v" , keyInfo .PublicKey , err .Error ())
82- }
53+ var pk = kyr .Public ()
8354
8455 return KeyringPair {
8556 URI : seedOrPhrase ,
86- Address : keyInfo . SS58Address ,
57+ Address : ss58Address ,
8758 PublicKey : pk ,
8859 }, nil
8960}
@@ -103,31 +74,18 @@ func Sign(data []byte, privateKeyURI string) ([]byte, error) {
10374 data = h [:]
10475 }
10576
106- // use "subkey" command for signature
107- cmd := exec .Command (subkeyCmd , "sign" , "--suri" , privateKeyURI , "--hex" )
108-
109- // data to stdin
110- dataHex := hex .EncodeToString (data )
111- cmd .Stdin = strings .NewReader (dataHex )
112-
113- // log.Printf("echo -n \"%v\" | %v sign %v --hex", dataHex, subkeyCmd, privateKeyURI)
114-
115- // execute the command, get the output
116- out , err := cmd .Output ()
77+ scheme := sr25519.Scheme {}
78+ kyr , err := subkey .DeriveKeyPair (scheme , privateKeyURI )
11779 if err != nil {
118- return nil , fmt . Errorf ( "failed to sign with subkey: %v" , err . Error ())
80+ return nil , err
11981 }
12082
121- // remove line feed
122- if len ( out ) > 0 && out [ len ( out ) - 1 ] == 10 {
123- out = out [: len ( out ) - 1 ]
83+ signature , err := kyr . Sign ( data )
84+ if err != nil {
85+ return nil , err
12486 }
12587
126- outStr := string (out )
127-
128- dec , err := hex .DecodeString (outStr )
129-
130- return dec , err
88+ return signature , nil
13189}
13290
13391// Verify verifies data using the provided signature and the key under the derivation path. Requires the subkey
@@ -139,32 +97,19 @@ func Verify(data []byte, sig []byte, privateKeyURI string) (bool, error) {
13997 data = h [:]
14098 }
14199
142- // hexify the sig
143- sigHex := hex .EncodeToString (sig )
144-
145- // use "subkey" command for signature
146- cmd := exec .Command (subkeyCmd , "verify" , "--hex" , sigHex , privateKeyURI )
147-
148- // data to stdin
149- dataHex := hex .EncodeToString (data )
150- cmd .Stdin = strings .NewReader (dataHex )
151-
152- //log.Printf("echo -n \"%v\" | %v verify --hex %v %v", dataHex, subkeyCmd, sigHex, privateKeyURI)
153-
154- // execute the command, get the output
155- out , err := cmd .Output ()
100+ scheme := sr25519.Scheme {}
101+ kyr , err := subkey .DeriveKeyPair (scheme , privateKeyURI )
156102 if err != nil {
157- return false , fmt . Errorf ( "failed to verify with subkey: %v" , err . Error ())
103+ return false , err
158104 }
159105
160- // remove line feed
161- if len (out ) > 0 && out [len (out )- 1 ] == 10 {
162- out = out [:len (out )- 1 ]
106+ if len (sig ) != 64 {
107+ return false , errors .New ("wrong signature length" )
163108 }
164109
165- outStr := string ( out )
166- valid := outStr == "Signature verifies correctly."
167- return valid , nil
110+ v := kyr . Verify ( data , sig )
111+
112+ return v , nil
168113}
169114
170115// LoadKeyringPairFromEnv looks up whether the env variable TEST_PRIV_KEY is set and is not empty and tries to use its
@@ -173,12 +118,18 @@ func Verify(data []byte, sig []byte, privateKeyURI string) (bool, error) {
173118// Loads Network from TEST_NETWORK variable
174119// Leave TEST_NETWORK empty or unset for default
175120func LoadKeyringPairFromEnv () (kp KeyringPair , ok bool ) {
176- network := os .Getenv ("TEST_NETWORK" )
121+ networkString := os .Getenv ("TEST_NETWORK" )
122+ network , err := strconv .ParseInt (networkString , 10 , 8 )
123+ if err != nil {
124+ // defaults to generic substrate address
125+ // https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)#checksum-types
126+ network = 42
127+ }
177128 priv , ok := os .LookupEnv ("TEST_PRIV_KEY" )
178129 if ! ok || priv == "" {
179130 return kp , false
180131 }
181- kp , err : = KeyringPairFromSecret (priv , network )
132+ kp , err = KeyringPairFromSecret (priv , uint8 ( network ) )
182133 if err != nil {
183134 panic (fmt .Errorf ("cannot load keyring pair from env or use fallback: %v" , err ))
184135 }
0 commit comments