Commit aa5a34a6 authored by Jeromy's avatar Jeromy

add init command to generate crypto keys

parent a5d54ea2
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),
}
......
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)
}
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:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment