Commit 4b97f1f2 authored by Jeromy's avatar Jeromy

create new crypto package and make rest of repo use it

parent aa5a34a6
......@@ -8,7 +8,8 @@ import (
"github.com/gonuts/flag"
"github.com/jbenet/commander"
config "github.com/jbenet/go-ipfs/config"
"github.com/jbenet/go-ipfs/identify"
ci "github.com/jbenet/go-ipfs/crypto"
identify "github.com/jbenet/go-ipfs/identify"
u "github.com/jbenet/go-ipfs/util"
)
......@@ -54,16 +55,20 @@ func initCmd(c *commander.Command, inp []string) error {
if nbits < 1024 {
return errors.New("Bitsize less than 1024 is considered unsafe.")
}
kp, err := identify.GenKeypair(nbits)
sk, pk, err := ci.GenerateKeyPair(ci.RSA, nbits)
if err != nil {
return err
}
// pretend to encrypt key, then store it unencrypted
enckey := base64.StdEncoding.EncodeToString(kp.PrivBytes())
cfg.Identity.PrivKey = enckey
skbytes, err := sk.Bytes()
if err != nil {
return err
}
cfg.Identity.PrivKey = base64.StdEncoding.EncodeToString(skbytes)
id, err := kp.ID()
id, err := identify.IdFromPubKey(pk)
if err != nil {
return err
}
......
package core
import (
"crypto"
"crypto/rsa"
"encoding/base64"
"errors"
"fmt"
......@@ -11,7 +10,7 @@ import (
"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"
ci "github.com/jbenet/go-ipfs/crypto"
merkledag "github.com/jbenet/go-ipfs/merkledag"
path "github.com/jbenet/go-ipfs/path"
peer "github.com/jbenet/go-ipfs/peer"
......@@ -103,24 +102,21 @@ func loadBitswap(cfg *config.Config, d ds.Datastore) (*bitswap.BitSwap, error) {
return nil, err
}
pk, err := cfg.Identity.DecodePrivateKey("")
skb, err := base64.StdEncoding.DecodeString(cfg.Identity.PrivKey)
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
sk, err := ci.UnmarshalPrivateKey(skb)
if err != nil {
return nil, err
}
local := &peer.Peer{
ID: peer.ID(b58.Decode(cfg.Identity.PeerID)),
Addresses: []*ma.Multiaddr{maddr},
PrivKey: pk,
PubKey: pubkey,
PrivKey: sk,
PubKey: sk.GetPublic(),
}
if len(local.ID) == 0 {
......
// Code generated by protoc-gen-go.
// source: encode.proto
// DO NOT EDIT!
/*
Package crypto is a generated protocol buffer package.
It is generated from these files:
encode.proto
It has these top-level messages:
PBPublicKey
PBPrivateKey
*/
package crypto
import proto "code.google.com/p/goprotobuf/proto"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = math.Inf
type KeyType int32
const (
KeyType_RSA KeyType = 0
)
var KeyType_name = map[int32]string{
0: "RSA",
}
var KeyType_value = map[string]int32{
"RSA": 0,
}
func (x KeyType) Enum() *KeyType {
p := new(KeyType)
*p = x
return p
}
func (x KeyType) String() string {
return proto.EnumName(KeyType_name, int32(x))
}
func (x *KeyType) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(KeyType_value, data, "KeyType")
if err != nil {
return err
}
*x = KeyType(value)
return nil
}
type PBPublicKey struct {
Type *KeyType `protobuf:"varint,1,req,enum=crypto.KeyType" json:"Type,omitempty"`
Data []byte `protobuf:"bytes,2,req" json:"Data,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *PBPublicKey) Reset() { *m = PBPublicKey{} }
func (m *PBPublicKey) String() string { return proto.CompactTextString(m) }
func (*PBPublicKey) ProtoMessage() {}
func (m *PBPublicKey) GetType() KeyType {
if m != nil && m.Type != nil {
return *m.Type
}
return KeyType_RSA
}
func (m *PBPublicKey) GetData() []byte {
if m != nil {
return m.Data
}
return nil
}
type PBPrivateKey struct {
Type *KeyType `protobuf:"varint,1,req,enum=crypto.KeyType" json:"Type,omitempty"`
Data []byte `protobuf:"bytes,2,req" json:"Data,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *PBPrivateKey) Reset() { *m = PBPrivateKey{} }
func (m *PBPrivateKey) String() string { return proto.CompactTextString(m) }
func (*PBPrivateKey) ProtoMessage() {}
func (m *PBPrivateKey) GetType() KeyType {
if m != nil && m.Type != nil {
return *m.Type
}
return KeyType_RSA
}
func (m *PBPrivateKey) GetData() []byte {
if m != nil {
return m.Data
}
return nil
}
func init() {
proto.RegisterEnum("crypto.KeyType", KeyType_name, KeyType_value)
}
package crypto;
enum KeyType {
RSA = 0;
}
message PBPublicKey {
required KeyType Type = 1;
required bytes Data = 2;
}
message PBPrivateKey {
required KeyType Type = 1;
required bytes Data = 2;
}
package crypto
import (
"errors"
"crypto/rand"
"crypto/rsa"
"code.google.com/p/goprotobuf/proto"
)
var ErrBadKeyType = errors.New("invalid or unsupported key type")
const (
RSA = iota
)
type PrivKey interface {
// Cryptographically sign the given bytes
Sign([]byte) ([]byte, error)
// Decrypt a message encrypted with this keys public key
Decrypt([]byte) ([]byte, error)
// Return a public key paired with this private key
GetPublic() PubKey
// Generate a secret string of bytes
GenSecret() []byte
// Bytes returns a serialized, storeable representation of this key
Bytes() ([]byte, error)
}
type PubKey interface {
// Verify that 'sig' is the signed hash of 'data'
Verify(data []byte, sig []byte) (bool, error)
// Encrypt the given data with the public key
Encrypt([]byte) ([]byte, error)
// Bytes returns a serialized, storeable representation of this key
Bytes() ([]byte, error)
}
func GenerateKeyPair(typ, bits int) (PrivKey, PubKey, error) {
switch typ {
case RSA:
priv, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, nil, err
}
pk := &priv.PublicKey
return &RsaPrivateKey{priv}, &RsaPublicKey{pk}, nil
default:
return nil, nil, ErrBadKeyType
}
}
func UnmarshalPublicKey(data []byte) (PubKey, error) {
pmes := new(PBPublicKey)
err := proto.Unmarshal(data, pmes)
if err != nil {
return nil, err
}
switch pmes.GetType() {
case KeyType_RSA:
return UnmarshalRsaPublicKey(pmes.GetData())
default:
return nil, ErrBadKeyType
}
}
func UnmarshalPrivateKey(data []byte) (PrivKey, error) {
pmes := new(PBPrivateKey)
err := proto.Unmarshal(data, pmes)
if err != nil {
return nil, err
}
switch pmes.GetType() {
case KeyType_RSA:
return UnmarshalRsaPrivateKey(pmes.GetData())
default:
return nil, ErrBadKeyType
}
}
package crypto
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"errors"
"code.google.com/p/goprotobuf/proto"
)
type RsaPrivateKey struct {
k *rsa.PrivateKey
}
type RsaPublicKey struct {
k *rsa.PublicKey
}
func (pk *RsaPublicKey) Verify(data, sig []byte) (bool, error) {
hashed := sha256.Sum256(data)
err := rsa.VerifyPKCS1v15(pk.k, crypto.SHA256, hashed[:], sig)
if err != nil {
return false, err
}
return true, nil
}
func (pk *RsaPublicKey) Encrypt(message []byte) ([]byte, error) {
return rsa.EncryptPKCS1v15(rand.Reader, pk.k, message)
}
func (pk *RsaPublicKey) Bytes() ([]byte, error) {
b, err := x509.MarshalPKIXPublicKey(pk.k)
if err != nil {
return nil, err
}
pbmes := new(PBPublicKey)
typ := KeyType_RSA
pbmes.Type = &typ
pbmes.Data = b
return proto.Marshal(pbmes)
}
func (sk *RsaPrivateKey) GenSecret() []byte {
buf := make([]byte, 16)
rand.Read(buf)
return buf
}
func (sk *RsaPrivateKey) Sign(message []byte) ([]byte, error) {
hashed := sha256.Sum256(message)
return rsa.SignPKCS1v15(rand.Reader, sk.k, crypto.SHA256, hashed[:])
}
func (sk *RsaPrivateKey) Decrypt(ciphertext []byte) ([]byte, error) {
return rsa.DecryptPKCS1v15(rand.Reader, sk.k, ciphertext)
}
func (sk *RsaPrivateKey) GetPublic() PubKey {
return &RsaPublicKey{&sk.k.PublicKey}
}
func (sk *RsaPrivateKey) Bytes() ([]byte, error) {
b := x509.MarshalPKCS1PrivateKey(sk.k)
pbmes := new(PBPrivateKey)
typ := KeyType_RSA
pbmes.Type = &typ
pbmes.Data = b
return proto.Marshal(pbmes)
}
func UnmarshalRsaPrivateKey(b []byte) (*RsaPrivateKey, error) {
sk, err := x509.ParsePKCS1PrivateKey(b)
if err != nil {
return nil, err
}
return &RsaPrivateKey{sk}, nil
}
func UnmarshalRsaPublicKey(b []byte) (*RsaPublicKey, error) {
pub, err := x509.ParsePKIXPublicKey(b)
if err != nil {
return nil, err
}
pk, ok := pub.(*rsa.PublicKey)
if !ok {
return nil, errors.New("Not actually an rsa public key.")
}
return &RsaPublicKey{pk}, nil
}
......@@ -4,14 +4,10 @@ package identify
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"errors"
"io/ioutil"
proto "code.google.com/p/goprotobuf/proto"
ci "github.com/jbenet/go-ipfs/crypto"
peer "github.com/jbenet/go-ipfs/peer"
u "github.com/jbenet/go-ipfs/util"
)
......@@ -40,15 +36,14 @@ func Handshake(self, remote *peer.Peer, in, out chan []byte) error {
return verifyErr
}
pubkey, err := x509.ParsePKIXPublicKey(pbresp.GetPubkey())
pubkey, err := ci.UnmarshalPublicKey(pbresp.GetPubkey())
if err != nil {
return err
}
// Challenge peer to ensure they own the given pubkey
secret := make([]byte, 16)
rand.Read(secret)
encrypted, err := rsa.EncryptPKCS1v15(rand.Reader, pubkey.(*rsa.PublicKey), secret)
secret := self.PrivKey.GenSecret()
encrypted, err := pubkey.Encrypt(secret)
if err != nil {
//... this is odd
return err
......@@ -58,7 +53,7 @@ func Handshake(self, remote *peer.Peer, in, out chan []byte) error {
challenge := <-in
// Decrypt challenge and send plaintext to partner
plain, err := rsa.DecryptPKCS1v15(rand.Reader, self.PrivKey.(*rsa.PrivateKey), challenge)
plain, err := self.PrivKey.Decrypt(challenge)
if err != nil {
return err
}
......@@ -77,7 +72,7 @@ func Handshake(self, remote *peer.Peer, in, out chan []byte) error {
}
func buildHandshake(self *peer.Peer) ([]byte, error) {
pkb, err := x509.MarshalPKIXPublicKey(self.PubKey)
pkb, err := self.PubKey.Bytes()
if err != nil {
return nil, err
}
......@@ -107,73 +102,14 @@ func verifyID(id peer.ID, pubkey []byte) error {
return errors.New("ID did not match public key!")
}
type KeyPair struct {
Pub crypto.PublicKey
Priv crypto.PrivateKey
}
func GenKeypair(bits int) (*KeyPair, error) {
priv, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, err
}
return &KeyPair{
Priv: priv,
Pub: &priv.PublicKey,
}, nil
}
func LoadKeypair(dir string) (*KeyPair, error) {
var kp KeyPair
pk_b, err := ioutil.ReadFile(dir + "/priv.key")
if err != nil {
return nil, err
}
priv, err := x509.ParsePKCS1PrivateKey(pk_b)
if err != nil {
return nil, err
}
kp.Priv = priv
kp.Pub = priv.PublicKey
return &kp, nil
}
func (pk *KeyPair) ID() (peer.ID, error) {
pub_b, err := x509.MarshalPKIXPublicKey(pk.Pub)
func IdFromPubKey(pk ci.PubKey) (peer.ID, error) {
b, err := pk.Bytes()
if err != nil {
return nil, err
}
hash, err := u.Hash(pub_b)
hash, err := u.Hash(b)
if err != nil {
return nil, err
}
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:
err := k.Validate()
if err != nil {
return err
}
pk_b := x509.MarshalPKCS1PrivateKey(k)
err = ioutil.WriteFile(dir+"/priv.key", pk_b, 0600)
return err
default:
return errors.New("invalid private key type.")
}
}
......@@ -3,15 +3,16 @@ package identify
import (
"testing"
ci "github.com/jbenet/go-ipfs/crypto"
"github.com/jbenet/go-ipfs/peer"
)
func TestHandshake(t *testing.T) {
kpa, err := GenKeypair(512)
ska, pka, err := ci.GenerateKeyPair(ci.RSA, 512)
if err != nil {
t.Fatal(err)
}
kpb, err := GenKeypair(512)
skb, pkb, err := ci.GenerateKeyPair(ci.RSA, 512)
if err != nil {
t.Fatal(err)
}
......@@ -19,24 +20,24 @@ func TestHandshake(t *testing.T) {
cha := make(chan []byte, 5)
chb := make(chan []byte, 5)
ida, err := kpa.ID()
ida, err := IdFromPubKey(pka)
if err != nil {
t.Fatal(err)
}
pa := &peer.Peer{
ID: ida,
PubKey: kpa.Pub,
PrivKey: kpa.Priv,
PubKey: pka,
PrivKey: ska,
}
idb, err := kpb.ID()
idb, err := IdFromPubKey(pkb)
if err != nil {
t.Fatal(err)
}
pb := &peer.Peer{
ID: idb,
PubKey: kpb.Pub,
PrivKey: kpb.Priv,
PubKey: pkb,
PrivKey: skb,
}
go func() {
......
package peer
import (
"crypto"
"sync"
"time"
b58 "github.com/jbenet/go-base58"
ic "github.com/jbenet/go-ipfs/crypto"
u "github.com/jbenet/go-ipfs/util"
ma "github.com/jbenet/go-multiaddr"
mh "github.com/jbenet/go-multihash"
......@@ -34,8 +34,8 @@ type Peer struct {
ID ID
Addresses []*ma.Multiaddr
PubKey crypto.PublicKey
PrivKey crypto.PrivateKey
PrivKey ic.PrivKey
PubKey ic.PubKey
latency time.Duration
latenLock sync.RWMutex
......
......@@ -4,6 +4,7 @@ import (
"testing"
ds "github.com/jbenet/datastore.go"
ci "github.com/jbenet/go-ipfs/crypto"
identify "github.com/jbenet/go-ipfs/identify"
peer "github.com/jbenet/go-ipfs/peer"
swarm "github.com/jbenet/go-ipfs/swarm"
......@@ -28,13 +29,13 @@ func setupDHTS(n int, t *testing.T) ([]*ma.Multiaddr, []*peer.Peer, []*IpfsDHT)
for i := 0; i < 4; i++ {
p := new(peer.Peer)
p.AddAddress(addrs[i])
kp, err := identify.GenKeypair(256)
sk, pk, err := ci.GenerateKeyPair(ci.RSA, 256)
if err != nil {
panic(err)
}
p.PubKey = kp.Pub
p.PrivKey = kp.Priv
id, err := kp.ID()
p.PubKey = pk
p.PrivKey = sk
id, err := identify.IdFromPubKey(pk)
if err != nil {
panic(err)
}
......@@ -60,13 +61,13 @@ func setupDHTS(n int, t *testing.T) ([]*ma.Multiaddr, []*peer.Peer, []*IpfsDHT)
func makePeer(addr *ma.Multiaddr) *peer.Peer {
p := new(peer.Peer)
p.AddAddress(addr)
kp, err := identify.GenKeypair(256)
sk, pk, err := ci.GenerateKeyPair(ci.RSA, 256)
if err != nil {
panic(err)
}
p.PrivKey = kp.Priv
p.PubKey = kp.Pub
id, err := kp.ID()
p.PrivKey = sk
p.PubKey = pk
id, err := identify.IdFromPubKey(pk)
if err != nil {
panic(err)
}
......
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