Skip to content
This repository has been archived by the owner on Mar 5, 2022. It is now read-only.

Commit

Permalink
feat: Sign config files in cli
Browse files Browse the repository at this point in the history
closes #148

Signed-off-by: Firas Qutishat <[email protected]>
  • Loading branch information
fqutishat committed May 26, 2020
1 parent b04386d commit 578757e
Show file tree
Hide file tree
Showing 14 changed files with 128 additions and 104 deletions.
58 changes: 37 additions & 21 deletions cmd/did-method-cli/createconfigcmd/createconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package createconfigcmd
import (
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
Expand All @@ -18,8 +17,8 @@ import (
"strings"

docdid "github.com/hyperledger/aries-framework-go/pkg/doc/did"
"github.com/hyperledger/aries-framework-go/pkg/doc/jose"
"github.com/spf13/cobra"
gojose "github.com/square/go-jose/v3"
cmdutils "github.com/trustbloc/edge-core/pkg/utils/cmd"
tlsutils "github.com/trustbloc/edge-core/pkg/utils/tls"

Expand Down Expand Up @@ -79,10 +78,11 @@ type memberData struct {
Policy models.StakeholderSettings `json:"policy"`
// Endpoints is a list of sidetree endpoints owned by this stakeholder organization
Endpoints []string `json:"endpoints"`
// PrivateKeyJwk is privatekey jwk
PrivateKeyJwk json.RawMessage `json:"privateKeyJwk,omitempty"`
// PrivateKeyJwk is privatekey jwk file
PrivateKeyJwkPath string `json:"privateKeyJwkPath,omitempty"`

jsonWebKey jose.JWK
jsonWebKey gojose.JSONWebKey
sigKey gojose.SigningKey
}

type didClient interface {
Expand Down Expand Up @@ -156,8 +156,10 @@ func createCreateConfigCmd() *cobra.Command {
}

func writeConfig(outputDirectory string, filesData map[string][]byte) error {
if err := os.MkdirAll(outputDirectory, 0700); err != nil {
return err
if outputDirectory != "" {
if err := os.MkdirAll(outputDirectory, 0700); err != nil {
return err
}
}

for k, v := range filesData {
Expand Down Expand Up @@ -189,9 +191,16 @@ func getConfig(cmd *cobra.Command) (*config, error) {
}

for _, member := range config.MembersData {
if err := member.jsonWebKey.UnmarshalJSON(member.PrivateKeyJwk); err != nil {
return nil, err
jwkData, err := ioutil.ReadFile(member.PrivateKeyJwkPath) //nolint: gosec
if err != nil {
return nil, fmt.Errorf("failed to read jwk file '%s' : %w", member.PrivateKeyJwkPath, err)
}

if err := member.jsonWebKey.UnmarshalJSON(jwkData); err != nil {
return nil, fmt.Errorf("failed to unmarshal to jwk: %w", err)
}
// TODO add support for ECDSA using P-256 and SHA-256
member.sigKey = gojose.SigningKey{Key: member.jsonWebKey.Key, Algorithm: gojose.EdDSA}
}

return &config, nil
Expand Down Expand Up @@ -233,6 +242,7 @@ func createFlags(startCmd *cobra.Command) {

func createConfig(parameters *parameters) (map[string][]byte, error) {
filesData := make(map[string][]byte)
sigKeys := make([]gojose.SigningKey, 0)

consortium := models.Consortium{Domain: parameters.config.ConsortiumData.Domain,
Policy: parameters.config.ConsortiumData.Policy}
Expand Down Expand Up @@ -260,40 +270,46 @@ func createConfig(parameters *parameters) (map[string][]byte, error) {
return nil, err
}

jwsBytes, err := signConfig(stakeholderBytes)
jws, err := signConfig(stakeholderBytes, []gojose.SigningKey{member.sigKey})
if err != nil {
return nil, err
}

filesData[member.Domain] = jwsBytes
sigKeys = append(sigKeys, member.sigKey)

filesData[member.Domain] = []byte(jws)
}

consortiumBytes, err := json.Marshal(consortium)
if err != nil {
return nil, err
}

jwsBytes, err := signConfig(consortiumBytes)
jws, err := signConfig(consortiumBytes, sigKeys)
if err != nil {
return nil, err
}

filesData[consortium.Domain] = jwsBytes
filesData[consortium.Domain] = []byte(jws)

return filesData, nil
}

func signConfig(configBytes []byte) ([]byte, error) {
// TODO add logic for jws
// for now return dummy jws
// remove this code after adding logic for jws
m := make(map[string]interface{})
m["payload"] = base64.RawURLEncoding.EncodeToString(configBytes)
func signConfig(configBytes []byte, keys []gojose.SigningKey) (string, error) {
signer, err := gojose.NewMultiSigner(keys, nil)
if err != nil {
return "", err
}

jws, err := signer.Sign(configBytes)
if err != nil {
return "", err
}

return json.Marshal(m)
return jws.FullSerialize(), nil
}

func createDID(didClient didClient, sidetreeURL string, jwk *jose.JWK) (*docdid.Doc, error) {
func createDID(didClient didClient, sidetreeURL string, jwk *gojose.JSONWebKey) (*docdid.Doc, error) {
pubKey, err := jwk.Public().MarshalJSON()
if err != nil {
return nil, err
Expand Down
97 changes: 55 additions & 42 deletions cmd/did-method-cli/createconfigcmd/createconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ SPDX-License-Identifier: Apache-2.0
package createconfigcmd

import (
"fmt"
"io/ioutil"
"os"
"testing"
Expand All @@ -21,7 +22,7 @@ import (
const flag = "--"

// nolint: gochecknoglobals
var configDataWithWrongJWK = `{
var configData = `{
"consortium_data": {
"domain": "consortium.net",
"policy": {
Expand All @@ -46,53 +47,19 @@ var configDataWithWrongJWK = `{
"http://endpoints.stakeholder.one/peer1/",
"http://endpoints.stakeholder.one/peer2/"
],
"privateKeyJwk": {
"kty": "OKP",
"kid": "key1",
"d": 1,
"crv": "Ed25519",
"x": "bWRCy8DtNhRO3HdKTFB2eEG5Ac1J00D0DQPffOwtAD0"
}
"privateKeyJwkPath": "%s"
}
]
}`

// nolint: gochecknoglobals
var configData = `{
"consortium_data": {
"domain": "consortium.net",
"policy": {
"cache": {
"max_age": 2419200
},
"num_queries": 2,
"history_hash": "SHA256",
"sidetree": {
"hash_algorithm": "SHA256",
"key_algorithm": "NotARealAlg2018",
"max_encoded_hash_length": 100,
"max_operation_size": 8192
}
}
},
"members_data": [
{
"domain": "stakeholder.one",
"policy": {"cache": {"max_age": 604800}},
"endpoints": [
"http://endpoints.stakeholder.one/peer1/",
"http://endpoints.stakeholder.one/peer2/"
],
"privateKeyJwk": {
var jwkData = `{
"kty": "OKP",
"kid": "key1",
"d": "-YawjZSeB9Rkdol9SHeOcT9hIvo_VuH6zM-pgtk3b10",
"crv": "Ed25519",
"x": "bWRCy8DtNhRO3HdKTFB2eEG5Ac1J00D0DQPffOwtAD0"
}
}
]
}`
}`

func TestCreateConfigCmdWithMissingArg(t *testing.T) {
t.Run("test missing arg sidetree url", func(t *testing.T) {
Expand Down Expand Up @@ -133,13 +100,43 @@ func TestCreateConfigCmd(t *testing.T) {
require.Contains(t, err.Error(), "failed to read config file")
})

t.Run("test wrong path for private key jwk", func(t *testing.T) {
cmd := GetCreateConfigCmd()

file, err := ioutil.TempFile("", "*.json")
require.NoError(t, err)

_, err = file.WriteString(fmt.Sprintf(configData, "notexist.json"))
require.NoError(t, err)

defer func() { require.NoError(t, os.Remove(file.Name())) }()

var args []string
args = append(args, sidetreeURLArg()...)
args = append(args, configFileArg(file.Name())...)

cmd.SetArgs(args)

err = cmd.Execute()
require.Error(t, err)
require.Contains(t, err.Error(), "failed to read jwk file")
})

t.Run("test wrong private key jwk", func(t *testing.T) {
cmd := GetCreateConfigCmd()

jwkFile, err := ioutil.TempFile("", "*.json")
require.NoError(t, err)

defer func() { require.NoError(t, os.Remove(jwkFile.Name())) }()

_, err = jwkFile.WriteString("wrongjwk")
require.NoError(t, err)

file, err := ioutil.TempFile("", "*.json")
require.NoError(t, err)

_, err = file.WriteString(configDataWithWrongJWK)
_, err = file.WriteString(fmt.Sprintf(configData, jwkFile.Name()))
require.NoError(t, err)

defer func() { require.NoError(t, os.Remove(file.Name())) }()
Expand All @@ -152,16 +149,24 @@ func TestCreateConfigCmd(t *testing.T) {

err = cmd.Execute()
require.Error(t, err)
require.Contains(t, err.Error(), "unable to read JWK")
require.Contains(t, err.Error(), "failed to unmarshal to jwk")
})

t.Run("test error from create did", func(t *testing.T) {
cmd := GetCreateConfigCmd()

jwkFile, err := ioutil.TempFile("", "*.json")
require.NoError(t, err)

defer func() { require.NoError(t, os.Remove(jwkFile.Name())) }()

_, err = jwkFile.WriteString(jwkData)
require.NoError(t, err)

file, err := ioutil.TempFile("", "*.json")
require.NoError(t, err)

_, err = file.WriteString(configData)
_, err = file.WriteString(fmt.Sprintf(configData, jwkFile.Name()))
require.NoError(t, err)

defer func() { require.NoError(t, os.Remove(file.Name())) }()
Expand All @@ -180,10 +185,18 @@ func TestCreateConfigCmd(t *testing.T) {
t.Run("test create config and write them to file", func(t *testing.T) {
os.Clearenv()

jwkFile, err := ioutil.TempFile("", "*.json")
require.NoError(t, err)

defer func() { require.NoError(t, os.Remove(jwkFile.Name())) }()

_, err = jwkFile.WriteString(jwkData)
require.NoError(t, err)

file, err := ioutil.TempFile("", "*.json")
require.NoError(t, err)

_, err = file.WriteString(configData)
_, err = file.WriteString(fmt.Sprintf(configData, jwkFile.Name()))
require.NoError(t, err)

defer func() { require.NoError(t, os.Remove(file.Name())) }()
Expand Down
2 changes: 2 additions & 0 deletions cmd/did-method-cli/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ replace github.com/trustbloc/trustbloc-did-method => ../..
require (
github.com/hyperledger/aries-framework-go v0.1.4-0.20200521101441-dcc599e23d09
github.com/spf13/cobra v1.0.0
github.com/square/go-jose/v3 v3.0.0-20191119004800-96c717272387
github.com/stretchr/testify v1.5.1
github.com/trustbloc/edge-core v0.1.3
github.com/trustbloc/trustbloc-did-method v0.0.0-00010101000000-000000000000
)
Expand Down
11 changes: 7 additions & 4 deletions cmd/did-method-cli/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
github.com/aws/aws-sdk-go v1.25.39/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bluele/gcache v0.0.0-20190518031135-bc40bd653833/go.mod h1:8c4/i2VlovMO2gBnHGQPN5EJw+H0lx1u/5p+cgsXtCk=
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
Expand Down Expand Up @@ -73,6 +74,7 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
Expand Down Expand Up @@ -181,8 +183,8 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/square/go-jose v2.4.1+incompatible h1:KFYc54wTtgnd3x4B/Y7Zr1s/QaEx2BNzRsB3Hae5LHo=
github.com/square/go-jose v2.4.1+incompatible/go.mod h1:7MxpAF/1WTVUu8Am+T5kNy+t0902CaLWM4Z745MkOa8=
github.com/square/go-jose v2.5.1+incompatible h1:FC+BwI9FzJZWpKaE0yUhFNbp/CyFHndARzuGVME/LGk=
github.com/square/go-jose v2.5.1+incompatible/go.mod h1:7MxpAF/1WTVUu8Am+T5kNy+t0902CaLWM4Z745MkOa8=
github.com/square/go-jose/v3 v3.0.0-20191119004800-96c717272387 h1:PjfQbTWDEoNh4v+4NNirclXoCIxjjLXsqSAP1iYxuOM=
github.com/square/go-jose/v3 v3.0.0-20191119004800-96c717272387/go.mod h1:iYbsnddeHsxZC0AxvsQsVV1gPR8VPiSYT5FsUTeaEuY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down Expand Up @@ -278,6 +280,7 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
Expand All @@ -297,8 +300,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y=
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Expand Down
16 changes: 2 additions & 14 deletions cmd/did-method-cli/sample/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,7 @@
"http://endpoints.stakeholder.one/peer1/",
"http://endpoints.stakeholder.one/peer2/"
],
"privateKeyJwk": {
"kty": "OKP",
"kid": "key1",
"d": "CSLczqR1ly2lpyBcWne9gFKnsjaKJw0dKfoSQu7lNvg",
"crv": "Ed25519",
"x": "bWRCy8DtNhRO3HdKTFB2eEG5Ac1J00D0DQPffOwtAD0"
}
"privateKeyJwkPath": "./sample/stakeholderone_jwk.json"
},
{
"domain": "stakeholder.two",
Expand All @@ -38,13 +32,7 @@
"http://endpoints.stakeholder.two/peer1/",
"http://endpoints.stakeholder.two/peer2/"
],
"privateKeyJwk": {
"kty": "OKP",
"kid": "key1",
"d": "-YawjZSeB9Rkdol9SHeOcT9hIvo_VuH6zM-pgtk3b10",
"crv": "Ed25519",
"x": "8rfXFZNHZs9GYzGbQLYDasGUAm1brAgTLI0jrD4KheU"
}
"privateKeyJwkPath": "./sample/stakeholdertwo_jwk.json"
}
]
}
7 changes: 7 additions & 0 deletions cmd/did-method-cli/sample/stakeholderone_jwk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"kty": "OKP",
"kid": "key1",
"d": "CSLczqR1ly2lpyBcWne9gFKnsjaKJw0dKfoSQu7lNvg",
"crv": "Ed25519",
"x": "bWRCy8DtNhRO3HdKTFB2eEG5Ac1J00D0DQPffOwtAD0"
}
7 changes: 7 additions & 0 deletions cmd/did-method-cli/sample/stakeholdertwo_jwk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"kty": "OKP",
"kid": "key1",
"d": "-YawjZSeB9Rkdol9SHeOcT9hIvo_VuH6zM-pgtk3b10",
"crv": "Ed25519",
"x": "8rfXFZNHZs9GYzGbQLYDasGUAm1brAgTLI0jrD4KheU"
}
Loading

0 comments on commit 578757e

Please sign in to comment.