From a0656402ed9cb527aedee902b4e65f4cd63dfb7a Mon Sep 17 00:00:00 2001 From: rendaw <> Date: Thu, 16 Jul 2020 22:25:37 +0900 Subject: [PATCH 1/6] Key import and export cli commands --- core/commands/commands_test.go | 3 + core/commands/keystore.go | 279 +++++++++++++++++++++++++++++--- core/coreapi/key.go | 42 +++-- test/sharness/lib/test-lib.sh | 16 ++ test/sharness/t0165-keystore.sh | 35 +++- 5 files changed, 338 insertions(+), 37 deletions(-) diff --git a/core/commands/commands_test.go b/core/commands/commands_test.go index 940b9e0f43f..10b0bfa236b 100644 --- a/core/commands/commands_test.go +++ b/core/commands/commands_test.go @@ -133,6 +133,9 @@ func TestCommands(t *testing.T) { "/id", "/key", "/key/gen", + "/key/export", + "/key/import", + "/key/identify", "/key/list", "/key/rename", "/key/rm", diff --git a/core/commands/keystore.go b/core/commands/keystore.go index c9865fd93ee..ae90e43010e 100644 --- a/core/commands/keystore.go +++ b/core/commands/keystore.go @@ -7,8 +7,13 @@ import ( cmds "github.com/ipfs/go-ipfs-cmds" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" + "github.com/ipfs/go-ipfs/core/coreapi" + repo "github.com/ipfs/go-ipfs/repo" + 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" + "github.com/mr-tron/base58/base58" mbase "github.com/multiformats/go-multibase" ) @@ -30,10 +35,13 @@ publish'. `, }, Subcommands: map[string]*cmds.Command{ - "gen": keyGenCmd, - "list": keyListCmd, - "rename": keyRenameCmd, - "rm": keyRmCmd, + "gen": keyGenCmd, + "export": keyExportCmd, + "import": keyImportCmd, + "identify": keyIdentifyCmd, + "list": keyListCmd, + "rename": keyRenameCmd, + "rm": keyRmCmd, }, } @@ -42,6 +50,16 @@ type KeyOutput struct { Id string } +type GenerateKeyOutput struct { + Name string + Id string + Sk string +} + +type ExportKeyOutput struct { + Sk string +} + type KeyOutputList struct { Keys []KeyOutput } @@ -58,6 +76,8 @@ const ( keyStoreTypeOptionName = "type" keyStoreSizeOptionName = "size" keyFormatOptionName = "format" + keyExportOptionName = "export" + keyNoStoreOptionName = "no-store" ) var keyGenCmd = &cmds.Command{ @@ -68,24 +88,57 @@ var keyGenCmd = &cmds.Command{ cmds.StringOption(keyStoreTypeOptionName, "t", "type of the key to create: rsa, ed25519").WithDefault("rsa"), cmds.IntOption(keyStoreSizeOptionName, "s", "size of the key to generate"), cmds.StringOption(keyFormatOptionName, "f", "output format: b58mh or b36cid").WithDefault("b58mh"), + cmds.BoolOption(keyExportOptionName, "e", "return generated key for later re-import").WithDefault(false), + cmds.BoolOption(keyNoStoreOptionName, "n", "don't add the key to the keychain").WithDefault(false), }, Arguments: []cmds.Argument{ - cmds.StringArg("name", true, false, "name of key to create"), + cmds.StringArg("name", false, false, "name of key to create, required unless -n specified"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - api, err := cmdenv.GetApi(env, req) - if err != nil { - return err - } - typ, f := req.Options[keyStoreTypeOptionName].(string) if !f { return fmt.Errorf("please specify a key type with --type") } - name := req.Arguments[0] - if name == "self" { - return fmt.Errorf("cannot create key with name 'self'") + store := !req.Options[keyNoStoreOptionName].(bool) + export := req.Options[keyExportOptionName].(bool) + + var name string + var r repo.Repo = nil + defer func() { + if r != nil { + r.Close() + } + }() + if store { + if len(req.Arguments) == 0 { + return fmt.Errorf("you must specify a key name") + } + + name = req.Arguments[0] + + if name == "self" { + return fmt.Errorf("cannot create key with name 'self'") + } + + cfgRoot, err := cmdenv.GetConfigRoot(env) + if err != nil { + return err + } + + r, err = fsrepo.Open(cfgRoot) + if err != nil { + return err + } + + _, err = r.Keystore().Get(name) + if err == nil { + return fmt.Errorf("key with name '%s' already exists", name) + } + } + + if !store && !export { + return fmt.Errorf("you must export key if not storing") } opts := []options.KeyGenerateOption{options.Key.Type(typ)} @@ -94,28 +147,52 @@ var keyGenCmd = &cmds.Command{ if sizefound { opts = append(opts, options.Key.Size(size)) } - if err = verifyFormatLabel(req.Options[keyFormatOptionName].(string)); err != nil { + if err := verifyFormatLabel(req.Options[keyFormatOptionName].(string)); err != nil { return err } - key, err := api.Key().Generate(req.Context, name, opts...) + sk, pk, err := coreapi.GenerateKey(opts...) + if err != nil { + return err + } + + if store { + err = r.Keystore().Put(name, sk) + if err != nil { + return err + } + } + pid, err := peer.IDFromPublicKey(pk) if err != nil { return err } - return cmds.EmitOnce(res, &KeyOutput{ + var encoded string + if export { + encoded, err = encodeSKForExport(sk) + if err != nil { + return err + } + } + + return cmds.EmitOnce(res, &GenerateKeyOutput{ Name: name, - Id: formatID(key.ID(), req.Options[keyFormatOptionName].(string)), + Id: formatID(pid, req.Options[keyFormatOptionName].(string)), + Sk: encoded, }) }, Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, ko *KeyOutput) error { + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, ko *GenerateKeyOutput) error { + if ko.Sk != "" { + _, err := w.Write([]byte(ko.Sk + "\n")) + return err + } _, err := w.Write([]byte(ko.Id + "\n")) return err }), }, - Type: KeyOutput{}, + Type: GenerateKeyOutput{}, } func verifyFormatLabel(formatLabel string) error { @@ -143,6 +220,170 @@ func formatID(id peer.ID, formatLabel string) string { } } +func encodeSKForExport(sk crypto.PrivKey) (string, error) { + data, err := crypto.MarshalPrivateKey(sk) + if err != nil { + return "", err + } + return base58.Encode(data), nil +} + +var keyExportCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Export a keypair", + }, + Arguments: []cmds.Argument{ + cmds.StringArg("name", true, false, "name of key to export").EnableStdin(), + }, + Options: []cmds.Option{}, + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + name := req.Arguments[0] + + if name == "self" { + return fmt.Errorf("exporting key 'self' is not allowed") + } + + cfgRoot, err := cmdenv.GetConfigRoot(env) + if err != nil { + return err + } + + r, err := fsrepo.Open(cfgRoot) + if err != nil { + return err + } + defer r.Close() + + sk, err := r.Keystore().Get(name) + if err != nil { + return fmt.Errorf("key with name '%s' doesn't exist", name) + } + + encoded, err := encodeSKForExport(sk) + if err != nil { + return err + } + + return cmds.EmitOnce(res, &ExportKeyOutput{ + Sk: encoded, + }) + }, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, ko *ExportKeyOutput) error { + _, err := w.Write([]byte(ko.Sk + "\n")) + return err + }), + }, + Type: ExportKeyOutput{}, +} + +var keyImportCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Import a key and prints imported key id", + }, + Options: []cmds.Option{ + cmds.StringOption(keyFormatOptionName, "f", "output format: b58mh or b36cid").WithDefault("b58mh"), + }, + Arguments: []cmds.Argument{ + cmds.StringArg("name", true, false, "name to associate with key in keychain"), + cmds.StringArg("key", true, false, "key provided by generate or export"), + }, + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + name := req.Arguments[0] + encoded := req.Arguments[1] + + data, err := base58.Decode(encoded) + if err != nil { + return err + } + + sk, err := crypto.UnmarshalPrivateKey(data) + if err != nil { + return err + } + + cfgRoot, err := cmdenv.GetConfigRoot(env) + if err != nil { + return err + } + + r, err := fsrepo.Open(cfgRoot) + if err != nil { + return err + } + defer r.Close() + + _, err = r.Keystore().Get(name) + if err == nil { + return fmt.Errorf("key with name '%s' already exists", name) + } + + err = r.Keystore().Put(name, sk) + if err != nil { + return err + } + + pid, err := peer.IDFromPrivateKey(sk) + if err != nil { + return err + } + + return cmds.EmitOnce(res, &KeyOutput{ + Name: name, + Id: formatID(pid, req.Options[keyFormatOptionName].(string)), + }) + }, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, ko *KeyOutput) error { + _, err := w.Write([]byte(ko.Id + "\n")) + return err + }), + }, + Type: KeyOutput{}, +} + +var keyIdentifyCmd = &cmds.Command{ + Helptext: cmds.HelpText{ + Tagline: "Identify an exported keypair", + }, + Options: []cmds.Option{ + cmds.StringOption(keyFormatOptionName, "f", "output format: b58mh or b36cid").WithDefault("b58mh"), + }, + Arguments: []cmds.Argument{ + cmds.StringArg("key", true, false, "key provided by generate or export"), + }, + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + encoded := req.Arguments[0] + + data, err := base58.Decode(encoded) + if err != nil { + return err + } + + sk, err := crypto.UnmarshalPrivateKey(data) + if err != nil { + return err + } + + pid, err := peer.IDFromPrivateKey(sk) + if err != nil { + return err + } + + return cmds.EmitOnce(res, &KeyOutput{ + Name: "", + Id: formatID(pid, req.Options[keyFormatOptionName].(string)), + }) + }, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, ko *KeyOutput) error { + _, err := w.Write([]byte(ko.Id + "\n")) + return err + }), + }, + Type: KeyOutput{}, +} + var keyListCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List all local keypairs", diff --git a/core/coreapi/key.go b/core/coreapi/key.go index e6fe7b124d1..5e8bda6df76 100644 --- a/core/coreapi/key.go +++ b/core/coreapi/key.go @@ -37,21 +37,11 @@ func (k *key) ID() peer.ID { return k.peerID } -// Generate generates new key, stores it in the keystore under the specified -// name and returns a base58 encoded multihash of its public key. -func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.KeyGenerateOption) (coreiface.Key, error) { +// GenerateKey generates a new keypair and returns it +func GenerateKey(opts ...caopts.KeyGenerateOption) (crypto.PrivKey, crypto.PubKey, error) { options, err := caopts.KeyGenerateOptions(opts...) if err != nil { - return nil, err - } - - if name == "self" { - return nil, fmt.Errorf("cannot create key with name 'self'") - } - - _, err = api.repo.Keystore().Get(name) - if err == nil { - return nil, fmt.Errorf("key with name '%s' already exists", name) + return nil, nil, err } var sk crypto.PrivKey @@ -65,7 +55,7 @@ func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.Key priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.RSA, options.Size, rand.Reader) if err != nil { - return nil, err + return nil, nil, err } sk = priv @@ -73,13 +63,33 @@ func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.Key case "ed25519": priv, pub, err := crypto.GenerateEd25519Key(rand.Reader) if err != nil { - return nil, err + return nil, nil, err } sk = priv pk = pub default: - return nil, fmt.Errorf("unrecognized key type: %s", options.Algorithm) + return nil, nil, fmt.Errorf("unrecognized key type: %s", options.Algorithm) + } + + return sk, pk, nil +} + +// Generate generates new key, stores it in the keystore under the specified +// name and returns a base58 encoded multihash of its public key. +func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.KeyGenerateOption) (coreiface.Key, error) { + if name == "self" { + return nil, fmt.Errorf("cannot create key with name 'self'") + } + + _, err := api.repo.Keystore().Get(name) + if err == nil { + return nil, fmt.Errorf("key with name '%s' already exists", name) + } + + sk, pk, err := GenerateKey(opts...) + if err != nil { + return nil, err } err = api.repo.Keystore().Put(name, sk) diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh index f9716b13ad7..e0a6e7b4af2 100644 --- a/test/sharness/lib/test-lib.sh +++ b/test/sharness/lib/test-lib.sh @@ -483,6 +483,22 @@ test_check_ed25519_b36cid_peerid() { } } +test_check_rsa2048_sk() { + peeridlen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && + test "$sklen" = "300" || { + echo "Bad RSA2048 sk '$1' with len '$sklen'" + return 1 + } +} + +test_check_ed25519_sk() { + sklen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && + test "$sklen" = "300" || { + echo "Bad ED25519 sk '$1' with len '$sklen'" + return 1 + } +} + convert_tcp_maddr() { echo $1 | awk -F'/' '{ printf "%s:%s", $3, $5 }' } diff --git a/test/sharness/t0165-keystore.sh b/test/sharness/t0165-keystore.sh index c4538c70eef..82afa66c5ab 100755 --- a/test/sharness/t0165-keystore.sh +++ b/test/sharness/t0165-keystore.sh @@ -17,6 +17,11 @@ PEERID=$(ipfs key gen -f=b58mh --type=rsa --size=2048 key_rsa) && test_check_rsa2048_b58mh_peerid $PEERID ' +test_expect_success "test RSA key B36CID sk export format" ' +PEERID=$(ipfs key export key_rsa) && +test_check_rsa2048_sk $PEERID +' + test_expect_success "test RSA key B36CID multihash format" ' PEERID=$(ipfs key list -f=b36cid -l | grep key_rsa | head -n 1 | cut -d " " -f1) && test_check_rsa2048_b36cid_peerid $PEERID && @@ -28,6 +33,11 @@ PEERID=$(ipfs key gen -f=b36cid --type=ed25519 key_ed25519) && test_check_ed25519_b36cid_peerid $PEERID ' +test_expect_success "test RSA key ED25519 sk export format" ' +PEERID=$(ipfs key export key_ed25519) && +test_check_ed25519_sk $PEERID +' + test_expect_success "test ED25519 key B36CID multihash format" ' PEERID=$(ipfs key list -f=b36cid -l | grep key_ed25519 | head -n 1 | cut -d " " -f1) && test_check_ed25519_b36cid_peerid $PEERID && @@ -43,11 +53,32 @@ ipfs key rm key_ed25519 test_expect_success "create a new ed25519 key" ' edhash=$(ipfs key gen -f=b58mh bazed --type=ed25519) ' + + test_expect_success "import an rsa key" ' + imphash=$(ipfs key import -f=b58mh quxel B9bLmHeKLQU1hX23meSn2kJiNW7AZ31C6PBNSYumejXB13vxSVvViZDkEnchAH4BTs9yVnBNZKZYLwykaCohzxTntesTCVaBhZR2Br2Swav2NXwVBhfrUbaBTrR2248KfbVxSiUdkpFn8kcAmUGwp2KGMGRmq85WreGFDdAvzz8ruN2EFfWSHLc1YeUxHeUgKsQm3N13uF7q5x4qvjWM6yvMWNY7JtZrihT8BZQhgb2ezR4iYPjXZTtPZWsLbrrhUvHhxSn1NsTw6NZ7Jbs84qMXXnH56BmT8J9LugRhQQvgBquSoS1m7aeD2y1L1A7mueVDYGLDzgxRSt5CohY7VVMdheUpPiq44CicuYt5YgbbuE3wMHntn6sd9QSYw7f4SjjKdw7Jhy5fNW29SkHvpLfZKfqzBNhSfHsofXVEASDpfr5mqws1eQTztqvvZhHXQxAoxxP3PK6TfDnATdLdV3Cy5v6nLt7ppsBj54hif5EZneHMLeYP8bYLbELQ2fZdoprpnKVBsMY1nWvgrMKUTpLjoKB6bzAZYuXaYVtmrdhESmKCyE12yEyvCcD8DJQU6JjqaD1DyVSPNkL3ze26Mm3ZyiFEH7M4XirUsPLrsj41Qt1xGaVGNEdkdthihytTZxxnmgyAptZMUNfSviBfH1tVbfoXFtBGU8eYMLdSHFqxSktT1mqeiWatxMQZ8pTeA9VCvAp9RTSRFkTQR9uP6w6qTzRD9cFcH4HyCEc5TJpiZdP7u9RjaEo2S3P9VkHfmqCH4McpLgw7He9nm7rf9JA2Gh7ubTKy5e6dJUWojgYhGS4KGe3yKGFhLaNgRiME63fUEFSnN2ZvCSM9qsrj34q2h8962xBod9hCVEDfk4tfmHu1UHX5AGaW6mk3pzqKKVYTTWXi84JSH7vzKPmQuhwaAR9Ye3Jbdzehp4xhrT5aFCjnz3r5qNv2zz48Fq5bGc1RUh88PUMT3z6kuzv6B1eXTLYpeu9gGdjc5C9DQDTYPfcHWn7dSHr4AGV1sN6SwVy8W5LZdMAZaeXCDn9iXDwbeD2DYd2ozVCEzceygVzpVdnueNx5FmG6zHtGzfuStr4Jj85sbd2jUGh4ES2bMU41jw2gJ6ujjf6CrxZpCWhXz6NJpAS9njcDFXuspf7otbMjCB6TzwokJwEse31nGUZQdhQgXn23vnZtxwCV621uXFbm7xVACRZKeuXgw8VdEVaXGvf2V4DdhjZnjmePBbTeJ7WjABavLcpMqZJH7FgaLxazFqk9RXtnfUEbVAAhuZzxz6L8Z6axHwz3a4EZtALRjfFjn6xjaUtsWXYW8P6F7femM6UHx3qXMo43hKC7oxnd6Tfta972dgyQfSoBwWkWzB8cvaJreNh4bdLNkw6mty86NXGKyijv83LR1HjbnUoTwPbEMX8JyzLfMf3qiWzwf6MHrXprwygmEpNc6w8tNNivmcWyCX3wmPkMKK1bmi5TCHoUtRrxcyXKhmuyo6zzag8KyK6iZaRbMiFiUJBi5VYwidMutkexWo8SRqfSV5yp2kxswknmpeVTnXBhVEy3anMEiD6bV48AnbF6SfKAi2DGBFqxBFfpFEbYtPauHiYYzZX1epqvKxY23xA9J8FosMk4yYN4Ps7Rh) + ' - test_expect_success "both keys show up in list output" ' + test_expect_success "identify an rsa key" ' + gothash=$(ipfs key identify B9bLmHeKLQU1hX23meSn2kJiNW7AZ31C6PBNSYumejXB13vxSVvViZDkEnchAH4BTs9yVnBNZKZYLwykaCohzxTntesTCVaBhZR2Br2Swav2NXwVBhfrUbaBTrR2248KfbVxSiUdkpFn8kcAmUGwp2KGMGRmq85WreGFDdAvzz8ruN2EFfWSHLc1YeUxHeUgKsQm3N13uF7q5x4qvjWM6yvMWNY7JtZrihT8BZQhgb2ezR4iYPjXZTtPZWsLbrrhUvHhxSn1NsTw6NZ7Jbs84qMXXnH56BmT8J9LugRhQQvgBquSoS1m7aeD2y1L1A7mueVDYGLDzgxRSt5CohY7VVMdheUpPiq44CicuYt5YgbbuE3wMHntn6sd9QSYw7f4SjjKdw7Jhy5fNW29SkHvpLfZKfqzBNhSfHsofXVEASDpfr5mqws1eQTztqvvZhHXQxAoxxP3PK6TfDnATdLdV3Cy5v6nLt7ppsBj54hif5EZneHMLeYP8bYLbELQ2fZdoprpnKVBsMY1nWvgrMKUTpLjoKB6bzAZYuXaYVtmrdhESmKCyE12yEyvCcD8DJQU6JjqaD1DyVSPNkL3ze26Mm3ZyiFEH7M4XirUsPLrsj41Qt1xGaVGNEdkdthihytTZxxnmgyAptZMUNfSviBfH1tVbfoXFtBGU8eYMLdSHFqxSktT1mqeiWatxMQZ8pTeA9VCvAp9RTSRFkTQR9uP6w6qTzRD9cFcH4HyCEc5TJpiZdP7u9RjaEo2S3P9VkHfmqCH4McpLgw7He9nm7rf9JA2Gh7ubTKy5e6dJUWojgYhGS4KGe3yKGFhLaNgRiME63fUEFSnN2ZvCSM9qsrj34q2h8962xBod9hCVEDfk4tfmHu1UHX5AGaW6mk3pzqKKVYTTWXi84JSH7vzKPmQuhwaAR9Ye3Jbdzehp4xhrT5aFCjnz3r5qNv2zz48Fq5bGc1RUh88PUMT3z6kuzv6B1eXTLYpeu9gGdjc5C9DQDTYPfcHWn7dSHr4AGV1sN6SwVy8W5LZdMAZaeXCDn9iXDwbeD2DYd2ozVCEzceygVzpVdnueNx5FmG6zHtGzfuStr4Jj85sbd2jUGh4ES2bMU41jw2gJ6ujjf6CrxZpCWhXz6NJpAS9njcDFXuspf7otbMjCB6TzwokJwEse31nGUZQdhQgXn23vnZtxwCV621uXFbm7xVACRZKeuXgw8VdEVaXGvf2V4DdhjZnjmePBbTeJ7WjABavLcpMqZJH7FgaLxazFqk9RXtnfUEbVAAhuZzxz6L8Z6axHwz3a4EZtALRjfFjn6xjaUtsWXYW8P6F7femM6UHx3qXMo43hKC7oxnd6Tfta972dgyQfSoBwWkWzB8cvaJreNh4bdLNkw6mty86NXGKyijv83LR1HjbnUoTwPbEMX8JyzLfMf3qiWzwf6MHrXprwygmEpNc6w8tNNivmcWyCX3wmPkMKK1bmi5TCHoUtRrxcyXKhmuyo6zzag8KyK6iZaRbMiFiUJBi5VYwidMutkexWo8SRqfSV5yp2kxswknmpeVTnXBhVEy3anMEiD6bV48AnbF6SfKAi2DGBFqxBFfpFEbYtPauHiYYzZX1epqvKxY23xA9J8FosMk4yYN4Ps7Rh) && + test $imphash = $gothash + ' + + test_expect_success "key import can't export self" ' + test_must_fail ipfs key export self 2>&1 | tee key_exp_out && + grep -q "Error: cannot export key with name" key_exp_out + ' + + test_expect_success "key import can't import self" ' + test_must_fail ipfs key import self B9bLmHeKLQU1hX23meSn2kJiNW7AZ31C6PBNSYumejXB13vxSVvViZDkEnchAH4BTs9yVnBNZKZYLwykaCohzxTntesTCVaBhZR2Br2Swav2NXwVBhfrUbaBTrR2248KfbVxSiUdkpFn8kcAmUGwp2KGMGRmq85WreGFDdAvzz8ruN2EFfWSHLc1YeUxHeUgKsQm3N13uF7q5x4qvjWM6yvMWNY7JtZrihT8BZQhgb2ezR4iYPjXZTtPZWsLbrrhUvHhxSn1NsTw6NZ7Jbs84qMXXnH56BmT8J9LugRhQQvgBquSoS1m7aeD2y1L1A7mueVDYGLDzgxRSt5CohY7VVMdheUpPiq44CicuYt5YgbbuE3wMHntn6sd9QSYw7f4SjjKdw7Jhy5fNW29SkHvpLfZKfqzBNhSfHsofXVEASDpfr5mqws1eQTztqvvZhHXQxAoxxP3PK6TfDnATdLdV3Cy5v6nLt7ppsBj54hif5EZneHMLeYP8bYLbELQ2fZdoprpnKVBsMY1nWvgrMKUTpLjoKB6bzAZYuXaYVtmrdhESmKCyE12yEyvCcD8DJQU6JjqaD1DyVSPNkL3ze26Mm3ZyiFEH7M4XirUsPLrsj41Qt1xGaVGNEdkdthihytTZxxnmgyAptZMUNfSviBfH1tVbfoXFtBGU8eYMLdSHFqxSktT1mqeiWatxMQZ8pTeA9VCvAp9RTSRFkTQR9uP6w6qTzRD9cFcH4HyCEc5TJpiZdP7u9RjaEo2S3P9VkHfmqCH4McpLgw7He9nm7rf9JA2Gh7ubTKy5e6dJUWojgYhGS4KGe3yKGFhLaNgRiME63fUEFSnN2ZvCSM9qsrj34q2h8962xBod9hCVEDfk4tfmHu1UHX5AGaW6mk3pzqKKVYTTWXi84JSH7vzKPmQuhwaAR9Ye3Jbdzehp4xhrT5aFCjnz3r5qNv2zz48Fq5bGc1RUh88PUMT3z6kuzv6B1eXTLYpeu9gGdjc5C9DQDTYPfcHWn7dSHr4AGV1sN6SwVy8W5LZdMAZaeXCDn9iXDwbeD2DYd2ozVCEzceygVzpVdnueNx5FmG6zHtGzfuStr4Jj85sbd2jUGh4ES2bMU41jw2gJ6ujjf6CrxZpCWhXz6NJpAS9njcDFXuspf7otbMjCB6TzwokJwEse31nGUZQdhQgXn23vnZtxwCV621uXFbm7xVACRZKeuXgw8VdEVaXGvf2V4DdhjZnjmePBbTeJ7WjABavLcpMqZJH7FgaLxazFqk9RXtnfUEbVAAhuZzxz6L8Z6axHwz3a4EZtALRjfFjn6xjaUtsWXYW8P6F7femM6UHx3qXMo43hKC7oxnd6Tfta972dgyQfSoBwWkWzB8cvaJreNh4bdLNkw6mty86NXGKyijv83LR1HjbnUoTwPbEMX8JyzLfMf3qiWzwf6MHrXprwygmEpNc6w8tNNivmcWyCX3wmPkMKK1bmi5TCHoUtRrxcyXKhmuyo6zzag8KyK6iZaRbMiFiUJBi5VYwidMutkexWo8SRqfSV5yp2kxswknmpeVTnXBhVEy3anMEiD6bV48AnbF6SfKAi2DGBFqxBFfpFEbYtPauHiYYzZX1epqvKxY23xA9J8FosMk4yYN4Ps7Rh 2>&1 | tee key_imp_out && + grep -q "Error: cannot import key with name" key_imp_out + ' + + test_expect_success "all keys show up in list output" ' echo bazed > list_exp && echo foobarsa >> list_exp && - echo self >> list_exp + echo quxel >> list_exp && + echo self >> list_exp && + sort -o list_exp list_exp ipfs key list -f=b58mh | sort > list_out && test_cmp list_exp list_out ' From c7657cb69036cd0c2c11b34b0f41fb44254fa61d Mon Sep 17 00:00:00 2001 From: rendaw <> Date: Thu, 16 Jul 2020 23:57:30 +0900 Subject: [PATCH 2/6] Fix sharness tests --- core/commands/keystore.go | 7 ++++- test/sharness/lib/test-lib.sh | 10 +++---- test/sharness/t0165-keystore.sh | 48 ++++++++++++++++++++++----------- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/core/commands/keystore.go b/core/commands/keystore.go index ae90e43010e..a71ca3a2687 100644 --- a/core/commands/keystore.go +++ b/core/commands/keystore.go @@ -240,7 +240,7 @@ var keyExportCmd = &cmds.Command{ name := req.Arguments[0] if name == "self" { - return fmt.Errorf("exporting key 'self' is not allowed") + return fmt.Errorf("cannot export key with name 'self'") } cfgRoot, err := cmdenv.GetConfigRoot(env) @@ -290,6 +290,11 @@ var keyImportCmd = &cmds.Command{ }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { name := req.Arguments[0] + + if name == "self" { + return fmt.Errorf("cannot import key with name 'self'") + } + encoded := req.Arguments[1] data, err := base58.Decode(encoded) diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh index e0a6e7b4af2..9cbc9597950 100644 --- a/test/sharness/lib/test-lib.sh +++ b/test/sharness/lib/test-lib.sh @@ -484,19 +484,19 @@ test_check_ed25519_b36cid_peerid() { } test_check_rsa2048_sk() { - peeridlen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && - test "$sklen" = "300" || { + sklen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && + if (($sklen < 1600)); then echo "Bad RSA2048 sk '$1' with len '$sklen'" return 1 - } + fi } test_check_ed25519_sk() { sklen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && - test "$sklen" = "300" || { + if (($sklen < 1600)); then echo "Bad ED25519 sk '$1' with len '$sklen'" return 1 - } + fi } convert_tcp_maddr() { diff --git a/test/sharness/t0165-keystore.sh b/test/sharness/t0165-keystore.sh index 82afa66c5ab..444353edfc4 100755 --- a/test/sharness/t0165-keystore.sh +++ b/test/sharness/t0165-keystore.sh @@ -11,15 +11,31 @@ test_description="Test keystore commands" test_init_ipfs test_key_cmd() { + test_expect_success "export with no store doesn't store" ' + ipfs key gen -n -e && echo self > list_exp && + ipfs key list > list_out && + test_sort_cmp list_exp list_out + ' + + test_expect_success "no store without export is an error" ' + test_must_fail ipfs key gen -n 2>&1 | tee key_gen_out && + grep -q "you must export key" key_gen_out + ' + + test_expect_success "key gen without name is an error" ' + test_must_fail ipfs key gen 2>&1 | tee key_gen_out && + grep -q "you must specify a key name" key_gen_out + ' + # test key output format test_expect_success "create an RSA key and test B58MH multihash output" ' PEERID=$(ipfs key gen -f=b58mh --type=rsa --size=2048 key_rsa) && test_check_rsa2048_b58mh_peerid $PEERID ' -test_expect_success "test RSA key B36CID sk export format" ' -PEERID=$(ipfs key export key_rsa) && -test_check_rsa2048_sk $PEERID +test_expect_success "test RSA key sk export format" ' +SK=$(ipfs key export key_rsa) && +test_check_rsa2048_sk $SK ' test_expect_success "test RSA key B36CID multihash format" ' @@ -33,9 +49,10 @@ PEERID=$(ipfs key gen -f=b36cid --type=ed25519 key_ed25519) && test_check_ed25519_b36cid_peerid $PEERID ' -test_expect_success "test RSA key ED25519 sk export format" ' -PEERID=$(ipfs key export key_ed25519) && -test_check_ed25519_sk $PEERID +test_expect_success "create and export an ED25519 key" ' +SK=$(ipfs key gen -e key_ed25519_2) && +test_check_ed25519_sk $SK && +ipfs key rm key_ed25519_2 ' test_expect_success "test ED25519 key B36CID multihash format" ' @@ -63,7 +80,7 @@ ipfs key rm key_ed25519 test $imphash = $gothash ' - test_expect_success "key import can't export self" ' + test_expect_success "key export can't export self" ' test_must_fail ipfs key export self 2>&1 | tee key_exp_out && grep -q "Error: cannot export key with name" key_exp_out ' @@ -77,10 +94,9 @@ ipfs key rm key_ed25519 echo bazed > list_exp && echo foobarsa >> list_exp && echo quxel >> list_exp && - echo self >> list_exp && - sort -o list_exp list_exp - ipfs key list -f=b58mh | sort > list_out && - test_cmp list_exp list_out + echo self >> list_exp + ipfs key list -f=b58mh > list_out && + test_sort_cmp list_exp list_out ' test_expect_success "key hashes show up in long list output" ' @@ -96,9 +112,10 @@ ipfs key rm key_ed25519 test_expect_success "key rm remove a key" ' ipfs key rm foobarsa echo bazed > list_exp && + echo quxel >> list_exp && echo self >> list_exp - ipfs key list -f=b58mh | sort > list_out && - test_cmp list_exp list_out + ipfs key list -f=b58mh > list_out && + test_sort_cmp list_exp list_out ' test_expect_success "key rm can't remove self" ' @@ -109,9 +126,10 @@ ipfs key rm key_ed25519 test_expect_success "key rename rename a key" ' ipfs key rename bazed fooed echo fooed > list_exp && + echo quxel >> list_exp && echo self >> list_exp - ipfs key list -f=b58mh | sort > list_out && - test_cmp list_exp list_out + ipfs key list -f=b58mh > list_out && + test_sort_cmp list_exp list_out ' test_expect_success "key rename rename key output succeeds" ' From a70d04b68f3433208c89a406b6429919660f7c07 Mon Sep 17 00:00:00 2001 From: Adin Schmahmann Date: Thu, 30 Jul 2020 16:25:35 -0400 Subject: [PATCH 3/6] remove ipfs key identify command --- core/commands/commands_test.go | 1 - core/commands/keystore.go | 43 --------------------------------- test/sharness/t0165-keystore.sh | 11 +++++---- 3 files changed, 6 insertions(+), 49 deletions(-) diff --git a/core/commands/commands_test.go b/core/commands/commands_test.go index 10b0bfa236b..96d7c501058 100644 --- a/core/commands/commands_test.go +++ b/core/commands/commands_test.go @@ -135,7 +135,6 @@ func TestCommands(t *testing.T) { "/key/gen", "/key/export", "/key/import", - "/key/identify", "/key/list", "/key/rename", "/key/rm", diff --git a/core/commands/keystore.go b/core/commands/keystore.go index a71ca3a2687..84586055e4e 100644 --- a/core/commands/keystore.go +++ b/core/commands/keystore.go @@ -38,7 +38,6 @@ publish'. "gen": keyGenCmd, "export": keyExportCmd, "import": keyImportCmd, - "identify": keyIdentifyCmd, "list": keyListCmd, "rename": keyRenameCmd, "rm": keyRmCmd, @@ -347,48 +346,6 @@ var keyImportCmd = &cmds.Command{ Type: KeyOutput{}, } -var keyIdentifyCmd = &cmds.Command{ - Helptext: cmds.HelpText{ - Tagline: "Identify an exported keypair", - }, - Options: []cmds.Option{ - cmds.StringOption(keyFormatOptionName, "f", "output format: b58mh or b36cid").WithDefault("b58mh"), - }, - Arguments: []cmds.Argument{ - cmds.StringArg("key", true, false, "key provided by generate or export"), - }, - Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - encoded := req.Arguments[0] - - data, err := base58.Decode(encoded) - if err != nil { - return err - } - - sk, err := crypto.UnmarshalPrivateKey(data) - if err != nil { - return err - } - - pid, err := peer.IDFromPrivateKey(sk) - if err != nil { - return err - } - - return cmds.EmitOnce(res, &KeyOutput{ - Name: "", - Id: formatID(pid, req.Options[keyFormatOptionName].(string)), - }) - }, - Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, ko *KeyOutput) error { - _, err := w.Write([]byte(ko.Id + "\n")) - return err - }), - }, - Type: KeyOutput{}, -} - var keyListCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "List all local keypairs", diff --git a/test/sharness/t0165-keystore.sh b/test/sharness/t0165-keystore.sh index 444353edfc4..ecc7facb107 100755 --- a/test/sharness/t0165-keystore.sh +++ b/test/sharness/t0165-keystore.sh @@ -72,12 +72,13 @@ ipfs key rm key_ed25519 ' test_expect_success "import an rsa key" ' - imphash=$(ipfs key import -f=b58mh quxel B9bLmHeKLQU1hX23meSn2kJiNW7AZ31C6PBNSYumejXB13vxSVvViZDkEnchAH4BTs9yVnBNZKZYLwykaCohzxTntesTCVaBhZR2Br2Swav2NXwVBhfrUbaBTrR2248KfbVxSiUdkpFn8kcAmUGwp2KGMGRmq85WreGFDdAvzz8ruN2EFfWSHLc1YeUxHeUgKsQm3N13uF7q5x4qvjWM6yvMWNY7JtZrihT8BZQhgb2ezR4iYPjXZTtPZWsLbrrhUvHhxSn1NsTw6NZ7Jbs84qMXXnH56BmT8J9LugRhQQvgBquSoS1m7aeD2y1L1A7mueVDYGLDzgxRSt5CohY7VVMdheUpPiq44CicuYt5YgbbuE3wMHntn6sd9QSYw7f4SjjKdw7Jhy5fNW29SkHvpLfZKfqzBNhSfHsofXVEASDpfr5mqws1eQTztqvvZhHXQxAoxxP3PK6TfDnATdLdV3Cy5v6nLt7ppsBj54hif5EZneHMLeYP8bYLbELQ2fZdoprpnKVBsMY1nWvgrMKUTpLjoKB6bzAZYuXaYVtmrdhESmKCyE12yEyvCcD8DJQU6JjqaD1DyVSPNkL3ze26Mm3ZyiFEH7M4XirUsPLrsj41Qt1xGaVGNEdkdthihytTZxxnmgyAptZMUNfSviBfH1tVbfoXFtBGU8eYMLdSHFqxSktT1mqeiWatxMQZ8pTeA9VCvAp9RTSRFkTQR9uP6w6qTzRD9cFcH4HyCEc5TJpiZdP7u9RjaEo2S3P9VkHfmqCH4McpLgw7He9nm7rf9JA2Gh7ubTKy5e6dJUWojgYhGS4KGe3yKGFhLaNgRiME63fUEFSnN2ZvCSM9qsrj34q2h8962xBod9hCVEDfk4tfmHu1UHX5AGaW6mk3pzqKKVYTTWXi84JSH7vzKPmQuhwaAR9Ye3Jbdzehp4xhrT5aFCjnz3r5qNv2zz48Fq5bGc1RUh88PUMT3z6kuzv6B1eXTLYpeu9gGdjc5C9DQDTYPfcHWn7dSHr4AGV1sN6SwVy8W5LZdMAZaeXCDn9iXDwbeD2DYd2ozVCEzceygVzpVdnueNx5FmG6zHtGzfuStr4Jj85sbd2jUGh4ES2bMU41jw2gJ6ujjf6CrxZpCWhXz6NJpAS9njcDFXuspf7otbMjCB6TzwokJwEse31nGUZQdhQgXn23vnZtxwCV621uXFbm7xVACRZKeuXgw8VdEVaXGvf2V4DdhjZnjmePBbTeJ7WjABavLcpMqZJH7FgaLxazFqk9RXtnfUEbVAAhuZzxz6L8Z6axHwz3a4EZtALRjfFjn6xjaUtsWXYW8P6F7femM6UHx3qXMo43hKC7oxnd6Tfta972dgyQfSoBwWkWzB8cvaJreNh4bdLNkw6mty86NXGKyijv83LR1HjbnUoTwPbEMX8JyzLfMf3qiWzwf6MHrXprwygmEpNc6w8tNNivmcWyCX3wmPkMKK1bmi5TCHoUtRrxcyXKhmuyo6zzag8KyK6iZaRbMiFiUJBi5VYwidMutkexWo8SRqfSV5yp2kxswknmpeVTnXBhVEy3anMEiD6bV48AnbF6SfKAi2DGBFqxBFfpFEbYtPauHiYYzZX1epqvKxY23xA9J8FosMk4yYN4Ps7Rh) + echo "B9bLmHeKLQU1hX23meSn2kJiNW7AZ31C6PBNSYumejXB13vxSVvViZDkEnchAH4BTs9yVnBNZKZYLwykaCohzxTntesTCVaBhZR2Br2Swav2NXwVBhfrUbaBTrR2248KfbVxSiUdkpFn8kcAmUGwp2KGMGRmq85WreGFDdAvzz8ruN2EFfWSHLc1YeUxHeUgKsQm3N13uF7q5x4qvjWM6yvMWNY7JtZrihT8BZQhgb2ezR4iYPjXZTtPZWsLbrrhUvHhxSn1NsTw6NZ7Jbs84qMXXnH56BmT8J9LugRhQQvgBquSoS1m7aeD2y1L1A7mueVDYGLDzgxRSt5CohY7VVMdheUpPiq44CicuYt5YgbbuE3wMHntn6sd9QSYw7f4SjjKdw7Jhy5fNW29SkHvpLfZKfqzBNhSfHsofXVEASDpfr5mqws1eQTztqvvZhHXQxAoxxP3PK6TfDnATdLdV3Cy5v6nLt7ppsBj54hif5EZneHMLeYP8bYLbELQ2fZdoprpnKVBsMY1nWvgrMKUTpLjoKB6bzAZYuXaYVtmrdhESmKCyE12yEyvCcD8DJQU6JjqaD1DyVSPNkL3ze26Mm3ZyiFEH7M4XirUsPLrsj41Qt1xGaVGNEdkdthihytTZxxnmgyAptZMUNfSviBfH1tVbfoXFtBGU8eYMLdSHFqxSktT1mqeiWatxMQZ8pTeA9VCvAp9RTSRFkTQR9uP6w6qTzRD9cFcH4HyCEc5TJpiZdP7u9RjaEo2S3P9VkHfmqCH4McpLgw7He9nm7rf9JA2Gh7ubTKy5e6dJUWojgYhGS4KGe3yKGFhLaNgRiME63fUEFSnN2ZvCSM9qsrj34q2h8962xBod9hCVEDfk4tfmHu1UHX5AGaW6mk3pzqKKVYTTWXi84JSH7vzKPmQuhwaAR9Ye3Jbdzehp4xhrT5aFCjnz3r5qNv2zz48Fq5bGc1RUh88PUMT3z6kuzv6B1eXTLYpeu9gGdjc5C9DQDTYPfcHWn7dSHr4AGV1sN6SwVy8W5LZdMAZaeXCDn9iXDwbeD2DYd2ozVCEzceygVzpVdnueNx5FmG6zHtGzfuStr4Jj85sbd2jUGh4ES2bMU41jw2gJ6ujjf6CrxZpCWhXz6NJpAS9njcDFXuspf7otbMjCB6TzwokJwEse31nGUZQdhQgXn23vnZtxwCV621uXFbm7xVACRZKeuXgw8VdEVaXGvf2V4DdhjZnjmePBbTeJ7WjABavLcpMqZJH7FgaLxazFqk9RXtnfUEbVAAhuZzxz6L8Z6axHwz3a4EZtALRjfFjn6xjaUtsWXYW8P6F7femM6UHx3qXMo43hKC7oxnd6Tfta972dgyQfSoBwWkWzB8cvaJreNh4bdLNkw6mty86NXGKyijv83LR1HjbnUoTwPbEMX8JyzLfMf3qiWzwf6MHrXprwygmEpNc6w8tNNivmcWyCX3wmPkMKK1bmi5TCHoUtRrxcyXKhmuyo6zzag8KyK6iZaRbMiFiUJBi5VYwidMutkexWo8SRqfSV5yp2kxswknmpeVTnXBhVEy3anMEiD6bV48AnbF6SfKAi2DGBFqxBFfpFEbYtPauHiYYzZX1epqvKxY23xA9J8FosMk4yYN4Ps7Rh" >> importkey + imphash=$(ipfs key import -f=b58mh quxel $(cat importkey)) ' - test_expect_success "identify an rsa key" ' - gothash=$(ipfs key identify B9bLmHeKLQU1hX23meSn2kJiNW7AZ31C6PBNSYumejXB13vxSVvViZDkEnchAH4BTs9yVnBNZKZYLwykaCohzxTntesTCVaBhZR2Br2Swav2NXwVBhfrUbaBTrR2248KfbVxSiUdkpFn8kcAmUGwp2KGMGRmq85WreGFDdAvzz8ruN2EFfWSHLc1YeUxHeUgKsQm3N13uF7q5x4qvjWM6yvMWNY7JtZrihT8BZQhgb2ezR4iYPjXZTtPZWsLbrrhUvHhxSn1NsTw6NZ7Jbs84qMXXnH56BmT8J9LugRhQQvgBquSoS1m7aeD2y1L1A7mueVDYGLDzgxRSt5CohY7VVMdheUpPiq44CicuYt5YgbbuE3wMHntn6sd9QSYw7f4SjjKdw7Jhy5fNW29SkHvpLfZKfqzBNhSfHsofXVEASDpfr5mqws1eQTztqvvZhHXQxAoxxP3PK6TfDnATdLdV3Cy5v6nLt7ppsBj54hif5EZneHMLeYP8bYLbELQ2fZdoprpnKVBsMY1nWvgrMKUTpLjoKB6bzAZYuXaYVtmrdhESmKCyE12yEyvCcD8DJQU6JjqaD1DyVSPNkL3ze26Mm3ZyiFEH7M4XirUsPLrsj41Qt1xGaVGNEdkdthihytTZxxnmgyAptZMUNfSviBfH1tVbfoXFtBGU8eYMLdSHFqxSktT1mqeiWatxMQZ8pTeA9VCvAp9RTSRFkTQR9uP6w6qTzRD9cFcH4HyCEc5TJpiZdP7u9RjaEo2S3P9VkHfmqCH4McpLgw7He9nm7rf9JA2Gh7ubTKy5e6dJUWojgYhGS4KGe3yKGFhLaNgRiME63fUEFSnN2ZvCSM9qsrj34q2h8962xBod9hCVEDfk4tfmHu1UHX5AGaW6mk3pzqKKVYTTWXi84JSH7vzKPmQuhwaAR9Ye3Jbdzehp4xhrT5aFCjnz3r5qNv2zz48Fq5bGc1RUh88PUMT3z6kuzv6B1eXTLYpeu9gGdjc5C9DQDTYPfcHWn7dSHr4AGV1sN6SwVy8W5LZdMAZaeXCDn9iXDwbeD2DYd2ozVCEzceygVzpVdnueNx5FmG6zHtGzfuStr4Jj85sbd2jUGh4ES2bMU41jw2gJ6ujjf6CrxZpCWhXz6NJpAS9njcDFXuspf7otbMjCB6TzwokJwEse31nGUZQdhQgXn23vnZtxwCV621uXFbm7xVACRZKeuXgw8VdEVaXGvf2V4DdhjZnjmePBbTeJ7WjABavLcpMqZJH7FgaLxazFqk9RXtnfUEbVAAhuZzxz6L8Z6axHwz3a4EZtALRjfFjn6xjaUtsWXYW8P6F7femM6UHx3qXMo43hKC7oxnd6Tfta972dgyQfSoBwWkWzB8cvaJreNh4bdLNkw6mty86NXGKyijv83LR1HjbnUoTwPbEMX8JyzLfMf3qiWzwf6MHrXprwygmEpNc6w8tNNivmcWyCX3wmPkMKK1bmi5TCHoUtRrxcyXKhmuyo6zzag8KyK6iZaRbMiFiUJBi5VYwidMutkexWo8SRqfSV5yp2kxswknmpeVTnXBhVEy3anMEiD6bV48AnbF6SfKAi2DGBFqxBFfpFEbYtPauHiYYzZX1epqvKxY23xA9J8FosMk4yYN4Ps7Rh) && - test $imphash = $gothash + test_expect_success "export an rsa key" ' + ipfs key export quxel >> exportkey && + test_cmp importkey exportkey ' test_expect_success "key export can't export self" ' @@ -86,7 +87,7 @@ ipfs key rm key_ed25519 ' test_expect_success "key import can't import self" ' - test_must_fail ipfs key import self B9bLmHeKLQU1hX23meSn2kJiNW7AZ31C6PBNSYumejXB13vxSVvViZDkEnchAH4BTs9yVnBNZKZYLwykaCohzxTntesTCVaBhZR2Br2Swav2NXwVBhfrUbaBTrR2248KfbVxSiUdkpFn8kcAmUGwp2KGMGRmq85WreGFDdAvzz8ruN2EFfWSHLc1YeUxHeUgKsQm3N13uF7q5x4qvjWM6yvMWNY7JtZrihT8BZQhgb2ezR4iYPjXZTtPZWsLbrrhUvHhxSn1NsTw6NZ7Jbs84qMXXnH56BmT8J9LugRhQQvgBquSoS1m7aeD2y1L1A7mueVDYGLDzgxRSt5CohY7VVMdheUpPiq44CicuYt5YgbbuE3wMHntn6sd9QSYw7f4SjjKdw7Jhy5fNW29SkHvpLfZKfqzBNhSfHsofXVEASDpfr5mqws1eQTztqvvZhHXQxAoxxP3PK6TfDnATdLdV3Cy5v6nLt7ppsBj54hif5EZneHMLeYP8bYLbELQ2fZdoprpnKVBsMY1nWvgrMKUTpLjoKB6bzAZYuXaYVtmrdhESmKCyE12yEyvCcD8DJQU6JjqaD1DyVSPNkL3ze26Mm3ZyiFEH7M4XirUsPLrsj41Qt1xGaVGNEdkdthihytTZxxnmgyAptZMUNfSviBfH1tVbfoXFtBGU8eYMLdSHFqxSktT1mqeiWatxMQZ8pTeA9VCvAp9RTSRFkTQR9uP6w6qTzRD9cFcH4HyCEc5TJpiZdP7u9RjaEo2S3P9VkHfmqCH4McpLgw7He9nm7rf9JA2Gh7ubTKy5e6dJUWojgYhGS4KGe3yKGFhLaNgRiME63fUEFSnN2ZvCSM9qsrj34q2h8962xBod9hCVEDfk4tfmHu1UHX5AGaW6mk3pzqKKVYTTWXi84JSH7vzKPmQuhwaAR9Ye3Jbdzehp4xhrT5aFCjnz3r5qNv2zz48Fq5bGc1RUh88PUMT3z6kuzv6B1eXTLYpeu9gGdjc5C9DQDTYPfcHWn7dSHr4AGV1sN6SwVy8W5LZdMAZaeXCDn9iXDwbeD2DYd2ozVCEzceygVzpVdnueNx5FmG6zHtGzfuStr4Jj85sbd2jUGh4ES2bMU41jw2gJ6ujjf6CrxZpCWhXz6NJpAS9njcDFXuspf7otbMjCB6TzwokJwEse31nGUZQdhQgXn23vnZtxwCV621uXFbm7xVACRZKeuXgw8VdEVaXGvf2V4DdhjZnjmePBbTeJ7WjABavLcpMqZJH7FgaLxazFqk9RXtnfUEbVAAhuZzxz6L8Z6axHwz3a4EZtALRjfFjn6xjaUtsWXYW8P6F7femM6UHx3qXMo43hKC7oxnd6Tfta972dgyQfSoBwWkWzB8cvaJreNh4bdLNkw6mty86NXGKyijv83LR1HjbnUoTwPbEMX8JyzLfMf3qiWzwf6MHrXprwygmEpNc6w8tNNivmcWyCX3wmPkMKK1bmi5TCHoUtRrxcyXKhmuyo6zzag8KyK6iZaRbMiFiUJBi5VYwidMutkexWo8SRqfSV5yp2kxswknmpeVTnXBhVEy3anMEiD6bV48AnbF6SfKAi2DGBFqxBFfpFEbYtPauHiYYzZX1epqvKxY23xA9J8FosMk4yYN4Ps7Rh 2>&1 | tee key_imp_out && + test_must_fail ipfs key import self $(cat importkey) 2>&1 | tee key_imp_out && grep -q "Error: cannot import key with name" key_imp_out ' From 356ca3aefad5c68b0c315e5f9a6af215661e51f8 Mon Sep 17 00:00:00 2001 From: rendaw <> Date: Sat, 1 Aug 2020 10:45:38 +0900 Subject: [PATCH 4/6] Remove export option from generate --- core/commands/keystore.go | 109 ++++++-------------------------- core/coreapi/key.go | 42 +++++------- test/sharness/lib/test-lib.sh | 4 +- test/sharness/t0165-keystore.sh | 25 ++------ 4 files changed, 43 insertions(+), 137 deletions(-) diff --git a/core/commands/keystore.go b/core/commands/keystore.go index 84586055e4e..a34fdcc8090 100644 --- a/core/commands/keystore.go +++ b/core/commands/keystore.go @@ -7,8 +7,6 @@ import ( cmds "github.com/ipfs/go-ipfs-cmds" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" - "github.com/ipfs/go-ipfs/core/coreapi" - repo "github.com/ipfs/go-ipfs/repo" fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" options "github.com/ipfs/interface-go-ipfs-core/options" "github.com/libp2p/go-libp2p-core/crypto" @@ -35,12 +33,12 @@ publish'. `, }, Subcommands: map[string]*cmds.Command{ - "gen": keyGenCmd, - "export": keyExportCmd, - "import": keyImportCmd, - "list": keyListCmd, - "rename": keyRenameCmd, - "rm": keyRmCmd, + "gen": keyGenCmd, + "export": keyExportCmd, + "import": keyImportCmd, + "list": keyListCmd, + "rename": keyRenameCmd, + "rm": keyRmCmd, }, } @@ -49,12 +47,6 @@ type KeyOutput struct { Id string } -type GenerateKeyOutput struct { - Name string - Id string - Sk string -} - type ExportKeyOutput struct { Sk string } @@ -75,8 +67,6 @@ const ( keyStoreTypeOptionName = "type" keyStoreSizeOptionName = "size" keyFormatOptionName = "format" - keyExportOptionName = "export" - keyNoStoreOptionName = "no-store" ) var keyGenCmd = &cmds.Command{ @@ -87,57 +77,24 @@ var keyGenCmd = &cmds.Command{ cmds.StringOption(keyStoreTypeOptionName, "t", "type of the key to create: rsa, ed25519").WithDefault("rsa"), cmds.IntOption(keyStoreSizeOptionName, "s", "size of the key to generate"), cmds.StringOption(keyFormatOptionName, "f", "output format: b58mh or b36cid").WithDefault("b58mh"), - cmds.BoolOption(keyExportOptionName, "e", "return generated key for later re-import").WithDefault(false), - cmds.BoolOption(keyNoStoreOptionName, "n", "don't add the key to the keychain").WithDefault(false), }, Arguments: []cmds.Argument{ - cmds.StringArg("name", false, false, "name of key to create, required unless -n specified"), + cmds.StringArg("name", true, false, "name of key to create"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + api, err := cmdenv.GetApi(env, req) + if err != nil { + return err + } + typ, f := req.Options[keyStoreTypeOptionName].(string) if !f { return fmt.Errorf("please specify a key type with --type") } - store := !req.Options[keyNoStoreOptionName].(bool) - export := req.Options[keyExportOptionName].(bool) - - var name string - var r repo.Repo = nil - defer func() { - if r != nil { - r.Close() - } - }() - if store { - if len(req.Arguments) == 0 { - return fmt.Errorf("you must specify a key name") - } - - name = req.Arguments[0] - - if name == "self" { - return fmt.Errorf("cannot create key with name 'self'") - } - - cfgRoot, err := cmdenv.GetConfigRoot(env) - if err != nil { - return err - } - - r, err = fsrepo.Open(cfgRoot) - if err != nil { - return err - } - - _, err = r.Keystore().Get(name) - if err == nil { - return fmt.Errorf("key with name '%s' already exists", name) - } - } - - if !store && !export { - return fmt.Errorf("you must export key if not storing") + name := req.Arguments[0] + if name == "self" { + return fmt.Errorf("cannot create key with name 'self'") } opts := []options.KeyGenerateOption{options.Key.Type(typ)} @@ -146,52 +103,28 @@ var keyGenCmd = &cmds.Command{ if sizefound { opts = append(opts, options.Key.Size(size)) } - if err := verifyFormatLabel(req.Options[keyFormatOptionName].(string)); err != nil { - return err - } - - sk, pk, err := coreapi.GenerateKey(opts...) - if err != nil { + if err = verifyFormatLabel(req.Options[keyFormatOptionName].(string)); err != nil { return err } - if store { - err = r.Keystore().Put(name, sk) - if err != nil { - return err - } - } + key, err := api.Key().Generate(req.Context, name, opts...) - pid, err := peer.IDFromPublicKey(pk) if err != nil { return err } - var encoded string - if export { - encoded, err = encodeSKForExport(sk) - if err != nil { - return err - } - } - - return cmds.EmitOnce(res, &GenerateKeyOutput{ + return cmds.EmitOnce(res, &KeyOutput{ Name: name, - Id: formatID(pid, req.Options[keyFormatOptionName].(string)), - Sk: encoded, + Id: formatID(key.ID(), req.Options[keyFormatOptionName].(string)), }) }, Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, ko *GenerateKeyOutput) error { - if ko.Sk != "" { - _, err := w.Write([]byte(ko.Sk + "\n")) - return err - } + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, ko *KeyOutput) error { _, err := w.Write([]byte(ko.Id + "\n")) return err }), }, - Type: GenerateKeyOutput{}, + Type: KeyOutput{}, } func verifyFormatLabel(formatLabel string) error { diff --git a/core/coreapi/key.go b/core/coreapi/key.go index 5e8bda6df76..e6fe7b124d1 100644 --- a/core/coreapi/key.go +++ b/core/coreapi/key.go @@ -37,11 +37,21 @@ func (k *key) ID() peer.ID { return k.peerID } -// GenerateKey generates a new keypair and returns it -func GenerateKey(opts ...caopts.KeyGenerateOption) (crypto.PrivKey, crypto.PubKey, error) { +// Generate generates new key, stores it in the keystore under the specified +// name and returns a base58 encoded multihash of its public key. +func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.KeyGenerateOption) (coreiface.Key, error) { options, err := caopts.KeyGenerateOptions(opts...) if err != nil { - return nil, nil, err + return nil, err + } + + if name == "self" { + return nil, fmt.Errorf("cannot create key with name 'self'") + } + + _, err = api.repo.Keystore().Get(name) + if err == nil { + return nil, fmt.Errorf("key with name '%s' already exists", name) } var sk crypto.PrivKey @@ -55,7 +65,7 @@ func GenerateKey(opts ...caopts.KeyGenerateOption) (crypto.PrivKey, crypto.PubKe priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.RSA, options.Size, rand.Reader) if err != nil { - return nil, nil, err + return nil, err } sk = priv @@ -63,33 +73,13 @@ func GenerateKey(opts ...caopts.KeyGenerateOption) (crypto.PrivKey, crypto.PubKe case "ed25519": priv, pub, err := crypto.GenerateEd25519Key(rand.Reader) if err != nil { - return nil, nil, err + return nil, err } sk = priv pk = pub default: - return nil, nil, fmt.Errorf("unrecognized key type: %s", options.Algorithm) - } - - return sk, pk, nil -} - -// Generate generates new key, stores it in the keystore under the specified -// name and returns a base58 encoded multihash of its public key. -func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.KeyGenerateOption) (coreiface.Key, error) { - if name == "self" { - return nil, fmt.Errorf("cannot create key with name 'self'") - } - - _, err := api.repo.Keystore().Get(name) - if err == nil { - return nil, fmt.Errorf("key with name '%s' already exists", name) - } - - sk, pk, err := GenerateKey(opts...) - if err != nil { - return nil, err + return nil, fmt.Errorf("unrecognized key type: %s", options.Algorithm) } err = api.repo.Keystore().Put(name, sk) diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh index 8a96b57679e..bada4b525d8 100644 --- a/test/sharness/lib/test-lib.sh +++ b/test/sharness/lib/test-lib.sh @@ -493,10 +493,10 @@ test_check_rsa2048_sk() { test_check_ed25519_sk() { sklen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && - if (($sklen < 1600)); then + test "$sklen" = "93" || { echo "Bad ED25519 sk '$1' with len '$sklen'" return 1 - fi + } } convert_tcp_maddr() { diff --git a/test/sharness/t0165-keystore.sh b/test/sharness/t0165-keystore.sh index ecc7facb107..2f57bc99c7a 100755 --- a/test/sharness/t0165-keystore.sh +++ b/test/sharness/t0165-keystore.sh @@ -11,22 +11,6 @@ test_description="Test keystore commands" test_init_ipfs test_key_cmd() { - test_expect_success "export with no store doesn't store" ' - ipfs key gen -n -e && echo self > list_exp && - ipfs key list > list_out && - test_sort_cmp list_exp list_out - ' - - test_expect_success "no store without export is an error" ' - test_must_fail ipfs key gen -n 2>&1 | tee key_gen_out && - grep -q "you must export key" key_gen_out - ' - - test_expect_success "key gen without name is an error" ' - test_must_fail ipfs key gen 2>&1 | tee key_gen_out && - grep -q "you must specify a key name" key_gen_out - ' - # test key output format test_expect_success "create an RSA key and test B58MH multihash output" ' PEERID=$(ipfs key gen -f=b58mh --type=rsa --size=2048 key_rsa) && @@ -49,10 +33,9 @@ PEERID=$(ipfs key gen -f=b36cid --type=ed25519 key_ed25519) && test_check_ed25519_b36cid_peerid $PEERID ' -test_expect_success "create and export an ED25519 key" ' -SK=$(ipfs key gen -e key_ed25519_2) && -test_check_ed25519_sk $SK && -ipfs key rm key_ed25519_2 +test_expect_success "test ED25519 key sk export format" ' +SK=$(ipfs key export key_ed25519) && +test_check_ed25519_sk $SK ' test_expect_success "test ED25519 key B36CID multihash format" ' @@ -76,7 +59,7 @@ ipfs key rm key_ed25519 imphash=$(ipfs key import -f=b58mh quxel $(cat importkey)) ' - test_expect_success "export an rsa key" ' + test_expect_success "exported key matches imported" ' ipfs key export quxel >> exportkey && test_cmp importkey exportkey ' From 7f15be2ae570fea8f7a9b019b6863cd8adfb7798 Mon Sep 17 00:00:00 2001 From: Adin Schmahmann Date: Mon, 3 Aug 2020 15:46:15 -0400 Subject: [PATCH 5/6] switch ipfs key import/export to use files instead of strings --- core/commands/keystore.go | 79 +++++++++++++++++++++----------- test/sharness/lib/test-lib.sh | 16 ------- test/sharness/t0165-keystore.sh | 81 +++++++++++++++++++++++++-------- 3 files changed, 113 insertions(+), 63 deletions(-) diff --git a/core/commands/keystore.go b/core/commands/keystore.go index a34fdcc8090..abf0dc8a229 100644 --- a/core/commands/keystore.go +++ b/core/commands/keystore.go @@ -1,17 +1,20 @@ package commands import ( + "bytes" "fmt" "io" + "io/ioutil" + "os" "text/tabwriter" cmds "github.com/ipfs/go-ipfs-cmds" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" + "github.com/ipfs/go-ipfs/core/commands/e" 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" - "github.com/mr-tron/base58/base58" mbase "github.com/multiformats/go-multibase" ) @@ -47,10 +50,6 @@ type KeyOutput struct { Id string } -type ExportKeyOutput struct { - Sk string -} - type KeyOutputList struct { Keys []KeyOutput } @@ -152,22 +151,22 @@ func formatID(id peer.ID, formatLabel string) string { } } -func encodeSKForExport(sk crypto.PrivKey) (string, error) { - data, err := crypto.MarshalPrivateKey(sk) - if err != nil { - return "", err - } - return base58.Encode(data), nil -} - var keyExportCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Export a keypair", + ShortDescription: ` +Exports a named libp2p key to disk. + +By default, the output will be stored at './', but an alternate +path can be specified with '--output=' or '-o='. +`, }, Arguments: []cmds.Argument{ cmds.StringArg("name", true, false, "name of key to export").EnableStdin(), }, - Options: []cmds.Option{}, + Options: []cmds.Option{ + cmds.StringOption(outputOptionName, "o", "The path where the output should be stored."), + }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { name := req.Arguments[0] @@ -191,22 +190,44 @@ var keyExportCmd = &cmds.Command{ return fmt.Errorf("key with name '%s' doesn't exist", name) } - encoded, err := encodeSKForExport(sk) + encoded, err := crypto.MarshalPrivateKey(sk) if err != nil { return err } - return cmds.EmitOnce(res, &ExportKeyOutput{ - Sk: encoded, - }) + return res.Emit(bytes.NewReader(encoded)) }, - Encoders: cmds.EncoderMap{ - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, ko *ExportKeyOutput) error { - _, err := w.Write([]byte(ko.Sk + "\n")) - return err - }), + PostRun: cmds.PostRunMap{ + cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error { + req := res.Request() + + v, err := res.Next() + if err != nil { + return err + } + + outReader, ok := v.(io.Reader) + if !ok { + return e.New(e.TypeErr(outReader, v)) + } + + outPath := getOutPath(req) + + // create file + file, err := os.Create(outPath) + if err != nil { + return err + } + defer file.Close() + + _, err = io.Copy(file, outReader) + if err != nil { + return err + } + + return nil + }, }, - Type: ExportKeyOutput{}, } var keyImportCmd = &cmds.Command{ @@ -218,7 +239,7 @@ var keyImportCmd = &cmds.Command{ }, Arguments: []cmds.Argument{ cmds.StringArg("name", true, false, "name to associate with key in keychain"), - cmds.StringArg("key", true, false, "key provided by generate or export"), + cmds.FileArg("key", true, false, "key provided by generate or export"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { name := req.Arguments[0] @@ -227,9 +248,13 @@ var keyImportCmd = &cmds.Command{ return fmt.Errorf("cannot import key with name 'self'") } - encoded := req.Arguments[1] + file, err := cmdenv.GetFileArg(req.Files.Entries()) + if err != nil { + return err + } + defer file.Close() - data, err := base58.Decode(encoded) + data, err := ioutil.ReadAll(file) if err != nil { return err } diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh index bada4b525d8..c7169717519 100644 --- a/test/sharness/lib/test-lib.sh +++ b/test/sharness/lib/test-lib.sh @@ -483,22 +483,6 @@ test_check_ed25519_b36cid_peerid() { } } -test_check_rsa2048_sk() { - sklen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && - if (($sklen < 1600)); then - echo "Bad RSA2048 sk '$1' with len '$sklen'" - return 1 - fi -} - -test_check_ed25519_sk() { - sklen=$(echo "$1" | tr -dC "[:alnum:]" | wc -c | tr -d " ") && - test "$sklen" = "93" || { - echo "Bad ED25519 sk '$1' with len '$sklen'" - return 1 - } -} - convert_tcp_maddr() { echo $1 | awk -F'/' '{ printf "%s:%s", $3, $5 }' } diff --git a/test/sharness/t0165-keystore.sh b/test/sharness/t0165-keystore.sh index 2f57bc99c7a..035c7e1e2db 100755 --- a/test/sharness/t0165-keystore.sh +++ b/test/sharness/t0165-keystore.sh @@ -18,8 +18,9 @@ test_check_rsa2048_b58mh_peerid $PEERID ' test_expect_success "test RSA key sk export format" ' -SK=$(ipfs key export key_rsa) && -test_check_rsa2048_sk $SK +ipfs key export key_rsa && +test_check_rsa2048_sk key_rsa && +rm key_rsa ' test_expect_success "test RSA key B36CID multihash format" ' @@ -34,8 +35,9 @@ test_check_ed25519_b36cid_peerid $PEERID ' test_expect_success "test ED25519 key sk export format" ' -SK=$(ipfs key export key_ed25519) && -test_check_ed25519_sk $SK +ipfs key export key_ed25519 && +test_check_ed25519_sk key_ed25519 && +rm key_ed25519 ' test_expect_success "test ED25519 key B36CID multihash format" ' @@ -47,36 +49,59 @@ ipfs key rm key_ed25519 test_expect_success "create a new rsa key" ' - rsahash=$(ipfs key gen -f=b58mh foobarsa --type=rsa --size=2048) + rsahash=$(ipfs key gen -f=b58mh generated_rsa_key --type=rsa --size=2048) + echo $rsahash > rsa_key_id ' test_expect_success "create a new ed25519 key" ' - edhash=$(ipfs key gen -f=b58mh bazed --type=ed25519) + edhash=$(ipfs key gen -f=b58mh generated_ed25519_key --type=ed25519) + echo $edhash > ed25519_key_id ' - - test_expect_success "import an rsa key" ' - echo "B9bLmHeKLQU1hX23meSn2kJiNW7AZ31C6PBNSYumejXB13vxSVvViZDkEnchAH4BTs9yVnBNZKZYLwykaCohzxTntesTCVaBhZR2Br2Swav2NXwVBhfrUbaBTrR2248KfbVxSiUdkpFn8kcAmUGwp2KGMGRmq85WreGFDdAvzz8ruN2EFfWSHLc1YeUxHeUgKsQm3N13uF7q5x4qvjWM6yvMWNY7JtZrihT8BZQhgb2ezR4iYPjXZTtPZWsLbrrhUvHhxSn1NsTw6NZ7Jbs84qMXXnH56BmT8J9LugRhQQvgBquSoS1m7aeD2y1L1A7mueVDYGLDzgxRSt5CohY7VVMdheUpPiq44CicuYt5YgbbuE3wMHntn6sd9QSYw7f4SjjKdw7Jhy5fNW29SkHvpLfZKfqzBNhSfHsofXVEASDpfr5mqws1eQTztqvvZhHXQxAoxxP3PK6TfDnATdLdV3Cy5v6nLt7ppsBj54hif5EZneHMLeYP8bYLbELQ2fZdoprpnKVBsMY1nWvgrMKUTpLjoKB6bzAZYuXaYVtmrdhESmKCyE12yEyvCcD8DJQU6JjqaD1DyVSPNkL3ze26Mm3ZyiFEH7M4XirUsPLrsj41Qt1xGaVGNEdkdthihytTZxxnmgyAptZMUNfSviBfH1tVbfoXFtBGU8eYMLdSHFqxSktT1mqeiWatxMQZ8pTeA9VCvAp9RTSRFkTQR9uP6w6qTzRD9cFcH4HyCEc5TJpiZdP7u9RjaEo2S3P9VkHfmqCH4McpLgw7He9nm7rf9JA2Gh7ubTKy5e6dJUWojgYhGS4KGe3yKGFhLaNgRiME63fUEFSnN2ZvCSM9qsrj34q2h8962xBod9hCVEDfk4tfmHu1UHX5AGaW6mk3pzqKKVYTTWXi84JSH7vzKPmQuhwaAR9Ye3Jbdzehp4xhrT5aFCjnz3r5qNv2zz48Fq5bGc1RUh88PUMT3z6kuzv6B1eXTLYpeu9gGdjc5C9DQDTYPfcHWn7dSHr4AGV1sN6SwVy8W5LZdMAZaeXCDn9iXDwbeD2DYd2ozVCEzceygVzpVdnueNx5FmG6zHtGzfuStr4Jj85sbd2jUGh4ES2bMU41jw2gJ6ujjf6CrxZpCWhXz6NJpAS9njcDFXuspf7otbMjCB6TzwokJwEse31nGUZQdhQgXn23vnZtxwCV621uXFbm7xVACRZKeuXgw8VdEVaXGvf2V4DdhjZnjmePBbTeJ7WjABavLcpMqZJH7FgaLxazFqk9RXtnfUEbVAAhuZzxz6L8Z6axHwz3a4EZtALRjfFjn6xjaUtsWXYW8P6F7femM6UHx3qXMo43hKC7oxnd6Tfta972dgyQfSoBwWkWzB8cvaJreNh4bdLNkw6mty86NXGKyijv83LR1HjbnUoTwPbEMX8JyzLfMf3qiWzwf6MHrXprwygmEpNc6w8tNNivmcWyCX3wmPkMKK1bmi5TCHoUtRrxcyXKhmuyo6zzag8KyK6iZaRbMiFiUJBi5VYwidMutkexWo8SRqfSV5yp2kxswknmpeVTnXBhVEy3anMEiD6bV48AnbF6SfKAi2DGBFqxBFfpFEbYtPauHiYYzZX1epqvKxY23xA9J8FosMk4yYN4Ps7Rh" >> importkey - imphash=$(ipfs key import -f=b58mh quxel $(cat importkey)) + + test_expect_success "export and import rsa key" ' + ipfs key export generated_rsa_key && + ipfs key rm generated_rsa_key && + ipfs key import generated_rsa_key generated_rsa_key > roundtrip_rsa_key_id && + test_cmp rsa_key_id roundtrip_rsa_key_id ' - test_expect_success "exported key matches imported" ' - ipfs key export quxel >> exportkey && - test_cmp importkey exportkey + test_expect_success "export and import ed25519 key" ' + ipfs key export generated_ed25519_key && + ipfs key rm generated_ed25519_key && + ipfs key import generated_ed25519_key generated_ed25519_key > roundtrip_ed25519_key_id && + test_cmp ed25519_key_id roundtrip_ed25519_key_id + ' + + test_expect_success "test export file option" ' + ipfs key export generated_rsa_key -o=named_rsa_export_file && + test_cmp generated_rsa_key named_rsa_export_file && + ipfs key export generated_ed25519_key -o=named_ed25519_export_file && + test_cmp generated_ed25519_key named_ed25519_export_file ' test_expect_success "key export can't export self" ' test_must_fail ipfs key export self 2>&1 | tee key_exp_out && + grep -q "Error: cannot export key with name" key_exp_out && + test_must_fail ipfs key export self -o=selfexport 2>&1 | tee key_exp_out && grep -q "Error: cannot export key with name" key_exp_out ' test_expect_success "key import can't import self" ' - test_must_fail ipfs key import self $(cat importkey) 2>&1 | tee key_imp_out && - grep -q "Error: cannot import key with name" key_imp_out + ipfs key gen overwrite_self_import && + ipfs key export overwrite_self_import && + test_must_fail ipfs key import self overwrite_self_import 2>&1 | tee key_imp_out && + grep -q "Error: cannot import key with name" key_imp_out && + ipfs key rm overwrite_self_import && + rm overwrite_self_import + ' + + test_expect_success "add a default key" ' + ipfs key gen quxel ' test_expect_success "all keys show up in list output" ' - echo bazed > list_exp && - echo foobarsa >> list_exp && + echo generated_ed25519_key > list_exp && + echo generated_rsa_key >> list_exp && echo quxel >> list_exp && echo self >> list_exp ipfs key list -f=b58mh > list_out && @@ -94,8 +119,8 @@ ipfs key rm key_ed25519 ' test_expect_success "key rm remove a key" ' - ipfs key rm foobarsa - echo bazed > list_exp && + ipfs key rm generated_rsa_key + echo generated_ed25519_key > list_exp && echo quxel >> list_exp && echo self >> list_exp ipfs key list -f=b58mh > list_out && @@ -108,7 +133,7 @@ ipfs key rm key_ed25519 ' test_expect_success "key rename rename a key" ' - ipfs key rename bazed fooed + ipfs key rename generated_ed25519_key fooed echo fooed > list_exp && echo quxel >> list_exp && echo self >> list_exp @@ -134,6 +159,22 @@ ipfs key rm key_ed25519 ' } +test_check_rsa2048_sk() { + sklen=$(ls -l $1 | awk '{print $5}') && + test "$sklen" -lt "1600" && test "$sklen" -gt "1000" || { + echo "Bad RSA2048 sk '$1' with len '$sklen'" + return 1 + } +} + +test_check_ed25519_sk() { + sklen=$(ls -l $1 | awk '{print $5}') && + test "$sklen" -lt "100" && test "$sklen" -gt "30" || { + echo "Bad ED25519 sk '$1' with len '$sklen'" + return 1 + } +} + test_key_cmd test_done From fab3a3578d8f5f9b9de4a262a6015d0bf210429b Mon Sep 17 00:00:00 2001 From: Adin Schmahmann Date: Mon, 3 Aug 2020 17:28:55 -0400 Subject: [PATCH 6/6] ipfs key export output keys with .key extension by default --- core/commands/keystore.go | 11 +++++++++-- test/sharness/t0165-keystore.sh | 20 ++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/core/commands/keystore.go b/core/commands/keystore.go index abf0dc8a229..9089caf6053 100644 --- a/core/commands/keystore.go +++ b/core/commands/keystore.go @@ -6,6 +6,8 @@ import ( "io" "io/ioutil" "os" + "path/filepath" + "strings" "text/tabwriter" cmds "github.com/ipfs/go-ipfs-cmds" @@ -157,7 +159,7 @@ var keyExportCmd = &cmds.Command{ ShortDescription: ` Exports a named libp2p key to disk. -By default, the output will be stored at './', but an alternate +By default, the output will be stored at './.key', but an alternate path can be specified with '--output=' or '-o='. `, }, @@ -211,7 +213,12 @@ path can be specified with '--output=' or '-o='. return e.New(e.TypeErr(outReader, v)) } - outPath := getOutPath(req) + outPath, _ := req.Options[outputOptionName].(string) + if outPath == "" { + trimmed := strings.TrimRight(fmt.Sprintf("%s.key", req.Arguments[0]), "/") + _, outPath = filepath.Split(trimmed) + outPath = filepath.Clean(outPath) + } // create file file, err := os.Create(outPath) diff --git a/test/sharness/t0165-keystore.sh b/test/sharness/t0165-keystore.sh index 035c7e1e2db..f75c0d5d30f 100755 --- a/test/sharness/t0165-keystore.sh +++ b/test/sharness/t0165-keystore.sh @@ -19,8 +19,8 @@ test_check_rsa2048_b58mh_peerid $PEERID test_expect_success "test RSA key sk export format" ' ipfs key export key_rsa && -test_check_rsa2048_sk key_rsa && -rm key_rsa +test_check_rsa2048_sk key_rsa.key && +rm key_rsa.key ' test_expect_success "test RSA key B36CID multihash format" ' @@ -36,8 +36,8 @@ test_check_ed25519_b36cid_peerid $PEERID test_expect_success "test ED25519 key sk export format" ' ipfs key export key_ed25519 && -test_check_ed25519_sk key_ed25519 && -rm key_ed25519 +test_check_ed25519_sk key_ed25519.key && +rm key_ed25519.key ' test_expect_success "test ED25519 key B36CID multihash format" ' @@ -61,22 +61,22 @@ ipfs key rm key_ed25519 test_expect_success "export and import rsa key" ' ipfs key export generated_rsa_key && ipfs key rm generated_rsa_key && - ipfs key import generated_rsa_key generated_rsa_key > roundtrip_rsa_key_id && + ipfs key import generated_rsa_key generated_rsa_key.key > roundtrip_rsa_key_id && test_cmp rsa_key_id roundtrip_rsa_key_id ' test_expect_success "export and import ed25519 key" ' ipfs key export generated_ed25519_key && ipfs key rm generated_ed25519_key && - ipfs key import generated_ed25519_key generated_ed25519_key > roundtrip_ed25519_key_id && + ipfs key import generated_ed25519_key generated_ed25519_key.key > roundtrip_ed25519_key_id && test_cmp ed25519_key_id roundtrip_ed25519_key_id ' test_expect_success "test export file option" ' ipfs key export generated_rsa_key -o=named_rsa_export_file && - test_cmp generated_rsa_key named_rsa_export_file && + test_cmp generated_rsa_key.key named_rsa_export_file && ipfs key export generated_ed25519_key -o=named_ed25519_export_file && - test_cmp generated_ed25519_key named_ed25519_export_file + test_cmp generated_ed25519_key.key named_ed25519_export_file ' test_expect_success "key export can't export self" ' @@ -89,10 +89,10 @@ ipfs key rm key_ed25519 test_expect_success "key import can't import self" ' ipfs key gen overwrite_self_import && ipfs key export overwrite_self_import && - test_must_fail ipfs key import self overwrite_self_import 2>&1 | tee key_imp_out && + test_must_fail ipfs key import self overwrite_self_import.key 2>&1 | tee key_imp_out && grep -q "Error: cannot import key with name" key_imp_out && ipfs key rm overwrite_self_import && - rm overwrite_self_import + rm overwrite_self_import.key ' test_expect_success "add a default key" '