github.com/stafiprotocol/go-substrate-rpc-client@v1.4.7/signature/signature.go (about) 1 // Go Substrate RPC Client (GSRPC) provides APIs and types around Polkadot and any Substrate-based chain RPC calls 2 // 3 // Copyright 2020 Stafi Protocol 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package signature 18 19 import ( 20 "errors" 21 "fmt" 22 "os" 23 "strconv" 24 25 "github.com/stafiprotocol/go-substrate-rpc-client/sr25519" 26 "github.com/stafiprotocol/go-substrate-rpc-client/subkey" 27 "golang.org/x/crypto/blake2b" 28 ) 29 30 type KeyringPair struct { 31 // URI is the derivation path for the private key in subkey 32 URI string 33 // Address is an SS58 address 34 Address string 35 // PublicKey 36 PublicKey []byte 37 } 38 39 // InspectKeyInfo type is used as target from `subkey` inspect JSON output 40 type InspectKeyInfo struct { 41 AccountID string `json:"accountId"` 42 PublicKey string `json:"publicKey"` 43 SecretPhrase string `json:"secretPhrase"` 44 SecretSeed string `json:"secretSeed"` 45 SS58Address string `json:"ss58Address"` 46 } 47 48 // KeyringPairFromSecret creates KeyPair based on seed/phrase and network 49 // Leave network empty for default behavior 50 func KeyringPairFromSecret(seedOrPhrase string, network uint16) (KeyringPair, error) { 51 52 scheme := sr25519.Scheme{} 53 kyr, err := subkey.DeriveKeyPair(scheme, seedOrPhrase) 54 if err != nil { 55 return KeyringPair{}, err 56 } 57 58 return KeyringPair{ 59 URI: seedOrPhrase, 60 Address: kyr.SS58Address(network), 61 PublicKey: kyr.Public(), 62 }, nil 63 } 64 65 var TestKeyringPairAlice = KeyringPair{ 66 URI: "//Alice", 67 PublicKey: []byte{0xd4, 0x35, 0x93, 0xc7, 0x15, 0xfd, 0xd3, 0x1c, 0x61, 0x14, 0x1a, 0xbd, 0x4, 0xa9, 0x9f, 0xd6, 0x82, 0x2c, 0x85, 0x58, 0x85, 0x4c, 0xcd, 0xe3, 0x9a, 0x56, 0x84, 0xe7, 0xa5, 0x6d, 0xa2, 0x7d}, //nolint:lll 68 Address: "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", 69 } 70 71 // Sign signs data with the private key under the given derivation path, returning the signature. Requires the subkey 72 // command to be in path 73 func Sign(data []byte, privateKeyURI string) ([]byte, error) { 74 // if data is longer than 256 bytes, hash it first 75 if len(data) > 256 { 76 h := blake2b.Sum256(data) 77 data = h[:] 78 } 79 scheme := sr25519.Scheme{} 80 kyr, err := subkey.DeriveKeyPair(scheme, privateKeyURI) 81 if err != nil { 82 return nil, err 83 } 84 85 signature, err := kyr.Sign(data) 86 if err != nil { 87 return nil, err 88 } 89 90 return signature, nil 91 } 92 93 // Verify verifies data using the provided signature and the key under the derivation path. Requires the subkey 94 // command to be in path 95 func Verify(data []byte, sig []byte, privateKeyURI string) (bool, error) { 96 // if data is longer than 256 bytes, hash it first 97 if len(data) > 256 { 98 h := blake2b.Sum256(data) 99 data = h[:] 100 } 101 102 scheme := sr25519.Scheme{} 103 kyr, err := subkey.DeriveKeyPair(scheme, privateKeyURI) 104 if err != nil { 105 return false, err 106 } 107 108 if len(sig) != 64 { 109 return false, errors.New("wrong signature length") 110 } 111 112 v := kyr.Verify(data, sig) 113 114 return v, nil 115 } 116 117 // LoadKeyringPairFromEnv looks up whether the env variable TEST_PRIV_KEY is set and is not empty and tries to use its 118 // content as a private phrase, seed or URI to derive a key ring pair. Panics if the private phrase, seed or URI is 119 // not valid or the keyring pair cannot be derived 120 // Loads Network from TEST_NETWORK variable 121 // Leave TEST_NETWORK empty or unset for default 122 func LoadKeyringPairFromEnv() (kp KeyringPair, ok bool) { 123 networkString := os.Getenv("TEST_NETWORK") 124 network, err := strconv.ParseInt(networkString, 10, 16) 125 if err != nil { 126 // defaults to generic substrate address 127 // https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)#checksum-types 128 network = 42 129 } 130 priv, ok := os.LookupEnv("TEST_PRIV_KEY") 131 if !ok || priv == "" { 132 return kp, false 133 } 134 kp, err = KeyringPairFromSecret(priv, uint16(network)) 135 if err != nil { 136 panic(fmt.Errorf("cannot load keyring pair from env or use fallback: %v", err)) 137 } 138 return kp, true 139 }