diff --git a/core/commands/name/name.go b/core/commands/name/name.go index e03312919c57..e1795b6e7121 100644 --- a/core/commands/name/name.go +++ b/core/commands/name/name.go @@ -15,7 +15,6 @@ import ( "github.com/ipld/go-ipld-prime" "github.com/ipld/go-ipld-prime/codec/dagcbor" "github.com/ipld/go-ipld-prime/codec/dagjson" - "github.com/libp2p/go-libp2p/core/crypto" mbase "github.com/multiformats/go-multibase" "google.golang.org/protobuf/proto" ) @@ -83,9 +82,9 @@ Resolve the value of a dnslink: } type IpnsInspectValidation struct { - Valid bool - Reason string - PublicKey string + Valid bool + Reason string + Name string } // IpnsInspectEntry contains the deserialized values from an IPNS Entry: @@ -218,21 +217,11 @@ Passing --verify will verify signature against provided public key. return err } - pk, err := ipns.ExtractPublicKey(rec, name) - if err != nil { - return err - } - - bytes, err := crypto.MarshalPublicKey(pk) - if err != nil { - return err - } - result.Validation = &IpnsInspectValidation{ - PublicKey: encoder.Encode(bytes), + Name: name.String(), } - err = ipns.Validate(rec, pk) + err = ipns.ValidateWithName(rec, name) if err == nil { result.Validation.Valid = true } else { @@ -278,7 +267,7 @@ Passing --verify will verify signature against provided public key. if out.Validation.Reason != "" { fmt.Fprintf(tw, "\tReason:\t%s\n", out.Validation.Reason) } - fmt.Fprintf(tw, "\tPublicKey:\t%s\n", out.Validation.PublicKey) + fmt.Fprintf(tw, "\tName:\t%s\n", out.Validation.Name) } return nil diff --git a/docs/examples/kubo-as-a-library/go.mod b/docs/examples/kubo-as-a-library/go.mod index 8aa87b9e5617..65cb1208ca60 100644 --- a/docs/examples/kubo-as-a-library/go.mod +++ b/docs/examples/kubo-as-a-library/go.mod @@ -7,7 +7,7 @@ go 1.18 replace github.com/ipfs/kubo => ./../../.. require ( - github.com/ipfs/boxo v0.10.1-0.20230615083040-d5e141ea82cd + github.com/ipfs/boxo v0.10.1-0.20230615091437-c5a71fad393d github.com/ipfs/kubo v0.0.0-00010101000000-000000000000 github.com/libp2p/go-libp2p v0.27.5 github.com/multiformats/go-multiaddr v0.9.0 diff --git a/docs/examples/kubo-as-a-library/go.sum b/docs/examples/kubo-as-a-library/go.sum index 2e1f6b5966ad..2c28761cb51b 100644 --- a/docs/examples/kubo-as-a-library/go.sum +++ b/docs/examples/kubo-as-a-library/go.sum @@ -319,8 +319,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/boxo v0.10.1-0.20230615083040-d5e141ea82cd h1:mR5STWmJw1n+JZ2t7Jx0vPxp+iL9vuAM4RFxoqFyww0= -github.com/ipfs/boxo v0.10.1-0.20230615083040-d5e141ea82cd/go.mod h1:IwBbXi5P7fA0HzLhsw/FtAj9RAMacODuOCPPsBcvqcE= +github.com/ipfs/boxo v0.10.1-0.20230615091437-c5a71fad393d h1:vgxYdy3FL2y/oBFpoioPImg3QccT7Y03fyCxfIhm3HY= +github.com/ipfs/boxo v0.10.1-0.20230615091437-c5a71fad393d/go.mod h1:IwBbXi5P7fA0HzLhsw/FtAj9RAMacODuOCPPsBcvqcE= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= diff --git a/go.mod b/go.mod index 0c420ba490e9..1dea79f699b9 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/fsnotify/fsnotify v1.6.0 github.com/google/uuid v1.3.0 github.com/hashicorp/go-multierror v1.1.1 - github.com/ipfs/boxo v0.10.1-0.20230615083040-d5e141ea82cd + github.com/ipfs/boxo v0.10.1-0.20230615091437-c5a71fad393d github.com/ipfs/go-block-format v0.1.2 github.com/ipfs/go-cid v0.4.1 github.com/ipfs/go-cidutil v0.1.0 diff --git a/go.sum b/go.sum index 2d286fde7041..39b695ea21d5 100644 --- a/go.sum +++ b/go.sum @@ -354,8 +354,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/boxo v0.10.1-0.20230615083040-d5e141ea82cd h1:mR5STWmJw1n+JZ2t7Jx0vPxp+iL9vuAM4RFxoqFyww0= -github.com/ipfs/boxo v0.10.1-0.20230615083040-d5e141ea82cd/go.mod h1:IwBbXi5P7fA0HzLhsw/FtAj9RAMacODuOCPPsBcvqcE= +github.com/ipfs/boxo v0.10.1-0.20230615091437-c5a71fad393d h1:vgxYdy3FL2y/oBFpoioPImg3QccT7Y03fyCxfIhm3HY= +github.com/ipfs/boxo v0.10.1-0.20230615091437-c5a71fad393d/go.mod h1:IwBbXi5P7fA0HzLhsw/FtAj9RAMacODuOCPPsBcvqcE= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= diff --git a/test/cli/fixtures/TestName.car b/test/cli/fixtures/TestName.car new file mode 100644 index 000000000000..8115dce5c107 Binary files /dev/null and b/test/cli/fixtures/TestName.car differ diff --git a/test/cli/name_test.go b/test/cli/name_test.go new file mode 100644 index 000000000000..d72866c74b15 --- /dev/null +++ b/test/cli/name_test.go @@ -0,0 +1,154 @@ +package cli + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "strings" + "testing" + + "github.com/ipfs/boxo/ipns" + "github.com/ipfs/kubo/core/commands/name" + "github.com/ipfs/kubo/test/cli/harness" + "github.com/stretchr/testify/require" +) + +func TestName(t *testing.T) { + const ( + fixturePath = "fixtures/TestName.car" + fixtureCid = "bafybeicxptj5cposoeaj5cwk3to7kivguoz6rdj56dr2aogzkeodzqfzfi" + ) + + makeDaemon := func(t *testing.T, initArgs []string, startArgs []string) *harness.Node { + node := harness.NewT(t).NewNode().Init(initArgs...).StartDaemon(startArgs...) + r, err := os.Open(fixturePath) + require.Nil(t, err) + defer r.Close() + err = node.IPFSDagImport(r, fixtureCid) + require.NoError(t, err) + return node + } + + testPublishingWithSelf := func(keyType string) { + t.Run("Publishing with self (keyType = "+keyType+")", func(t *testing.T) { + t.Parallel() + + args := []string{} + if keyType != "default" { + args = append(args, "-a="+keyType) + } + + node := makeDaemon(t, args, nil) + + t.Run("Publishing a CID", func(t *testing.T) { + name := ipns.NameFromPeer(node.PeerID()) + publishPath := "/ipfs/" + fixtureCid + + res := node.IPFS("name", "publish", "--allow-offline", publishPath) + require.Equal(t, fmt.Sprintf("Published to %s: %s\n", name.String(), publishPath), res.Stdout.String()) + + res = node.IPFS("name", "resolve", "/ipns/"+name.String()) + require.Equal(t, publishPath+"\n", res.Stdout.String()) + }) + + t.Run("Publishing a CID with -Q option", func(t *testing.T) { + name := ipns.NameFromPeer(node.PeerID()) + publishPath := "/ipfs/" + fixtureCid + + res := node.IPFS("name", "publish", "--allow-offline", "-Q", publishPath) + require.Equal(t, name.String()+"\n", res.Stdout.String()) + + res = node.IPFS("name", "resolve", "/ipns/"+name.String()) + require.Equal(t, publishPath+"\n", res.Stdout.String()) + }) + + t.Run("Publishing a CID+Path", func(t *testing.T) { + name := ipns.NameFromPeer(node.PeerID()) + publishPath := "/ipfs/" + fixtureCid + "/hello" + + res := node.IPFS("name", "publish", "--allow-offline", publishPath) + require.Equal(t, fmt.Sprintf("Published to %s: %s\n", name.String(), publishPath), res.Stdout.String()) + + res = node.IPFS("name", "resolve", "/ipns/"+name.String()) + require.Equal(t, publishPath+"\n", res.Stdout.String()) + }) + + t.Run("Publishing Nothing Fails", func(t *testing.T) { + res := node.RunIPFS("name", "publish") + require.Error(t, res.Err) + require.Equal(t, 1, res.ExitCode()) + require.Contains(t, res.Stderr.String(), `argument "ipfs-path" is required`) + }) + }) + } + + testPublishingWithSelf("default") + testPublishingWithSelf("rsa") + testPublishingWithSelf("ed25519") + + testPublishWithKey := func(name string, keyArgs ...string) { + t.Run(name, func(t *testing.T) { + t.Parallel() + node := makeDaemon(t, nil, nil) + + keyGenArgs := []string{"key", "gen"} + keyGenArgs = append(keyGenArgs, keyArgs...) + keyGenArgs = append(keyGenArgs, "key") + + res := node.IPFS(keyGenArgs...) + key := strings.TrimSpace(res.Stdout.String()) + + publishPath := "/ipfs/" + fixtureCid + name, err := ipns.NameFromString(key) + require.NoError(t, err) + + res = node.IPFS("name", "publish", "--allow-offline", "--key="+key, publishPath) + require.Equal(t, fmt.Sprintf("Published to %s: %s\n", name.String(), publishPath), res.Stdout.String()) + }) + } + + testPublishWithKey("Publishing with RSA (with b58mh) Key", "--ipns-base=b58mh", "--type=rsa", "--size=2048") + testPublishWithKey("Publishing with ED25519 (with b58mh) Key", "--ipns-base=b58mh", "--type=ed25519") + testPublishWithKey("Publishing with ED25519 (with base36) Key", "--ipns-base=base36", "--type=ed25519") + + t.Run("Inspect with verification using wrong RSA key errors", func(t *testing.T) { + t.Parallel() + node := makeDaemon(t, nil, nil) + + // Prepare RSA Key 1 + res := node.IPFS("key", "gen", "--type=rsa", "--size=4096", "key1") + key1 := strings.TrimSpace(res.Stdout.String()) + name1, err := ipns.NameFromString(key1) + require.NoError(t, err) + + // Prepare RSA Key 2 + res = node.IPFS("key", "gen", "--type=rsa", "--size=4096", "key2") + key2 := strings.TrimSpace(res.Stdout.String()) + name2, err := ipns.NameFromString(key2) + require.NoError(t, err) + + // Publish using Key 1 + publishPath := "/ipfs/" + fixtureCid + res = node.IPFS("name", "publish", "--allow-offline", "--key="+key1, publishPath) + require.Equal(t, fmt.Sprintf("Published to %s: %s\n", name1.String(), publishPath), res.Stdout.String()) + + // Get IPNS Record + res = node.IPFS("routing", "get", ipns.NamespacePrefix+name1.String()) + record := res.Stdout.Bytes() + + // Validate with correct key succeeds + res = node.PipeToIPFS(bytes.NewReader(record), "name", "inspect", "--verify="+name1.String(), "--enc=json") + val := name.IpnsInspectResult{} + err = json.Unmarshal(res.Stdout.Bytes(), &val) + require.NoError(t, err) + require.True(t, val.Validation.Valid) + + // Validate with wrong key fails + res = node.PipeToIPFS(bytes.NewReader(record), "name", "inspect", "--verify="+name2.String(), "--enc=json") + val = name.IpnsInspectResult{} + err = json.Unmarshal(res.Stdout.Bytes(), &val) + require.NoError(t, err) + require.False(t, val.Validation.Valid) + }) +} diff --git a/test/dependencies/go.mod b/test/dependencies/go.mod index c13927f65ab4..9a29b4d73f91 100644 --- a/test/dependencies/go.mod +++ b/test/dependencies/go.mod @@ -7,7 +7,7 @@ replace github.com/ipfs/kubo => ../../ require ( github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd github.com/golangci/golangci-lint v1.49.0 - github.com/ipfs/boxo v0.10.1-0.20230615083040-d5e141ea82cd + github.com/ipfs/boxo v0.10.1-0.20230615091437-c5a71fad393d github.com/ipfs/go-cid v0.4.1 github.com/ipfs/go-cidutil v0.1.0 github.com/ipfs/go-datastore v0.6.0 diff --git a/test/dependencies/go.sum b/test/dependencies/go.sum index f66363e82f94..266522ed1dd6 100644 --- a/test/dependencies/go.sum +++ b/test/dependencies/go.sum @@ -412,8 +412,8 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/boxo v0.10.1-0.20230615083040-d5e141ea82cd h1:mR5STWmJw1n+JZ2t7Jx0vPxp+iL9vuAM4RFxoqFyww0= -github.com/ipfs/boxo v0.10.1-0.20230615083040-d5e141ea82cd/go.mod h1:IwBbXi5P7fA0HzLhsw/FtAj9RAMacODuOCPPsBcvqcE= +github.com/ipfs/boxo v0.10.1-0.20230615091437-c5a71fad393d h1:vgxYdy3FL2y/oBFpoioPImg3QccT7Y03fyCxfIhm3HY= +github.com/ipfs/boxo v0.10.1-0.20230615091437-c5a71fad393d/go.mod h1:IwBbXi5P7fA0HzLhsw/FtAj9RAMacODuOCPPsBcvqcE= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo= diff --git a/test/sharness/t0100-name.sh b/test/sharness/t0100-name.sh index cb39e45c8abe..097aa0fcfd00 100755 --- a/test/sharness/t0100-name.sh +++ b/test/sharness/t0100-name.sh @@ -28,83 +28,8 @@ test_name_with_self() { test_check_peerid "${PEERID}" ' - # test publishing a hash - test_expect_success "'ipfs name publish --allow-offline' succeeds" ' - ipfs name publish --allow-offline "/ipfs/$HASH_WELCOME_DOCS" >publish_out - ' - - test_expect_success "publish output looks good" ' - echo "Published to ${PEERID}: /ipfs/$HASH_WELCOME_DOCS" >expected1 && - test_cmp expected1 publish_out - ' - - test_expect_success "'ipfs name resolve' succeeds" ' - ipfs name resolve "$PEERID" >output - ' - - test_expect_success "resolve output looks good" ' - printf "/ipfs/%s\n" "$HASH_WELCOME_DOCS" >expected2 && - test_cmp expected2 output - ' - - # test publishing with -Q option - - test_expect_success "'ipfs name publish --quieter' succeeds" ' - ipfs name publish --allow-offline -Q "/ipfs/$HASH_WELCOME_DOCS" >publish_out - ' - - test_expect_success "publish --quieter output looks good" ' - echo "${PEERID}" >expected1 && - test_cmp expected1 publish_out - ' - - test_expect_success "'ipfs name resolve' succeeds" ' - ipfs name resolve "$PEERID" >output - ' - - test_expect_success "resolve output looks good" ' - printf "/ipfs/%s\n" "$HASH_WELCOME_DOCS" >expected2 && - test_cmp expected2 output - ' - - # now test with a path - - test_expect_success "'ipfs name publish --allow-offline' succeeds" ' - ipfs name publish --allow-offline "/ipfs/$HASH_WELCOME_DOCS/help" >publish_out - ' - - test_expect_success "publish a path looks good" ' - echo "Published to ${PEERID}: /ipfs/$HASH_WELCOME_DOCS/help" >expected3 && - test_cmp expected3 publish_out - ' - - test_expect_success "'ipfs name resolve' succeeds" ' - ipfs name resolve "$PEERID" >output - ' - - test_expect_success "resolve output looks good" ' - printf "/ipfs/%s/help\n" "$HASH_WELCOME_DOCS" >expected4 && - test_cmp expected4 output - ' - - test_expect_success "ipfs cat on published content succeeds" ' - ipfs cat "/ipfs/$HASH_WELCOME_DOCS/help" >expected && - ipfs cat "/ipns/$PEERID" >actual && - test_cmp expected actual - ' - - # publish with an explicit node ID - - test_expect_failure "'ipfs name publish --allow-offline ' succeeds" ' - echo ipfs name publish --allow-offline "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" && - ipfs name publish --allow-offline "${PEERID}" "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish - ' - - test_expect_failure "publish with our explicit node ID looks good" ' - echo "Published to ${PEERID}: /ipfs/$HASH_WELCOME_DOCS" >expected_node_id_publish && - test_cmp expected_node_id_publish actual_node_id_publish - ' + # test publishing with B36CID and B58MH resolve to the same B36CID @@ -164,28 +89,6 @@ test_name_with_self() { test_cmp expected4 output ' - # test publishing nothing - - test_expect_success "'ipfs name publish' fails" ' - printf '' | test_expect_code 1 ipfs name publish --allow-offline >publish_out 2>&1 - ' - - test_expect_success "publish output has the correct error" ' - grep "argument \"ipfs-path\" is required" publish_out - ' - - test_expect_success "'ipfs name publish' fails" ' - printf '' | test_expect_code 1 ipfs name publish -Q --allow-offline >publish_out 2>&1 - ' - - test_expect_success "publish output has the correct error" ' - grep "argument \"ipfs-path\" is required" publish_out - ' - - test_expect_success "'ipfs name publish --help' succeeds" ' - ipfs name publish --help - ' - # test offline resolve test_expect_success "'ipfs name resolve --offline' succeeds" ' @@ -270,78 +173,4 @@ test_name_with_self 'default' test_name_with_self 'rsa' test_name_with_self 'ed25519' -test_name_with_key() { - GEN_ALG=$1 - - test_expect_success "ipfs init (key variant $GEN_ALG)" ' - export IPFS_PATH="$(pwd)/.ipfs" && - ipfs init --empty-repo=false --profile=test > /dev/null - ' - - test_expect_success "'prepare keys" ' - case $GEN_ALG in - rsa) - export KEY=`ipfs key gen --ipns-base=b58mh --type=rsa --size=2048 key` && - export KEY_B36CID=`ipfs key list --ipns-base=base36 -l | grep key | cut -d " " -f1` - ;; - ed25519_b58) - export KEY=`ipfs key gen --ipns-base=b58mh --type=ed25519 key` - export KEY_B36CID=`ipfs key list --ipns-base=base36 -l | grep key | cut -d " " -f1` - ;; - ed25519_b36) - export KEY=`ipfs key gen --ipns-base=base36 --type=ed25519 key` - export KEY_B36CID=$KEY - ;; - esac && - test_check_peerid "${KEY}" - ' - - # publish with an explicit node ID as key name - - test_expect_success "'ipfs name publish --allow-offline --key= ' succeeds" ' - ipfs name publish --allow-offline --key=${KEY} "/ipfs/$HASH_WELCOME_DOCS" >actual_node_id_publish - ' - - test_expect_success "publish an explicit node ID as key name looks good" ' - echo "Published to ${KEY_B36CID}: /ipfs/$HASH_WELCOME_DOCS" >expected_node_id_publish && - test_cmp expected_node_id_publish actual_node_id_publish - ' - - # cleanup - test_expect_success "clean up ipfs dir" ' - rm -rf "$IPFS_PATH" - ' -} -test_name_with_key 'rsa' -test_name_with_key 'ed25519_b58' -test_name_with_key 'ed25519_b36' - - -# `ipfs name inspect --verify` using the wrong RSA key should not succeed - -test_init_ipfs --empty-repo=false -test_launch_ipfs_daemon - -test_expect_success "prepare RSA keys" ' - export KEY_1=`ipfs key gen --type=rsa --size=4096 key1` && - export KEY_2=`ipfs key gen --type=rsa --size=4096 key2` && - export PEERID_1=`ipfs key list --ipns-base=base36 -l | grep key1 | cut -d " " -f1` && - export PEERID_2=`ipfs key list --ipns-base=base36 -l | grep key2 | cut -d " " -f1` -' - -test_expect_success "ipfs name publish --allow-offline --key= ' succeeds" ' - ipfs name publish --allow-offline --key=${KEY_1} "/ipfs/$( echo "helloworld" | ipfs add --inline -q )" && - ipfs routing get "/ipns/$PEERID_1" > ipns_record -' - -test_expect_success "ipfs name inspect --verify' has '.Validation.Validity' set to 'true' with correct Peer ID" ' - ipfs name inspect --verify $PEERID_1 --enc json < ipns_record | jq -e ".Validation.Valid == true" -' - -test_expect_success "ipfs name inspect --verify' has '.Validation.Validity' set to 'false' when we verify the wrong Peer ID" ' - ipfs name inspect --verify $PEERID_2 --enc json < ipns_record | jq -e ".Validation.Valid == false" -' - -test_kill_ipfs_daemon - test_done