Skip to content

Commit

Permalink
Merge pull request #4 from NodeFactoryIo/mmuftic/replace-subkey
Browse files Browse the repository at this point in the history
Replace subkey with go-subkey port
  • Loading branch information
mace authored Nov 17, 2020
2 parents f0ad28d + dd85a5d commit fe8589d
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 118 deletions.
11 changes: 1 addition & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
# Note: We don't use Alpine and its packaged Rust/Cargo because they're too often out of date,
# preventing them from being used to build Substrate/Polkadot.

# First Phase - Load Subkey
FROM parity/subkey:2.0.0 as subkey
RUN subkey --version

## Second Phase - Build context for tests
## First Phase - Build context for tests
FROM parity/substrate:v2.0.0

USER root

COPY --from=subkey /usr/local/bin/subkey /usr/local/bin/subkey

# gcc for cgo
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
Expand Down Expand Up @@ -65,9 +59,6 @@ RUN mkdir -p $GOPATH/src/github.com/NodeFactoryIo/go-substrate-rpc-client
WORKDIR $GOPATH/src/github.com/NodeFactoryIo/go-substrate-rpc-client
COPY . .

# Ensuring Subkey is available
RUN subkey --version

RUN make install

# Reset parent entrypoint
Expand Down
6 changes: 3 additions & 3 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ type client struct {
url string

// metadataVersioned is the metadata cache to prevent unnecessary requests
//metadataVersioned *MetadataVersioned
// metadataVersioned *MetadataVersioned

//metadataLock sync.RWMutex
// metadataLock sync.RWMutex
}

// URL returns the URL the client connects to
Expand All @@ -52,7 +52,7 @@ func (c client) URL() string {
}

