@cryptotaxi247 / kubo / commits / 4b97f1f27

create new crypto package and make rest of repo use it

Jeromy committed Sep 3, 2014 at 20:15 UTC 4b97f1f27005fc5e583b0343c53703a22af4753c
10 files changed +349 -109
cmd/ipfs/init.go
+10 -5
@@ -8,7 +8,8 @@ import (
8 "github.com/gonuts/flag"
9 "github.com/jbenet/commander"
10 config "github.com/jbenet/go-ipfs/config"
11 - "github.com/jbenet/go-ipfs/identify"
11 + ci "github.com/jbenet/go-ipfs/crypto"
12 + identify "github.com/jbenet/go-ipfs/identify"
13 u "github.com/jbenet/go-ipfs/util"
14 )
15
@@ -54,16 +55,20 @@ func initCmd(c *commander.Command, inp []string) error {
55 if nbits < 1024 {
56 return errors.New("Bitsize less than 1024 is considered unsafe.")
57 }
57 - kp, err := identify.GenKeypair(nbits)
58 +
59 + sk, pk, err := ci.GenerateKeyPair(ci.RSA, nbits)
60 if err != nil {
61 return err
62 }
63
64 // pretend to encrypt key, then store it unencrypted
63 - enckey := base64.StdEncoding.EncodeToString(kp.PrivBytes())
64 - cfg.Identity.PrivKey = enckey
65 + skbytes, err := sk.Bytes()
66 + if err != nil {
67 + return err
68 + }
69 + cfg.Identity.PrivKey = base64.StdEncoding.EncodeToString(skbytes)
70
66 - id, err := kp.ID()
71 + id, err := identify.IdFromPubKey(pk)
72 if err != nil {
73 return err
74 }
core/core.go
+8 -12
@@ -1,8 +1,7 @@
1 package core
2
3 import (
4 - "crypto"
5 - "crypto/rsa"
4 + "encoding/base64"
5 "errors"
6 "fmt"
7
@@ -11,7 +10,7 @@ import (
10 "github.com/jbenet/go-ipfs/bitswap"
11 bserv "github.com/jbenet/go-ipfs/blockservice"
12 config "github.com/jbenet/go-ipfs/config"
14 - "github.com/jbenet/go-ipfs/identify"
13 + ci "github.com/jbenet/go-ipfs/crypto"
14 merkledag "github.com/jbenet/go-ipfs/merkledag"
15 path "github.com/jbenet/go-ipfs/path"
16 peer "github.com/jbenet/go-ipfs/peer"
@@ -103,24 +102,21 @@ func loadBitswap(cfg *config.Config, d ds.Datastore) (*bitswap.BitSwap, error) {
102 return nil, err
103 }
104
106 - pk, err := cfg.Identity.DecodePrivateKey("")
105 + skb, err := base64.StdEncoding.DecodeString(cfg.Identity.PrivKey)
106 if err != nil {
107 return nil, err
108 }
109
111 - var pubkey crypto.PublicKey
112 - switch k := pk.(type) {
113 - case *rsa.PrivateKey:
114 - pubkey = &k.PublicKey
115 - default:
116 - return nil, identify.ErrUnsupportedKeyType
110 + sk, err := ci.UnmarshalPrivateKey(skb)
111 + if err != nil {
112 + return nil, err
113 }
114
115 local := &peer.Peer{
116 ID: peer.ID(b58.Decode(cfg.Identity.PeerID)),
117 Addresses: []*ma.Multiaddr{maddr},
122 - PrivKey: pk,
123 - PubKey: pubkey,
118 + PrivKey: sk,
119 + PubKey: sk.GetPublic(),
120 }
121
122 if len(local.ID) == 0 {
crypto/encode.pb.go new
+104
@@ -0,0 +1,104 @@
1 +// Code generated by protoc-gen-go.
2 +// source: encode.proto
3 +// DO NOT EDIT!
4 +
5 +/*
6 +Package crypto is a generated protocol buffer package.
7 +
8 +It is generated from these files:
9 + encode.proto
10 +
11 +It has these top-level messages:
12 + PBPublicKey
13 + PBPrivateKey
14 +*/
15 +package crypto
16 +
17 +import proto "code.google.com/p/goprotobuf/proto"
18 +import math "math"
19 +
20 +// Reference imports to suppress errors if they are not otherwise used.
21 +var _ = proto.Marshal
22 +var _ = math.Inf
23 +
24 +type KeyType int32
25 +
26 +const (
27 + KeyType_RSA KeyType = 0
28 +)
29 +
30 +var KeyType_name = map[int32]string{
31 + 0: "RSA",
32 +}
33 +var KeyType_value = map[string]int32{
34 + "RSA": 0,
35 +}
36 +
37 +func (x KeyType) Enum() *KeyType {
38 + p := new(KeyType)
39 + *p = x
40 + return p
41 +}
42 +func (x KeyType) String() string {
43 + return proto.EnumName(KeyType_name, int32(x))
44 +}
45 +func (x *KeyType) UnmarshalJSON(data []byte) error {
46 + value, err := proto.UnmarshalJSONEnum(KeyType_value, data, "KeyType")
47 + if err != nil {
48 + return err
49 + }
50 + *x = KeyType(value)
51 + return nil
52 +}
53 +
54 +type PBPublicKey struct {
55 + Type *KeyType `protobuf:"varint,1,req,enum=crypto.KeyType" json:"Type,omitempty"`
56 + Data []byte `protobuf:"bytes,2,req" json:"Data,omitempty"`
57 + XXX_unrecognized []byte `json:"-"`
58 +}
59 +
60 +func (m *PBPublicKey) Reset() { *m = PBPublicKey{} }
61 +func (m *PBPublicKey) String() string { return proto.CompactTextString(m) }
62 +func (*PBPublicKey) ProtoMessage() {}
63 +
64 +func (m *PBPublicKey) GetType() KeyType {
65 + if m != nil && m.Type != nil {
66 + return *m.Type
67 + }
68 + return KeyType_RSA
69 +}
70 +
71 +func (m *PBPublicKey) GetData() []byte {
72 + if m != nil {
73 + return m.Data
74 + }
75 + return nil
76 +}
77 +
78 +type PBPrivateKey struct {
79 + Type *KeyType `protobuf:"varint,1,req,enum=crypto.KeyType" json:"Type,omitempty"`
80 + Data []byte `protobuf:"bytes,2,req" json:"Data,omitempty"`
81 + XXX_unrecognized []byte `json:"-"`
82 +}
83 +
84 +func (m *PBPrivateKey) Reset() { *m = PBPrivateKey{} }
85 +func (m *PBPrivateKey) String() string { return proto.CompactTextString(m) }
86 +func (*PBPrivateKey) ProtoMessage() {}
87 +
88 +func (m *PBPrivateKey) GetType() KeyType {
89 + if m != nil && m.Type != nil {
90 + return *m.Type
91 + }
92 + return KeyType_RSA
93 +}
94 +
95 +func (m *PBPrivateKey) GetData() []byte {
96 + if m != nil {
97 + return m.Data
98 + }
99 + return nil
100 +}
101 +
102 +func init() {
103 + proto.RegisterEnum("crypto.KeyType", KeyType_name, KeyType_value)
104 +}
crypto/encode.proto new
+15
@@ -0,0 +1,15 @@
1 +package crypto;
2 +
3 +enum KeyType {
4 + RSA = 0;
5 +}
6 +
7 +message PBPublicKey {
8 + required KeyType Type = 1;
9 + required bytes Data = 2;
10 +}
11 +
12 +message PBPrivateKey {
13 + required KeyType Type = 1;
14 + required bytes Data = 2;
15 +}
crypto/key.go new
+88
@@ -0,0 +1,88 @@
1 +package crypto
2 +
3 +import (
4 + "errors"
5 +
6 + "crypto/rand"
7 + "crypto/rsa"
8 +
9 + "code.google.com/p/goprotobuf/proto"
10 +)
11 +
12 +var ErrBadKeyType = errors.New("invalid or unsupported key type")
13 +
14 +const (
15 + RSA = iota
16 +)
17 +
18 +type PrivKey interface {
19 + // Cryptographically sign the given bytes
20 + Sign([]byte) ([]byte, error)
21 +
22 + // Decrypt a message encrypted with this keys public key
23 + Decrypt([]byte) ([]byte, error)
24 +
25 + // Return a public key paired with this private key
26 + GetPublic() PubKey
27 +
28 + // Generate a secret string of bytes
29 + GenSecret() []byte
30 +
31 + // Bytes returns a serialized, storeable representation of this key
32 + Bytes() ([]byte, error)
33 +}
34 +
35 +type PubKey interface {
36 + // Verify that 'sig' is the signed hash of 'data'
37 + Verify(data []byte, sig []byte) (bool, error)
38 +
39 + // Encrypt the given data with the public key
40 + Encrypt([]byte) ([]byte, error)
41 +
42 + // Bytes returns a serialized, storeable representation of this key
43 + Bytes() ([]byte, error)
44 +}
45 +
46 +func GenerateKeyPair(typ, bits int) (PrivKey, PubKey, error) {
47 + switch typ {
48 + case RSA:
49 + priv, err := rsa.GenerateKey(rand.Reader, bits)
50 + if err != nil {
51 + return nil, nil, err
52 + }
53 + pk := &priv.PublicKey
54 + return &RsaPrivateKey{priv}, &RsaPublicKey{pk}, nil
55 + default:
56 + return nil, nil, ErrBadKeyType
57 + }
58 +}
59 +
60 +func UnmarshalPublicKey(data []byte) (PubKey, error) {
61 + pmes := new(PBPublicKey)
62 + err := proto.Unmarshal(data, pmes)
63 + if err != nil {
64 + return nil, err
65 + }
66 +
67 + switch pmes.GetType() {
68 + case KeyType_RSA:
69 + return UnmarshalRsaPublicKey(pmes.GetData())
70 + default:
71 + return nil, ErrBadKeyType
72 + }
73 +}
74 +
75 +func UnmarshalPrivateKey(data []byte) (PrivKey, error) {
76 + pmes := new(PBPrivateKey)
77 + err := proto.Unmarshal(data, pmes)
78 + if err != nil {
79 + return nil, err
80 + }
81 +
82 + switch pmes.GetType() {
83 + case KeyType_RSA:
84 + return UnmarshalRsaPrivateKey(pmes.GetData())
85 + default:
86 + return nil, ErrBadKeyType
87 + }
88 +}
crypto/rsa.go new
+94
@@ -0,0 +1,94 @@
1 +package crypto
2 +
3 +import (
4 + "crypto"
5 + "crypto/rand"
6 + "crypto/rsa"
7 + "crypto/sha256"
8 + "crypto/x509"
9 + "errors"
10 +
11 + "code.google.com/p/goprotobuf/proto"
12 +)
13 +
14 +type RsaPrivateKey struct {
15 + k *rsa.PrivateKey
16 +}
17 +
18 +type RsaPublicKey struct {
19 + k *rsa.PublicKey
20 +}
21 +
22 +func (pk *RsaPublicKey) Verify(data, sig []byte) (bool, error) {
23 + hashed := sha256.Sum256(data)
24 + err := rsa.VerifyPKCS1v15(pk.k, crypto.SHA256, hashed[:], sig)
25 + if err != nil {
26 + return false, err
27 + }
28 + return true, nil
29 +}
30 +
31 +func (pk *RsaPublicKey) Encrypt(message []byte) ([]byte, error) {
32 + return rsa.EncryptPKCS1v15(rand.Reader, pk.k, message)
33 +}
34 +
35 +func (pk *RsaPublicKey) Bytes() ([]byte, error) {
36 + b, err := x509.MarshalPKIXPublicKey(pk.k)
37 + if err != nil {
38 + return nil, err
39 + }
40 +
41 + pbmes := new(PBPublicKey)
42 + typ := KeyType_RSA
43 + pbmes.Type = &typ
44 + pbmes.Data = b
45 + return proto.Marshal(pbmes)
46 +}
47 +
48 +func (sk *RsaPrivateKey) GenSecret() []byte {
49 + buf := make([]byte, 16)
50 + rand.Read(buf)
51 + return buf
52 +}
53 +
54 +func (sk *RsaPrivateKey) Sign(message []byte) ([]byte, error) {
55 + hashed := sha256.Sum256(message)
56 + return rsa.SignPKCS1v15(rand.Reader, sk.k, crypto.SHA256, hashed[:])
57 +}
58 +
59 +func (sk *RsaPrivateKey) Decrypt(ciphertext []byte) ([]byte, error) {
60 + return rsa.DecryptPKCS1v15(rand.Reader, sk.k, ciphertext)
61 +}
62 +
63 +func (sk *RsaPrivateKey) GetPublic() PubKey {
64 + return &RsaPublicKey{&sk.k.PublicKey}
65 +}
66 +
67 +func (sk *RsaPrivateKey) Bytes() ([]byte, error) {
68 + b := x509.MarshalPKCS1PrivateKey(sk.k)
69 + pbmes := new(PBPrivateKey)
70 + typ := KeyType_RSA
71 + pbmes.Type = &typ
72 + pbmes.Data = b
73 + return proto.Marshal(pbmes)
74 +}
75 +
76 +func UnmarshalRsaPrivateKey(b []byte) (*RsaPrivateKey, error) {
77 + sk, err := x509.ParsePKCS1PrivateKey(b)
78 + if err != nil {
79 + return nil, err
80 + }
81 + return &RsaPrivateKey{sk}, nil
82 +}
83 +
84 +func UnmarshalRsaPublicKey(b []byte) (*RsaPublicKey, error) {
85 + pub, err := x509.ParsePKIXPublicKey(b)
86 + if err != nil {
87 + return nil, err
88 + }
89 + pk, ok := pub.(*rsa.PublicKey)
90 + if !ok {
91 + return nil, errors.New("Not actually an rsa public key.")
92 + }
93 + return &RsaPublicKey{pk}, nil
94 +}
identify/identify.go
+9 -73
@@ -4,14 +4,10 @@ package identify
4
5 import (
6 "bytes"
7 - "crypto"
8 - "crypto/rand"
9 - "crypto/rsa"
10 - "crypto/x509"
7 "errors"
12 - "io/ioutil"
8
9 proto "code.google.com/p/goprotobuf/proto"
10 + ci "github.com/jbenet/go-ipfs/crypto"
11 peer "github.com/jbenet/go-ipfs/peer"
12 u "github.com/jbenet/go-ipfs/util"
13 )
@@ -40,15 +36,14 @@ func Handshake(self, remote *peer.Peer, in, out chan []byte) error {
36 return verifyErr
37 }
38
43 - pubkey, err := x509.ParsePKIXPublicKey(pbresp.GetPubkey())
39 + pubkey, err := ci.UnmarshalPublicKey(pbresp.GetPubkey())
40 if err != nil {
41 return err
42 }
43
44 // Challenge peer to ensure they own the given pubkey
49 - secret := make([]byte, 16)
50 - rand.Read(secret)
51 - encrypted, err := rsa.EncryptPKCS1v15(rand.Reader, pubkey.(*rsa.PublicKey), secret)
45 + secret := self.PrivKey.GenSecret()
46 + encrypted, err := pubkey.Encrypt(secret)
47 if err != nil {
48 //... this is odd
49 return err
@@ -58,7 +53,7 @@ func Handshake(self, remote *peer.Peer, in, out chan []byte) error {
53 challenge := <-in
54
55 // Decrypt challenge and send plaintext to partner
61 - plain, err := rsa.DecryptPKCS1v15(rand.Reader, self.PrivKey.(*rsa.PrivateKey), challenge)
56 + plain, err := self.PrivKey.Decrypt(challenge)
57 if err != nil {
58 return err
59 }
@@ -77,7 +72,7 @@ func Handshake(self, remote *peer.Peer, in, out chan []byte) error {
72 }
73
74 func buildHandshake(self *peer.Peer) ([]byte, error) {
80 - pkb, err := x509.MarshalPKIXPublicKey(self.PubKey)
75 + pkb, err := self.PubKey.Bytes()
76 if err != nil {
77 return nil, err
78 }
@@ -107,73 +102,14 @@ func verifyID(id peer.ID, pubkey []byte) error {
102 return errors.New("ID did not match public key!")
103 }
104
110 -type KeyPair struct {
111 - Pub crypto.PublicKey
112 - Priv crypto.PrivateKey
113 -}
114 -
115 -func GenKeypair(bits int) (*KeyPair, error) {
116 - priv, err := rsa.GenerateKey(rand.Reader, bits)
117 - if err != nil {
118 - return nil, err
119 - }
120 -
121 - return &KeyPair{
122 - Priv: priv,
123 - Pub: &priv.PublicKey,
124 - }, nil
125 -}
126 -
127 -func LoadKeypair(dir string) (*KeyPair, error) {
128 - var kp KeyPair
129 - pk_b, err := ioutil.ReadFile(dir + "/priv.key")
130 - if err != nil {
131 - return nil, err
132 - }
133 -
134 - priv, err := x509.ParsePKCS1PrivateKey(pk_b)
135 - if err != nil {
136 - return nil, err
137 - }
138 -
139 - kp.Priv = priv
140 - kp.Pub = priv.PublicKey
141 -
142 - return &kp, nil
143 -}
144 -
145 -func (pk *KeyPair) ID() (peer.ID, error) {
146 - pub_b, err := x509.MarshalPKIXPublicKey(pk.Pub)
105 +func IdFromPubKey(pk ci.PubKey) (peer.ID, error) {
106 + b, err := pk.Bytes()
107 if err != nil {
108 return nil, err
109 }
150 - hash, err := u.Hash(pub_b)
110 + hash, err := u.Hash(b)
111 if err != nil {
112 return nil, err
113 }
114 return peer.ID(hash), nil
115 }
156 -
157 -func (pk *KeyPair) PrivBytes() []byte {
158 - switch k := pk.Priv.(type) {
159 - case *rsa.PrivateKey:
160 - return x509.MarshalPKCS1PrivateKey(k)
161 - default:
162 - panic("Unsupported private key type.")
163 - }
164 -}
165 -
166 -func (kp *KeyPair) Save(dir string) error {
167 - switch k := kp.Priv.(type) {
168 - case *rsa.PrivateKey:
169 - err := k.Validate()
170 - if err != nil {
171 - return err
172 - }
173 - pk_b := x509.MarshalPKCS1PrivateKey(k)
174 - err = ioutil.WriteFile(dir+"/priv.key", pk_b, 0600)
175 - return err
176 - default:
177 - return errors.New("invalid private key type.")
178 - }
179 -}
identify/identify_test.go
+9 -8
@@ -3,15 +3,16 @@ package identify
3 import (
4 "testing"
5
6 + ci "github.com/jbenet/go-ipfs/crypto"
7 "github.com/jbenet/go-ipfs/peer"
8 )
9
10 func TestHandshake(t *testing.T) {
10 - kpa, err := GenKeypair(512)
11 + ska, pka, err := ci.GenerateKeyPair(ci.RSA, 512)
12 if err != nil {
13 t.Fatal(err)
14 }
14 - kpb, err := GenKeypair(512)
15 + skb, pkb, err := ci.GenerateKeyPair(ci.RSA, 512)
16 if err != nil {
17 t.Fatal(err)
18 }
@@ -19,24 +20,24 @@ func TestHandshake(t *testing.T) {
20 cha := make(chan []byte, 5)
21 chb := make(chan []byte, 5)
22
22 - ida, err := kpa.ID()
23 + ida, err := IdFromPubKey(pka)
24 if err != nil {
25 t.Fatal(err)
26 }
27 pa := &peer.Peer{
28 ID: ida,
28 - PubKey: kpa.Pub,
29 - PrivKey: kpa.Priv,
29 + PubKey: pka,
30 + PrivKey: ska,
31 }
32
32 - idb, err := kpb.ID()
33 + idb, err := IdFromPubKey(pkb)
34 if err != nil {
35 t.Fatal(err)
36 }
37 pb := &peer.Peer{
38 ID: idb,
38 - PubKey: kpb.Pub,
39 - PrivKey: kpb.Priv,
39 + PubKey: pkb,
40 + PrivKey: skb,
41 }
42
43 go func() {
peer/peer.go
+3 -3
@@ -1,11 +1,11 @@
1 package peer
2
3 import (
4 - "crypto"
4 "sync"
5 "time"
6
7 b58 "github.com/jbenet/go-base58"
8 + ic "github.com/jbenet/go-ipfs/crypto"
9 u "github.com/jbenet/go-ipfs/util"
10 ma "github.com/jbenet/go-multiaddr"
11 mh "github.com/jbenet/go-multihash"
@@ -34,8 +34,8 @@ type Peer struct {
34 ID ID
35 Addresses []*ma.Multiaddr
36
37 - PubKey crypto.PublicKey
38 - PrivKey crypto.PrivateKey
37 + PrivKey ic.PrivKey
38 + PubKey ic.PubKey
39
40 latency time.Duration
41 latenLock sync.RWMutex
routing/dht/dht_test.go
+9 -8
@@ -4,6 +4,7 @@ import (
4 "testing"
5
6 ds "github.com/jbenet/datastore.go"
7 + ci "github.com/jbenet/go-ipfs/crypto"
8 identify "github.com/jbenet/go-ipfs/identify"
9 peer "github.com/jbenet/go-ipfs/peer"
10 swarm "github.com/jbenet/go-ipfs/swarm"
@@ -28,13 +29,13 @@ func setupDHTS(n int, t *testing.T) ([]*ma.Multiaddr, []*peer.Peer, []*IpfsDHT)
29 for i := 0; i < 4; i++ {
30 p := new(peer.Peer)
31 p.AddAddress(addrs[i])
31 - kp, err := identify.GenKeypair(256)
32 + sk, pk, err := ci.GenerateKeyPair(ci.RSA, 256)
33 if err != nil {
34 panic(err)
35 }
35 - p.PubKey = kp.Pub
36 - p.PrivKey = kp.Priv
37 - id, err := kp.ID()
36 + p.PubKey = pk
37 + p.PrivKey = sk
38 + id, err := identify.IdFromPubKey(pk)
39 if err != nil {
40 panic(err)
41 }
@@ -60,13 +61,13 @@ func setupDHTS(n int, t *testing.T) ([]*ma.Multiaddr, []*peer.Peer, []*IpfsDHT)
61 func makePeer(addr *ma.Multiaddr) *peer.Peer {
62 p := new(peer.Peer)
63 p.AddAddress(addr)
63 - kp, err := identify.GenKeypair(256)
64 + sk, pk, err := ci.GenerateKeyPair(ci.RSA, 256)
65 if err != nil {
66 panic(err)
67 }
67 - p.PrivKey = kp.Priv
68 - p.PubKey = kp.Pub
69 - id, err := kp.ID()
68 + p.PrivKey = sk
69 + p.PubKey = pk
70 + id, err := identify.IdFromPubKey(pk)
71 if err != nil {
72 panic(err)
73 }