Skip to content

Commit

Permalink
Merge pull request #7582 from ipfs/petar/keys
Browse files Browse the repository at this point in the history
use b36 keys by default for keys and IPNS
  • Loading branch information
aschmahmann authored Aug 18, 2020
2 parents 8ae5aa5 + 4975d9b commit c7a24a3
Show file tree
Hide file tree
Showing 15 changed files with 197 additions and 126 deletions.
37 changes: 37 additions & 0 deletions core/commands/keyencode/keyencode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package keyencode

import (
peer "github.com/libp2p/go-libp2p-core/peer"
mbase "github.com/multiformats/go-multibase"
)

const IPNSKeyFormatOptionName = "ipns-base"

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
}
}
76 changes: 35 additions & 41 deletions core/commands/keystore.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ 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"
ke "github.com/ipfs/go-ipfs/core/commands/keyencode"
fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
options "github.com/ipfs/interface-go-ipfs-core/options"
"github.com/libp2p/go-libp2p-core/crypto"
peer "github.com/libp2p/go-libp2p-core/peer"
mbase "github.com/multiformats/go-multibase"
)

var KeyCmd = &cmds.Command{
Expand Down Expand Up @@ -68,11 +68,10 @@ type KeyRenameOutput struct {
}

const (
keyStoreAlgorithmDefault = options.RSAKey
keyStoreTypeOptionName = "type"
keyStoreSizeOptionName = "size"
keyFormatOptionName = "format"
oldKeyOptionName = "oldkey"
keyStoreAlgorithmDefault = options.RSAKey
keyStoreTypeOptionName = "type"
keyStoreSizeOptionName = "size"
oldKeyOptionName = "oldkey"
)

var keyGenCmd = &cmds.Command{
Expand All @@ -82,7 +81,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, "f", "output format: b58mh or b36cid").WithDefault("b58mh"),
cmds.StringOption(ke.IPNSKeyFormatOptionName, "", "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"),
Expand All @@ -109,7 +108,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 := ke.KeyEncoderFromString(req.Options[ke.IPNSKeyFormatOptionName].(string))
if err != nil {
return err
}

Expand All @@ -121,7 +121,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{
Expand Down Expand Up @@ -223,7 +223,7 @@ var keyImportCmd = &cmds.Command{
Tagline: "Import a key and prints imported key id",
},
Options: []cmds.Option{
cmds.StringOption(keyFormatOptionName, "f", "output format: b58mh or b36cid").WithDefault("b58mh"),
cmds.StringOption(ke.IPNSKeyFormatOptionName, "", "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"),
Expand All @@ -236,6 +236,11 @@ var keyImportCmd = &cmds.Command{
return fmt.Errorf("cannot import key with name 'self'")
}

keyEnc, err := ke.KeyEncoderFromString(req.Options[ke.IPNSKeyFormatOptionName].(string))
if err != nil {
return err
}

file, err := cmdenv.GetFileArg(req.Files.Entries())
if err != nil {
return err
Expand Down Expand Up @@ -280,7 +285,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{
Expand All @@ -298,10 +303,11 @@ var keyListCmd = &cmds.Command{
},
Options: []cmds.Option{
cmds.BoolOption("l", "Show extra information about keys."),
cmds.StringOption(keyFormatOptionName, "f", "output format: b58mh or b36cid").WithDefault("b58mh"),
cmds.StringOption(ke.IPNSKeyFormatOptionName, "", "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 := ke.KeyEncoderFromString(req.Options[ke.IPNSKeyFormatOptionName].(string))
if err != nil {
return err
}

Expand All @@ -320,7 +326,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()),
})
}

Expand All @@ -346,12 +352,17 @@ var keyRenameCmd = &cmds.Command{
},
Options: []cmds.Option{
cmds.BoolOption(keyStoreForceOptionName, "f", "Allow to overwrite an existing key."),
cmds.StringOption(ke.IPNSKeyFormatOptionName, "", "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
}
keyEnc, err := ke.KeyEncoderFromString(req.Options[ke.IPNSKeyFormatOptionName].(string))
if err != nil {
return err
}

name := req.Arguments[0]
newName := req.Arguments[1]
Expand All @@ -365,7 +376,7 @@ var keyRenameCmd = &cmds.Command{
return cmds.EmitOnce(res, &KeyRenameOutput{
Was: name,
Now: newName,
Id: key.ID().Pretty(),
Id: keyEnc.FormatID(key.ID()),
Overwrite: overwritten,
})
},
Expand All @@ -391,12 +402,17 @@ var keyRmCmd = &cmds.Command{
},
Options: []cmds.Option{
cmds.BoolOption("l", "Show extra information about keys."),
cmds.StringOption(ke.IPNSKeyFormatOptionName, "", "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
}
keyEnc, err := ke.KeyEncoderFromString(req.Options[ke.IPNSKeyFormatOptionName].(string))
if err != nil {
return err
}

names := req.Arguments

Expand All @@ -407,7 +423,10 @@ var keyRmCmd = &cmds.Command{
return err
}

list = append(list, KeyOutput{Name: name, Id: key.ID().Pretty()})
list = append(list, KeyOutput{
Name: name,
Id: keyEnc.FormatID(key.ID()),
})
}

return cmds.EmitOnce(res, &KeyOutputList{list})
Expand Down Expand Up @@ -517,31 +536,6 @@ func doRotate(out io.Writer, repoRoot string, oldKey string, algorithm string, n
return nil
}

func verifyIDFormatLabel(formatLabel string) error {
switch formatLabel {
case "b58mh":
return nil
case "b36cid":
return nil
}
return fmt.Errorf("invalid output format option")
}

func formatID(id peer.ID, formatLabel string) string {
switch formatLabel {
case "b58mh":
return id.Pretty()
case "b36cid":
if s, err := peer.ToCid(id).StringOfBase(mbase.Base36); err != nil {
panic(err)
} else {
return s
}
default:
panic("unreachable")
}
}

func keyOutputListEncoders() cmds.EncoderFunc {
return cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, list *KeyOutputList) error {
withID, _ := req.Options["l"].(bool)
Expand Down
15 changes: 12 additions & 3 deletions core/commands/name/ipnsps.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import (
"io"
"strings"

"github.com/ipfs/go-ipfs-cmds"
cmds "github.com/ipfs/go-ipfs-cmds"
"github.com/ipfs/go-ipfs/core/commands/cmdenv"
ke "github.com/ipfs/go-ipfs/core/commands/keyencode"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-record"
record "github.com/libp2p/go-libp2p-record"
)

type ipnsPubsubState struct {
Expand Down Expand Up @@ -72,7 +73,15 @@ var ipnspsSubsCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Show current name subscriptions",
},
Options: []cmds.Option{
cmds.StringOption(ke.IPNSKeyFormatOptionName, "", "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 {
keyEnc, err := ke.KeyEncoderFromString(req.Options[ke.IPNSKeyFormatOptionName].(string))
if err != nil {
return err
}

n, err := cmdenv.GetNode(env)
if err != nil {
return err
Expand All @@ -93,7 +102,7 @@ var ipnspsSubsCmd = &cmds.Command{
log.Errorf("ipns key not a valid peer ID: %s", err)
continue
}
paths = append(paths, "/ipns/"+peer.Encode(pid))
paths = append(paths, "/ipns/"+keyEnc.FormatID(pid))
}

return cmds.EmitOnce(res, &stringList{paths})
Expand Down
15 changes: 14 additions & 1 deletion core/commands/name/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import (
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"

cmds "github.com/ipfs/go-ipfs-cmds"
ke "github.com/ipfs/go-ipfs/core/commands/keyencode"
iface "github.com/ipfs/interface-go-ipfs-core"
options "github.com/ipfs/interface-go-ipfs-core/options"
path "github.com/ipfs/interface-go-ipfs-core/path"
peer "github.com/libp2p/go-libp2p-core/peer"
)

var (
Expand Down Expand Up @@ -81,12 +83,17 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
cmds.StringOption(ttlOptionName, "Time duration this record should be cached for. Uses the same syntax as the lifetime option. (caution: experimental)"),
cmds.StringOption(keyOptionName, "k", "Name of the key to be used or a valid PeerID, as listed by 'ipfs key list -l'.").WithDefault("self"),
cmds.BoolOption(quieterOptionName, "Q", "Write only final hash."),
cmds.StringOption(ke.IPNSKeyFormatOptionName, "", "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
}
keyEnc, err := ke.KeyEncoderFromString(req.Options[ke.IPNSKeyFormatOptionName].(string))
if err != nil {
return err
}

allowOffline, _ := req.Options[allowOfflineOptionName].(bool)
kname, _ := req.Options[keyOptionName].(string)
Expand Down Expand Up @@ -129,8 +136,14 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
return err
}

// parse path, extract cid, re-base cid, reconstruct path
pid, err := peer.Decode(out.Name())
if err != nil {
return err
}

return cmds.EmitOnce(res, &IpnsEntry{
Name: out.Name(),
Name: keyEnc.FormatID(pid),
Value: out.Value().String(),
})
},
Expand Down
34 changes: 17 additions & 17 deletions core/commands/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,23 +82,6 @@ Resolve the value of an IPFS DAG path:
name := req.Arguments[0]
recursive, _ := req.Options[resolveRecursiveOptionName].(bool)

var enc cidenc.Encoder
switch {
case !cmdenv.CidBaseDefined(req):
// Not specified, check the path.
enc, err = cmdenv.CidEncoderFromPath(name)
if err == nil {
break
}
// Nope, fallback on the default.
fallthrough
default:
enc, err = cmdenv.GetCidEncoder(req)
if err != nil {
return err
}
}

// the case when ipns is resolved step by step
if strings.HasPrefix(name, "/ipns/") && !recursive {
rc, rcok := req.Options[resolveDhtRecordCountOptionName].(uint)
Expand Down Expand Up @@ -128,6 +111,23 @@ Resolve the value of an IPFS DAG path:
return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: ipfspath.Path(p.String())})
}

var enc cidenc.Encoder
switch {
case !cmdenv.CidBaseDefined(req) && !strings.HasPrefix(name, "/ipns/"):
// Not specified, check the path.
enc, err = cmdenv.CidEncoderFromPath(name)
if err == nil {
break
}
// Nope, fallback on the default.
fallthrough
default:
enc, err = cmdenv.GetCidEncoder(req)
if err != nil {
return err
}
}

// else, ipfs path or ipns with recursive flag
rp, err := api.ResolvePath(req.Context, path.New(name))
if err != nil {
Expand Down
Loading

0 comments on commit c7a24a3

Please sign in to comment.