// TODO move to State struct
//func (c *client) MetaData(cache bool) (m *MetadataVersioned, err error) {
// func (c *client) MetaData(cache bool) (m *MetadataVersioned, err error) {
// if cache && c.metadataVersioned != nil {
// c.metadataLock.RLock()
// defer c.metadataLock.RUnlock()
Expand Down
3 changes: 2 additions & 1 deletion gethrpc/subscription_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package rpc
import (
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/common/hexutil"
"net"
"strings"
"testing"
Expand All @@ -28,7 +29,7 @@ import (
func TestNewID(t *testing.T) {
hexchars := "0123456789ABCDEFabcdef"
for i := 0; i < 100; i++ {
id := string(NewID())
id := hexutil.EncodeUint64(uint64(NewID()))
if !strings.HasPrefix(id, "0x") {
t.Fatalf("invalid ID prefix, want '0x...', got %s", id)
}
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ require (
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pierrec/xxHash v0.1.5
github.com/rs/cors v1.6.0
github.com/stretchr/testify v1.3.0
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7 // indirect
github.com/stretchr/testify v1.4.0
github.com/vedhavyas/go-subkey v0.0.0-20200211154731-4cce0189eaa4
golang.org/x/crypto v0.0.0-20200109152110-61a87790db17
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
)
32 changes: 32 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
github.com/ChainSafe/go-schnorrkel v0.0.0-20200112161544-2f1a03be8459 h1:fGu/ZmqFoLr+ddIuqYlddEXH2swjwKl9YgvZp6gjgws=
github.com/ChainSafe/go-schnorrkel v0.0.0-20200112161544-2f1a03be8459/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4=
github.com/aristanetworks/goarista v0.0.0-20190712234253-ed1100a1c015 h1:7ABPr1+uJdqESAdlVevnc/2FJGiC/K3uMg1JiELeF+0=
github.com/aristanetworks/goarista v0.0.0-20190712234253-ed1100a1c015/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/btcsuite/btcutil v0.0.0-20191219182022-e17c9730c422/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/decred/base58 v1.0.2 h1:yupIH6bg+q7KYfBk7oUv3xFjKGb5Ypm4+v/61X4keGY=
github.com/decred/base58 v1.0.2/go.mod h1:pXP9cXCfM2sFLb2viz2FNIdeMWmZDBKG3ZBYbiSM78E=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/ethereum/go-ethereum v1.9.3 h1:v3bE4abkXknLcyWCf4TRFn+Ecmm9thPtfLFvTEQ+1+U=
github.com/ethereum/go-ethereum v1.9.3/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is=
github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc=
github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pierrec/xxHash v0.1.5 h1:n/jBpwTHiER4xYvK3/CdPVnLDPchj8eTJFFLUb4QHBo=
Expand All @@ -25,16 +43,30 @@ github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/vedhavyas/go-subkey v0.0.0-20200211154731-4cce0189eaa4 h1:rBS1TlztYpCZTqoGzc6QyXudrhJduRG2D4kq04CS2Vg=
github.com/vedhavyas/go-subkey v0.0.0-20200211154731-4cce0189eaa4/go.mod h1:44zD24L8S1GZLwtUrxOVFee+TG9S8Zw5Ij2eirlizNg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 h1:nVJ3guKA9qdkEQ3TUdXI9QSINo2CUPM/cySEvw2w8I0=
golang.org/x/crypto v0.0.0-20200109152110-61a87790db17/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7 h1:LepdCS8Gf/MVejFIt8lsiexZATdoGVyp5bcyS+rYoUI=
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
12 changes: 6 additions & 6 deletions rpcmocksrv/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
package rpcmocksrv

import (
"math/rand"
"crypto/rand"
"math/big"
"strconv"
"time"

gethrpc "github.com/NodeFactoryIo/go-substrate-rpc-client/gethrpc"
)
Expand Down Expand Up @@ -50,8 +50,8 @@ func New() *Server {
}

func randomPort() int {
rand.Seed(time.Now().UnixNano())
min := 10000
max := 30000
return rand.Intn(max-min+1) + min
min := int64(10000)
max := int64(30000)
n, _ := rand.Int(rand.Reader, big.NewInt(max-min+1))
return int(n.Int64() + min)
}
109 changes: 32 additions & 77 deletions signature/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,15 @@
package signature

import (
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"os"
"os/exec"
"strings"

"github.com/vedhavyas/go-subkey/common"
subkey "github.com/vedhavyas/go-subkey/sr25519"
"golang.org/x/crypto/blake2b"
)

const subkeyCmd = "subkey"

type KeyringPair struct {
// URI is the derivation path for the private key in subkey
URI string
Expand All @@ -38,52 +35,31 @@ type KeyringPair struct {
PublicKey []byte
}

// InspectKeyInfo type is used as target from `subkey` inspect JSON output
type InspectKeyInfo struct {
AccountID string `json:"accountId"`
PublicKey string `json:"publicKey"`
SecretPhrase string `json:"secretPhrase"`
SecretSeed string `json:"secretSeed"`
SS58Address string `json:"ss58Address"`
}

// KeyringPairFromSecret creates KeyPair based on seed/phrase and network
// Leave network empty for default behavior
func KeyringPairFromSecret(seedOrPhrase, network string) (KeyringPair, error) {
var args []string
if network != "" {
args = []string{"--network", network}
if network == "" {
network = "substrate"
}
args = append([]string{"inspect", "--output-type", "Json", seedOrPhrase}, args...)

// use "subkey" command for creation of public key and address
cmd := exec.Command(subkeyCmd, args...)

// execute the command, get the output
out, err := cmd.Output()
kyr, err := subkey.KeyRingFromURI(seedOrPhrase)
if err != nil {
return KeyringPair{}, fmt.Errorf("failed to generate keyring pair from secret: %v", err.Error())
return KeyringPair{}, err
}

if string(out) == "Invalid phrase/URI given" {
return KeyringPair{}, fmt.Errorf("failed to generate keyring pair from secret: invalid phrase/URI given")
}

var keyInfo InspectKeyInfo
err = json.Unmarshal(out, &keyInfo)
ss58Address, err := kyr.SS58Address(network, common.SS58Checksum)
if err != nil {
return KeyringPair{}, fmt.Errorf("failed to deserialize key info JSON output: %v", err.Error())
return KeyringPair{}, err
}

pk, err := hex.DecodeString(strings.Replace(keyInfo.PublicKey, "0x", "", 1))
if err != nil {
return KeyringPair{}, fmt.Errorf("failed to generate keyring pair from secret, could not hex decode pubkey: "+
"%v with error: %v", keyInfo.PublicKey, err.Error())
var pk []byte
for _, b := range kyr.Public() {
pk = append(pk, b)
}

return KeyringPair{
URI: seedOrPhrase,
Address: keyInfo.SS58Address,
Address: ss58Address,
PublicKey: pk,
}, nil
}
Expand All @@ -103,31 +79,22 @@ func Sign(data []byte, privateKeyURI string) ([]byte, error) {
data = h[:]
}

// use "subkey" command for signature
cmd := exec.Command(subkeyCmd, "sign", "--suri", privateKeyURI, "--hex")

// data to stdin
dataHex := hex.EncodeToString(data)
cmd.Stdin = strings.NewReader(dataHex)

// log.Printf("echo -n \"%v\" | %v sign %v --hex", dataHex, subkeyCmd, privateKeyURI)

// execute the command, get the output
out, err := cmd.Output()
kyr, err := subkey.KeyRingFromURI(privateKeyURI)
if err != nil {
return nil, fmt.Errorf("failed to sign with subkey: %v", err.Error())
return nil, err
}

// remove line feed
if len(out) > 0 && out[len(out)-1] == 10 {
out = out[:len(out)-1]
signature, err := kyr.Sign(data)
if err != nil {
return nil, err
}

outStr := string(out)

dec, err := hex.DecodeString(outStr)
var sgn []byte
for _, b := range signature {
sgn = append(sgn, b)
}

return dec, err
return sgn, nil
}

// Verify verifies data using the provided signature and the key under the derivation path. Requires the subkey
Expand All @@ -139,32 +106,20 @@ func Verify(data []byte, sig []byte, privateKeyURI string) (bool, error) {
data = h[:]
}

// hexify the sig
sigHex := hex.EncodeToString(sig)

// use "subkey" command for signature
cmd := exec.Command(subkeyCmd, "verify", "--hex", sigHex, privateKeyURI)

// data to stdin
dataHex := hex.EncodeToString(data)
cmd.Stdin = strings.NewReader(dataHex)

//log.Printf("echo -n \"%v\" | %v verify --hex %v %v", dataHex, subkeyCmd, sigHex, privateKeyURI)

// execute the command, get the output
out, err := cmd.Output()
kyr, err := subkey.KeyRingFromURI(privateKeyURI)
if err != nil {
return false, fmt.Errorf("failed to verify with subkey: %v", err.Error())
return false, err
}

// remove line feed
if len(out) > 0 && out[len(out)-1] == 10 {
out = out[:len(out)-1]
if len(sig) != 64 {
return false, errors.New("wrong signature length")
}
var sig64 [64]byte
copy(sig64[:], sig)

v := kyr.Verify(data, sig64)

outStr := string(out)
valid := outStr == "Signature verifies correctly."
return valid, nil
return v, nil
}

// LoadKeyringPairFromEnv looks up whether the env variable TEST_PRIV_KEY is set and is not empty and tries to use its
Expand Down
Loading

0 comments on commit fe8589d

Please sign in to comment.