mirror of
https://github.com/ipfs/kubo.git
synced 2025-10-13 01:37:02 +08:00
add init command to generate crypto keys
This commit is contained in:
81
cmd/ipfs/init.go
Normal file
81
cmd/ipfs/init.go
Normal file
@ -0,0 +1,81 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/gonuts/flag"
|
||||
"github.com/jbenet/commander"
|
||||
config "github.com/jbenet/go-ipfs/config"
|
||||
"github.com/jbenet/go-ipfs/identify"
|
||||
u "github.com/jbenet/go-ipfs/util"
|
||||
)
|
||||
|
||||
var cmdIpfsInit = &commander.Command{
|
||||
UsageLine: "init",
|
||||
Short: "Initialize ipfs local configuration",
|
||||
Long: `ipfs init
|
||||
|
||||
Initializes ipfs configuration files and generates a
|
||||
new keypair.
|
||||
`,
|
||||
Run: initCmd,
|
||||
Flag: *flag.NewFlagSet("ipfs-init", flag.ExitOnError),
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdIpfsInit.Flag.Int("b", 4096, "number of bits for keypair")
|
||||
cmdIpfsInit.Flag.String("p", "", "passphrase for encrypting keys")
|
||||
cmdIpfsInit.Flag.Bool("f", false, "force overwrite of existing config")
|
||||
}
|
||||
|
||||
func initCmd(c *commander.Command, inp []string) error {
|
||||
_, err := os.Lstat(config.DefaultConfigFilePath)
|
||||
force := c.Flag.Lookup("f").Value.Get().(bool)
|
||||
if err != nil && !force {
|
||||
return errors.New("ipfs configuration file already exists!\nReinitializing would overwrite your keys.\n(use -f to force overwrite)")
|
||||
}
|
||||
cfg := new(config.Config)
|
||||
|
||||
cfg.Datastore = new(config.Datastore)
|
||||
dspath, err := u.TildeExpansion("~/.go-ipfs/datastore")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.Datastore.Path = dspath
|
||||
cfg.Datastore.Type = "leveldb"
|
||||
|
||||
cfg.Identity = new(config.Identity)
|
||||
// This needs thought
|
||||
// cfg.Identity.Address = ""
|
||||
|
||||
nbits := c.Flag.Lookup("b").Value.Get().(int)
|
||||
if nbits < 1024 {
|
||||
return errors.New("Bitsize less than 1024 is considered unsafe.")
|
||||
}
|
||||
kp, err := identify.GenKeypair(nbits)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// pretend to encrypt key, then store it unencrypted
|
||||
enckey := base64.StdEncoding.EncodeToString(kp.PrivBytes())
|
||||
cfg.Identity.PrivKey = enckey
|
||||
|
||||
id, err := kp.ID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.Identity.PeerID = id.Pretty()
|
||||
|
||||
path, err := u.TildeExpansion(config.DefaultConfigFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = config.WriteConfigFile(path, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -46,6 +46,7 @@ Use "ipfs help <command>" for more information about a command.
|
||||
cmdIpfsVersion,
|
||||
cmdIpfsCommands,
|
||||
cmdIpfsMount,
|
||||
cmdIpfsInit,
|
||||
},
|
||||
Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
u "github.com/jbenet/go-ipfs/util"
|
||||
@ -9,6 +13,7 @@ import (
|
||||
// Identity tracks the configuration of the local node's identity.
|
||||
type Identity struct {
|
||||
PeerID string
|
||||
PrivKey string
|
||||
Address string
|
||||
}
|
||||
|
||||
@ -29,8 +34,8 @@ type Config struct {
|
||||
Peers []*SavedPeer
|
||||
}
|
||||
|
||||
var defaultConfigFilePath = "~/.go-ipfs/config"
|
||||
var defaultConfigFile = `{
|
||||
var DefaultConfigFilePath = "~/.go-ipfs/config"
|
||||
var DefaultConfigFile = `{
|
||||
"identity": {},
|
||||
"datastore": {
|
||||
"type": "leveldb",
|
||||
@ -39,10 +44,20 @@ var defaultConfigFile = `{
|
||||
}
|
||||
`
|
||||
|
||||
func (i *Identity) DecodePrivateKey(passphrase string) (crypto.PrivateKey, error) {
|
||||
pkb, err := base64.StdEncoding.DecodeString(i.PrivKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//pretend to actually decrypt private key
|
||||
return x509.ParsePKCS1PrivateKey(pkb)
|
||||
}
|
||||
|
||||
// Filename returns the proper tilde expanded config filename.
|
||||
func Filename(filename string) (string, error) {
|
||||
if len(filename) == 0 {
|
||||
filename = defaultConfigFilePath
|
||||
filename = DefaultConfigFilePath
|
||||
}
|
||||
|
||||
// tilde expansion on config file
|
||||
@ -56,11 +71,9 @@ func Load(filename string) (*Config, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if nothing is there, write first config file.
|
||||
// if nothing is there, fail. User must run 'ipfs init'
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
if err := WriteFile(filename, []byte(defaultConfigFile)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, errors.New("ipfs not initialized, please run 'ipfs init'")
|
||||
}
|
||||
|
||||
var cfg Config
|
||||
@ -80,5 +93,5 @@ func Load(filename string) (*Config, error) {
|
||||
|
||||
// Set sets the value of a particular config key
|
||||
func Set(filename, key, value string) error {
|
||||
return nil
|
||||
return WriteConfigKey(filename, key, value)
|
||||
}
|
||||
|
28
core/core.go
28
core/core.go
@ -1,12 +1,17 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
ds "github.com/jbenet/datastore.go"
|
||||
b58 "github.com/jbenet/go-base58"
|
||||
"github.com/jbenet/go-ipfs/bitswap"
|
||||
bserv "github.com/jbenet/go-ipfs/blockservice"
|
||||
config "github.com/jbenet/go-ipfs/config"
|
||||
"github.com/jbenet/go-ipfs/identify"
|
||||
merkledag "github.com/jbenet/go-ipfs/merkledag"
|
||||
path "github.com/jbenet/go-ipfs/path"
|
||||
peer "github.com/jbenet/go-ipfs/peer"
|
||||
@ -98,17 +103,28 @@ func loadBitswap(cfg *config.Config, d ds.Datastore) (*bitswap.BitSwap, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pk, err := cfg.Identity.DecodePrivateKey("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pubkey crypto.PublicKey
|
||||
switch k := pk.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
pubkey = &k.PublicKey
|
||||
default:
|
||||
return nil, identify.ErrUnsupportedKeyType
|
||||
}
|
||||
|
||||
local := &peer.Peer{
|
||||
ID: peer.ID(cfg.Identity.PeerID),
|
||||
ID: peer.ID(b58.Decode(cfg.Identity.PeerID)),
|
||||
Addresses: []*ma.Multiaddr{maddr},
|
||||
PrivKey: pk,
|
||||
PubKey: pubkey,
|
||||
}
|
||||
|
||||
if len(local.ID) == 0 {
|
||||
mh, err := u.Hash([]byte("blah blah blah ID"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
local.ID = peer.ID(mh)
|
||||
return nil, errors.New("No peer ID in config! (was ipfs init run?)")
|
||||
}
|
||||
|
||||
net := swarm.NewSwarm(local)
|
||||
|
@ -16,6 +16,9 @@ import (
|
||||
u "github.com/jbenet/go-ipfs/util"
|
||||
)
|
||||
|
||||
// ErrUnsupportedKeyType is returned when a private key cast/type switch fails.
|
||||
var ErrUnsupportedKeyType = errors.New("unsupported key type")
|
||||
|
||||
// Perform initial communication with this peer to share node ID's and
|
||||
// initiate communication
|
||||
func Handshake(self, remote *peer.Peer, in, out chan []byte) error {
|
||||
@ -151,6 +154,15 @@ func (pk *KeyPair) ID() (peer.ID, error) {
|
||||
return peer.ID(hash), nil
|
||||
}
|
||||
|
||||
func (pk *KeyPair) PrivBytes() []byte {
|
||||
switch k := pk.Priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return x509.MarshalPKCS1PrivateKey(k)
|
||||
default:
|
||||
panic("Unsupported private key type.")
|
||||
}
|
||||
}
|
||||
|
||||
func (kp *KeyPair) Save(dir string) error {
|
||||
switch k := kp.Priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
|
Reference in New Issue
Block a user