diff --git a/core/commands/keybase/keybase.go b/core/commands/keybase/keybase.go new file mode 100644 index 00000000000..b857c8dbb99 --- /dev/null +++ b/core/commands/keybase/keybase.go @@ -0,0 +1,35 @@ +package keybase + +import ( + peer "github.com/libp2p/go-libp2p-core/peer" + mbase "github.com/multiformats/go-multibase" +) + +type KeyEncoder struct { + baseEnc *mbase.Encoder +} + +func KeyEncoderFromString(formatLabel string) (KeyEncoder, error) { + switch formatLabel { + case "b58mh", "v0": + return KeyEncoder{}, nil + default: + if enc, err := mbase.EncoderByName(formatLabel); err != nil { + return KeyEncoder{}, err + } else { + return KeyEncoder{&enc}, nil + } + } +} + +func (enc KeyEncoder) FormatID(id peer.ID) string { + if enc.baseEnc == nil { + //nolint deprecated + return peer.IDB58Encode(id) + } + if s, err := peer.ToCid(id).StringOfBase(enc.baseEnc.Encoding()); err != nil { + panic(err) + } else { + return s + } +} diff --git a/core/commands/keystore.go b/core/commands/keystore.go index 9935c589496..f78bafa20bc 100644 --- a/core/commands/keystore.go +++ b/core/commands/keystore.go @@ -15,6 +15,7 @@ import ( oldcmds "github.com/ipfs/go-ipfs/commands" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" "github.com/ipfs/go-ipfs/core/commands/e" + kb "github.com/ipfs/go-ipfs/core/commands/keybase" fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" options "github.com/ipfs/interface-go-ipfs-core/options" "github.com/libp2p/go-libp2p-core/crypto" @@ -82,7 +83,7 @@ var keyGenCmd = &cmds.Command{ Options: []cmds.Option{ cmds.StringOption(keyStoreTypeOptionName, "t", "type of the key to create: rsa, ed25519").WithDefault(keyStoreAlgorithmDefault), cmds.IntOption(keyStoreSizeOptionName, "s", "size of the key to generate"), - cmds.StringOption(keyFormatOptionName, "", "output format: b58mh or b36cid").WithDefault("b36cid"), + cmds.StringOption(keyFormatOptionName, "", "Encoding used for keys: Can either be a multibase encoded CID or a base58btc encoded multihash. Takes {b58mh|base36|k|base32|b...}.").WithDefault("base36"), }, Arguments: []cmds.Argument{ cmds.StringArg("name", true, false, "name of key to create"), @@ -109,7 +110,8 @@ var keyGenCmd = &cmds.Command{ if sizefound { opts = append(opts, options.Key.Size(size)) } - if err = verifyIDFormatLabel(req.Options[keyFormatOptionName].(string)); err != nil { + keyEnc, err := kb.KeyEncoderFromString(req.Options[keyFormatOptionName].(string)) + if err != nil { return err } @@ -121,7 +123,7 @@ var keyGenCmd = &cmds.Command{ return cmds.EmitOnce(res, &KeyOutput{ Name: name, - Id: formatID(key.ID(), req.Options[keyFormatOptionName].(string)), + Id: keyEnc.FormatID(key.ID()), }) }, Encoders: cmds.EncoderMap{ @@ -223,7 +225,7 @@ var keyImportCmd = &cmds.Command{ Tagline: "Import a key and prints imported key id", }, Options: []cmds.Option{ - cmds.StringOption(keyFormatOptionName, "", "output format: b58mh or b36cid").WithDefault("b58mh"), + cmds.StringOption(keyFormatOptionName, "", "Encoding used for keys: Can either be a multibase encoded CID or a base58btc encoded multihash. Takes {b58mh|base36|k|base32|b...}.").WithDefault("base36"), }, Arguments: []cmds.Argument{ cmds.StringArg("name", true, false, "name to associate with key in keychain"), @@ -236,6 +238,11 @@ var keyImportCmd = &cmds.Command{ return fmt.Errorf("cannot import key with name 'self'") } + keyEnc, err := kb.KeyEncoderFromString(req.Options[keyFormatOptionName].(string)) + if err != nil { + return err + } + file, err := cmdenv.GetFileArg(req.Files.Entries()) if err != nil { return err @@ -280,7 +287,7 @@ var keyImportCmd = &cmds.Command{ return cmds.EmitOnce(res, &KeyOutput{ Name: name, - Id: formatID(pid, req.Options[keyFormatOptionName].(string)), + Id: keyEnc.FormatID(pid), }) }, Encoders: cmds.EncoderMap{ @@ -298,10 +305,11 @@ var keyListCmd = &cmds.Command{ }, Options: []cmds.Option{ cmds.BoolOption("l", "Show extra information about keys."), - cmds.StringOption(keyFormatOptionName, "", "output format: b58mh or b36cid").WithDefault("b36cid"), + cmds.StringOption(keyFormatOptionName, "", "Encoding used for keys: Can either be a multibase encoded CID or a base58btc encoded multihash. Takes {b58mh|base36|k|base32|b...}.").WithDefault("base36"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - if err := verifyIDFormatLabel(req.Options[keyFormatOptionName].(string)); err != nil { + keyEnc, err := kb.KeyEncoderFromString(req.Options[keyFormatOptionName].(string)) + if err != nil { return err } @@ -320,7 +328,7 @@ var keyListCmd = &cmds.Command{ for _, key := range keys { list = append(list, KeyOutput{ Name: key.Name(), - Id: formatID(key.ID(), req.Options[keyFormatOptionName].(string)), + Id: keyEnc.FormatID(key.ID()), }) } @@ -346,14 +354,15 @@ var keyRenameCmd = &cmds.Command{ }, Options: []cmds.Option{ cmds.BoolOption(keyStoreForceOptionName, "f", "Allow to overwrite an existing key."), - cmds.StringOption(keyFormatOptionName, "", "output format: b58mh or b36cid").WithDefault("b36cid"), + cmds.StringOption(keyFormatOptionName, "", "Encoding used for keys: Can either be a multibase encoded CID or a base58btc encoded multihash. Takes {b58mh|base36|k|base32|b...}.").WithDefault("base36"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) if err != nil { return err } - if err = verifyIDFormatLabel(req.Options[keyFormatOptionName].(string)); err != nil { + keyEnc, err := kb.KeyEncoderFromString(req.Options[keyFormatOptionName].(string)) + if err != nil { return err } @@ -369,7 +378,7 @@ var keyRenameCmd = &cmds.Command{ return cmds.EmitOnce(res, &KeyRenameOutput{ Was: name, Now: newName, - Id: formatID(key.ID(), req.Options[keyFormatOptionName].(string)), // key.ID().Pretty(), + Id: keyEnc.FormatID(key.ID()), Overwrite: overwritten, }) }, @@ -395,14 +404,15 @@ var keyRmCmd = &cmds.Command{ }, Options: []cmds.Option{ cmds.BoolOption("l", "Show extra information about keys."), - cmds.StringOption(keyFormatOptionName, "", "output format: b58mh or b36cid").WithDefault("b36cid"), + cmds.StringOption(keyFormatOptionName, "", "Encoding used for keys: Can either be a multibase encoded CID or a base58btc encoded multihash. Takes {b58mh|base36|k|base32|b...}.").WithDefault("base36"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) if err != nil { return err } - if err = verifyIDFormatLabel(req.Options[keyFormatOptionName].(string)); err != nil { + keyEnc, err := kb.KeyEncoderFromString(req.Options[keyFormatOptionName].(string)) + if err != nil { return err } @@ -417,7 +427,7 @@ var keyRmCmd = &cmds.Command{ list = append(list, KeyOutput{ Name: name, - Id: formatID(key.ID(), req.Options[keyFormatOptionName].(string)), + Id: keyEnc.FormatID(key.ID()), }) } @@ -530,26 +540,36 @@ func doRotate(out io.Writer, repoRoot string, oldKey string, algorithm string, n func verifyIDFormatLabel(formatLabel string) error { switch formatLabel { - case "b58mh": - return nil - case "b36cid": + case "b58mh", "v0": return nil + default: + _, err := mbase.EncoderByName(formatLabel) + return err } - return fmt.Errorf("invalid output format option") } -func formatID(id peer.ID, formatLabel string) string { +func keyEncoderFromString(formatLabel string) (keyEncoder, error) { switch formatLabel { - case "b58mh": - return id.Pretty() - case "b36cid": - if s, err := peer.ToCid(id).StringOfBase(mbase.Base36); err != nil { - panic(err) + case "b58mh", "v0": + return keyEncoder{}, nil + default: + if enc, err := mbase.EncoderByName(formatLabel); err != nil { + return keyEncoder{}, err } else { - return s + return keyEncoder{&enc}, nil } - default: - panic("unreachable") + } +} + +func (enc keyEncoder) FormatID(id peer.ID) string { + if enc.baseEnc == nil { + //nolint deprecated + return peer.IDB58Encode(id) + } + if s, err := peer.ToCid(id).StringOfBase(enc.baseEnc.Encoding()); err != nil { + panic(err) + } else { + return s } } diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh index 6eac7a2e189..e67f56d4b4a 100644 --- a/test/sharness/lib/test-lib.sh +++ b/test/sharness/lib/test-lib.sh @@ -445,8 +445,8 @@ file_size() { # len 46: 2048-bit RSA keys, b58mh-encoded # len 52: ED25519 keys, b58mh-encoded -# len 56: 2048-bit RSA keys, b36cid-encoded -# len 62: ED25519 keys, b36cid-encoded +# len 56: 2048-bit RSA keys, base36-encoded +# len 62: ED25519 keys, base36-encoded test_check_peerid() { peeridlen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && test "$peeridlen" = "46" -o "$peeridlen" = "52" -o "$peeridlen" = "56" -o "$peeridlen" = "62" || { @@ -471,7 +471,7 @@ test_check_ed25519_b58mh_peerid() { } } -test_check_rsa2048_b36cid_peerid() { +test_check_rsa2048_base36_peerid() { peeridlen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && test "$peeridlen" = "56" || { echo "Bad RSA2048 B36CID peerid '$1' with len '$peeridlen'" @@ -479,7 +479,7 @@ test_check_rsa2048_b36cid_peerid() { } } -test_check_ed25519_b36cid_peerid() { +test_check_ed25519_base36_peerid() { peeridlen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && test "$peeridlen" = "62" || { echo "Bad ED25519 B36CID peerid '$1' with len '$peeridlen'" diff --git a/test/sharness/t0100-name.sh b/test/sharness/t0100-name.sh index e617d5070a9..9b7a60cd40e 100755 --- a/test/sharness/t0100-name.sh +++ b/test/sharness/t0100-name.sh @@ -24,7 +24,7 @@ test_name_with_self() { ipfs init --profile=test -a=ed25519 > /dev/null ;; esac && - export PEERID=`ipfs key list --ipns-base=b36cid -l | grep self | cut -d " " -f1` && + export PEERID=`ipfs key list --ipns-base=base36 -l | grep self | cut -d " " -f1` && test_check_peerid "${PEERID}" ' @@ -110,20 +110,20 @@ test_name_with_self() { test_expect_success "verify self key output" ' B58MH_ID=`ipfs key list --ipns-base=b58mh -l | grep self | cut -d " " -f1` && - B36CID_ID=`ipfs key list --ipns-base=b36cid -l | grep self | cut -d " " -f1` && + B36CID_ID=`ipfs key list --ipns-base=base36 -l | grep self | cut -d " " -f1` && test_check_peerid "${B58MH_ID}" && test_check_peerid "${B36CID_ID}" ' test_expect_success "'ipfs name publish --allow-offline --key= ' succeeds" ' ipfs name publish --allow-offline --key=${B58MH_ID} "/ipfs/$HASH_WELCOME_DOCS" >b58mh_published_id && - ipfs name publish --allow-offline --key=${B36CID_ID} "/ipfs/$HASH_WELCOME_DOCS" >b36cid_published_id + ipfs name publish --allow-offline --key=${B36CID_ID} "/ipfs/$HASH_WELCOME_DOCS" >base36_published_id ' test_expect_success "publish an explicit node ID as two key in B58MH and B36CID, name looks good" ' echo "Published to ${B36CID_ID}: /ipfs/$HASH_WELCOME_DOCS" >expected_published_id && test_cmp expected_published_id b58mh_published_id && - test_cmp expected_published_id b36cid_published_id + test_cmp expected_published_id base36_published_id ' test_expect_success "'ipfs name resolve' succeeds" ' @@ -251,14 +251,14 @@ test_name_with_key() { 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=b36cid -l | grep key | cut -d " " -f1` + 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=b36cid -l | grep key | cut -d " " -f1` + export KEY_B36CID=`ipfs key list --ipns-base=base36 -l | grep key | cut -d " " -f1` ;; ed25519_b36) - export KEY=`ipfs key gen --ipns-base=b36cid --type=ed25519 key` + export KEY=`ipfs key gen --ipns-base=base36 --type=ed25519 key` export KEY_B36CID=$KEY ;; esac && diff --git a/test/sharness/t0114-gateway-subdomains.sh b/test/sharness/t0114-gateway-subdomains.sh index 8d94eb9c483..19a040b5124 100755 --- a/test/sharness/t0114-gateway-subdomains.sh +++ b/test/sharness/t0114-gateway-subdomains.sh @@ -127,7 +127,7 @@ test_expect_success "Publish test text file to IPNS using RSA keys" ' test_expect_success "Publish test text file to IPNS using ED25519 keys" ' ED25519_KEY=$(ipfs key gen --ipns-base=b58mh --type=ed25519 test_key_ed25519 | head -n1 | tr -d "\n") ED25519_IPNS_IDv0=$ED25519_KEY - ED25519_IPNS_IDv1=$(ipfs key list -l --ipns-base=b36cid | grep test_key_ed25519 | cut -d " " -f1 | tr -d "\n") + ED25519_IPNS_IDv1=$(ipfs key list -l --ipns-base=base36 | grep test_key_ed25519 | cut -d " " -f1 | tr -d "\n") ED25519_IPNS_IDv1_DAGPB=$(echo "$ED25519_IPNS_IDv1" | ipfs cid format -v 1 -b base36 --codec protobuf) test_check_peerid "${ED25519_KEY}" && ipfs name publish --key test_key_ed25519 --allow-offline -Q "/ipfs/$CIDv1" > name_publish_out && diff --git a/test/sharness/t0160-resolve.sh b/test/sharness/t0160-resolve.sh index 4f67ac5a900..b460bae7f0a 100755 --- a/test/sharness/t0160-resolve.sh +++ b/test/sharness/t0160-resolve.sh @@ -22,10 +22,8 @@ test_expect_success "resolve: prepare dag" ' ' test_expect_success "resolve: prepare keys" ' - self_hash=$(ipfs key list --ipns-base=b36cid -l | grep self | cut -d " " -f1) && - alt_hash=$(ipfs key gen --ipns-base=b36cid -t rsa alt) - echo self_hash $self_hash - echo $(ipfs id -f="") + self_hash=$(ipfs key list --ipns-base=base36 -l | grep self | cut -d " " -f1) && + alt_hash=$(ipfs key gen --ipns-base=base36 -t rsa alt) ' test_resolve_setup_name() { diff --git a/test/sharness/t0165-keystore.sh b/test/sharness/t0165-keystore.sh index 5aafd9fb608..e981162f350 100755 --- a/test/sharness/t0165-keystore.sh +++ b/test/sharness/t0165-keystore.sh @@ -16,8 +16,8 @@ test_expect_success "create an RSA key and test B58MH/B36CID output formats" ' PEERID=$(ipfs key gen --ipns-base=b58mh --type=rsa --size=2048 key_rsa) && test_check_rsa2048_b58mh_peerid $PEERID && ipfs key rm key_rsa && -PEERID=$(ipfs key gen --ipns-base=b36cid --type=rsa --size=2048 key_rsa) && -test_check_rsa2048_b36cid_peerid $PEERID +PEERID=$(ipfs key gen --ipns-base=base36 --type=rsa --size=2048 key_rsa) && +test_check_rsa2048_base36_peerid $PEERID ' test_expect_success "test RSA key sk export format" ' @@ -29,8 +29,8 @@ rm key_rsa.key test_expect_success "test RSA key B58MH/B36CID multihash format" ' PEERID=$(ipfs key list --ipns-base=b58mh -l | grep key_rsa | head -n 1 | cut -d " " -f1) && test_check_rsa2048_b58mh_peerid $PEERID && -PEERID=$(ipfs key list --ipns-base=b36cid -l | grep key_rsa | head -n 1 | cut -d " " -f1) && -test_check_rsa2048_b36cid_peerid $PEERID && +PEERID=$(ipfs key list --ipns-base=base36 -l | grep key_rsa | head -n 1 | cut -d " " -f1) && +test_check_rsa2048_base36_peerid $PEERID && ipfs key rm key_rsa ' @@ -38,8 +38,8 @@ test_expect_success "create an ED25519 key and test B58MH/B36CID output formats" PEERID=$(ipfs key gen --ipns-base=b58mh --type=ed25519 key_ed25519) && test_check_ed25519_b58mh_peerid $PEERID && ipfs key rm key_ed25519 && -PEERID=$(ipfs key gen --ipns-base=b36cid --type=ed25519 key_ed25519) && -test_check_ed25519_b36cid_peerid $PEERID +PEERID=$(ipfs key gen --ipns-base=base36 --type=ed25519 key_ed25519) && +test_check_ed25519_base36_peerid $PEERID ' test_expect_success "test ED25519 key sk export format" ' @@ -51,8 +51,8 @@ rm key_ed25519.key test_expect_success "test ED25519 key B58MH/B36CID multihash format" ' PEERID=$(ipfs key list --ipns-base=b58mh -l | grep key_ed25519 | head -n 1 | cut -d " " -f1) && test_check_ed25519_b58mh_peerid $PEERID && -PEERID=$(ipfs key list --ipns-base=b36cid -l | grep key_ed25519 | head -n 1 | cut -d " " -f1) && -test_check_ed25519_b36cid_peerid $PEERID && +PEERID=$(ipfs key list --ipns-base=base36 -l | grep key_ed25519 | head -n 1 | cut -d " " -f1) && +test_check_ed25519_base36_peerid $PEERID && ipfs key rm key_ed25519 ' # end of format test diff --git a/test/sharness/t0600-issues-and-regressions-online.sh b/test/sharness/t0600-issues-and-regressions-online.sh index 07b90f7562a..93f51caeecb 100755 --- a/test/sharness/t0600-issues-and-regressions-online.sh +++ b/test/sharness/t0600-issues-and-regressions-online.sh @@ -62,7 +62,7 @@ test_expect_success "ipfs daemon --offline --mount fails - #2995" ' test_launch_ipfs_daemon --offline test_expect_success "'ipfs name resolve' succeeds after ipfs id when daemon offline" ' - PEERID=`ipfs key list --ipns-base=b36cid -l | grep self | cut -d " " -f1` && + PEERID=`ipfs key list --ipns-base=base36 -l | grep self | cut -d " " -f1` && test_check_peerid "${PEERID}" && ipfs name publish --allow-offline -Q "/ipfs/$HASH_WELCOME_DOCS" >publish_out '