Cleaned up code some.
Brendan Mc committed
Sep 4, 2014 at 13:15 UTC
c6823ac6e40ecefd59a87fc93f694f4533d498c1
3 files changed
+219
-261
crypto/key.go
+149
-6
@@ -1,10 +1,18 @@
1
package crypto
2
3
import (
4
+ "bytes"
5
"errors"
6
7
+ "crypto/elliptic"
8
+ "crypto/hmac"
9
"crypto/rand"
10
"crypto/rsa"
11
+ "crypto/sha1"
12
+ "crypto/sha256"
13
+ "crypto/sha512"
14
+ "hash"
15
+ "math/big"
16
17
"code.google.com/p/goprotobuf/proto"
18
)
@@ -19,9 +27,6 @@ type PrivKey interface {
27
// Cryptographically sign the given bytes
28
Sign([]byte) ([]byte, error)
29
22
- // Decrypt a message encrypted with this keys public key
23
- Decrypt([]byte) ([]byte, error)
24
-
30
// Return a public key paired with this private key
31
GetPublic() PubKey
32
@@ -36,13 +41,13 @@ type PubKey interface {
41
// Verify that 'sig' is the signed hash of 'data'
42
Verify(data []byte, sig []byte) (bool, error)
43
39
- // Encrypt the given data with the public key
40
- Encrypt([]byte) ([]byte, error)
41
-
44
// Bytes returns a serialized, storeable representation of this key
45
Bytes() ([]byte, error)
46
}
47
48
+// Given a public key, generates the shared key.
49
+type GenSharedKey func([]byte) ([]byte, error)
50
+
51
func GenerateKeyPair(typ, bits int) (PrivKey, PubKey, error) {
52
switch typ {
53
case RSA:
@@ -57,6 +62,144 @@ func GenerateKeyPair(typ, bits int) (PrivKey, PubKey, error) {
62
}
63
}
64
65
+// Generates an ephemeral public key and returns a function that will compute
66
+// the shared secret key. Used in the identify module.
67
+//
68
+// Focuses only on ECDH now, but can be made more general in the future.
69
+func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) {
70
+ var curve elliptic.Curve
71
+
72
+ switch curveName {
73
+ case "P-224":
74
+ curve = elliptic.P224()
75
+ case "P-256":
76
+ curve = elliptic.P256()
77
+ case "P-384":
78
+ curve = elliptic.P384()
79
+ case "P-521":
80
+ curve = elliptic.P521()
81
+ }
82
+
83
+ priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader)
84
+ if err != nil {
85
+ return nil, nil, err
86
+ }
87
+
88
+ var pubKey bytes.Buffer
89
+ pubKey.Write(x.Bytes())
90
+ pubKey.Write(y.Bytes())
91
+
92
+ done := func(theirPub []byte) ([]byte, error) {
93
+ // Verify and unpack node's public key.
94
+ curveSize := curve.Params().BitSize
95
+
96
+ if len(theirPub) != (curveSize / 4) {
97
+ return nil, errors.New("Malformed public key.")
98
+ }
99
+
100
+ bound := (curveSize / 8)
101
+ x := big.NewInt(0)
102
+ y := big.NewInt(0)
103
+
104
+ x.SetBytes(theirPub[0:bound])
105
+ y.SetBytes(theirPub[bound : bound*2])
106
+
107
+ if !curve.IsOnCurve(x, y) {
108
+ return nil, errors.New("Invalid public key.")
109
+ }
110
+
111
+ // Generate shared secret.
112
+ secret, _ := curve.ScalarMult(x, y, priv)
113
+
114
+ return secret.Bytes(), nil
115
+ }
116
+
117
+ return pubKey.Bytes(), done, nil
118
+}
119
+
120
+// Generates a set of keys for each party by stretching the shared key.
121
+// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey)
122
+func KeyStretcher(cmp int, cipherType string, hashType string, secret []byte) ([]byte, []byte, []byte, []byte, []byte, []byte) {
123
+ var cipherKeySize int
124
+ switch cipherType {
125
+ case "AES-128":
126
+ cipherKeySize = 16
127
+ case "AES-256":
128
+ cipherKeySize = 32
129
+ }
130
+
131
+ ivSize := 16
132
+ hmacKeySize := 20
133
+
134
+ seed := []byte("key expansion")
135
+
136
+ result := make([]byte, 2*(ivSize+cipherKeySize+hmacKeySize))
137
+
138
+ var h func() hash.Hash
139
+
140
+ switch hashType {
141
+ case "SHA1":
142
+ h = sha1.New
143
+ case "SHA256":
144
+ h = sha256.New
145
+ case "SHA512":
146
+ h = sha512.New
147
+ }
148
+
149
+ m := hmac.New(h, secret)
150
+ m.Write(seed)
151
+
152
+ a := m.Sum(nil)
153
+
154
+ j := 0
155
+ for j < len(result) {
156
+ m.Reset()
157
+ m.Write(a)
158
+ m.Write(seed)
159
+ b := m.Sum(nil)
160
+
161
+ todo := len(b)
162
+
163
+ if j+todo > len(result) {
164
+ todo = len(result) - j
165
+ }
166
+
167
+ copy(result[j:j+todo], b)
168
+
169
+ j += todo
170
+
171
+ m.Reset()
172
+ m.Write(a)
173
+ a = m.Sum(nil)
174
+ }
175
+
176
+ myResult := make([]byte, ivSize+cipherKeySize+hmacKeySize)
177
+ theirResult := make([]byte, ivSize+cipherKeySize+hmacKeySize)
178
+
179
+ half := len(result) / 2
180
+
181
+ if cmp == 1 {
182
+ copy(myResult, result[:half])
183
+ copy(theirResult, result[half:])
184
+ } else if cmp == -1 {
185
+ copy(myResult, result[half:])
186
+ copy(theirResult, result[:half])
187
+ } else { // Shouldn't happen, but oh well.
188
+ copy(myResult, result[half:])
189
+ copy(theirResult, result[half:])
190
+ }
191
+
192
+ myIV := myResult[0:ivSize]
193
+ myCKey := myResult[ivSize : ivSize+cipherKeySize]
194
+ myMKey := myResult[ivSize+cipherKeySize:]
195
+
196
+ theirIV := theirResult[0:ivSize]
197
+ theirCKey := theirResult[ivSize : ivSize+cipherKeySize]
198
+ theirMKey := theirResult[ivSize+cipherKeySize:]
199
+
200
+ return myIV, theirIV, myCKey, theirCKey, myMKey, theirMKey
201
+}
202
+
203
func UnmarshalPublicKey(data []byte) (PubKey, error) {
204
pmes := new(PBPublicKey)
205
err := proto.Unmarshal(data, pmes)
crypto/rsa.go
-8
@@ -28,10 +28,6 @@ func (pk *RsaPublicKey) Verify(data, sig []byte) (bool, error) {
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
-
31
func (pk *RsaPublicKey) Bytes() ([]byte, error) {
32
b, err := x509.MarshalPKIXPublicKey(pk.k)
33
if err != nil {
@@ -56,10 +52,6 @@ func (sk *RsaPrivateKey) Sign(message []byte) ([]byte, error) {
52
return rsa.SignPKCS1v15(rand.Reader, sk.k, crypto.SHA256, hashed[:])
53
}
54
59
-func (sk *RsaPrivateKey) Decrypt(ciphertext []byte) ([]byte, error) {
60
- return rsa.DecryptPKCS1v15(rand.Reader, sk.k, ciphertext)
61
-}
62
-
55
func (sk *RsaPrivateKey) GetPublic() PubKey {
56
return &RsaPublicKey{&sk.k.PublicKey}
57
}
identify/identify.go
+70
-247
@@ -4,18 +4,17 @@ package identify
4
5
import (
6
"bytes"
7
+ "errors"
8
+ "strings"
9
+
10
"crypto/aes"
11
"crypto/cipher"
9
- "crypto/elliptic"
12
"crypto/hmac"
13
"crypto/rand"
14
"crypto/sha1"
15
"crypto/sha256"
16
"crypto/sha512"
15
- "errors"
17
"hash"
17
- "math/big"
18
- "strings"
18
19
proto "code.google.com/p/goprotobuf/proto"
20
ci "github.com/jbenet/go-ipfs/crypto"
@@ -95,7 +94,7 @@ func Handshake(self, remote *peer.Peer, in, out chan []byte) (chan []byte, chan
94
return nil, nil, err
95
}
96
98
- epubkey, done, err := generateEPubKey(exchange) // Generate EphemeralPubKey
97
+ epubkey, done, err := ci.GenerateEKeyPair(exchange) // Generate EphemeralPubKey
98
99
var handshake bytes.Buffer // Gather corpus to sign.
100
handshake.Write(encoded)
@@ -144,87 +143,13 @@ func Handshake(self, remote *peer.Peer, in, out chan []byte) (chan []byte, chan
143
}
144
145
cmp := bytes.Compare(myPubKey, helloResp.GetPubkey())
147
- mIV, tIV, mCKey, tCKey, mMKey, tMKey := keyGenerator(cmp, cipherType, hashType, secret)
146
+ mIV, tIV, mCKey, tCKey, mMKey, tMKey := ci.KeyStretcher(cmp, cipherType, hashType, secret)
147
148
secureIn := make(chan []byte)
149
secureOut := make(chan []byte)
150
152
- go func() {
153
- myBlock, _ := aes.NewCipher(mCKey)
154
- myCipher := cipher.NewCTR(myBlock, mIV)
155
-
156
- theirBlock, _ := aes.NewCipher(tCKey)
157
- theirCipher := cipher.NewCTR(theirBlock, tIV)
158
-
159
- var myMac, theirMac hash.Hash
160
- var macSize int
161
-
162
- switch hashType {
163
- case "SHA1":
164
- myMac = hmac.New(sha1.New, mMKey)
165
- theirMac = hmac.New(sha1.New, tMKey)
166
- macSize = 20
167
-
168
- case "SHA256":
169
- myMac = hmac.New(sha256.New, mMKey)
170
- theirMac = hmac.New(sha256.New, tMKey)
171
- macSize = 32
172
-
173
- case "SHA512":
174
- myMac = hmac.New(sha512.New, mMKey)
175
- theirMac = hmac.New(sha512.New, tMKey)
176
- macSize = 64
177
- }
178
-
179
- for {
180
- select {
181
- case data, ok := <-secureOut:
182
- if !ok {
183
- return
184
- }
185
-
186
- if len(data) == 0 {
187
- continue
188
- }
189
-
190
- buff := make([]byte, len(data)+macSize)
191
-
192
- myCipher.XORKeyStream(buff, data)
193
-
194
- myMac.Write(buff[0:len(data)])
195
- copy(buff[len(data):], myMac.Sum(nil))
196
- myMac.Reset()
197
-
198
- out <- buff
199
-
200
- case data, ok := <-in:
201
- if !ok {
202
- return
203
- }
204
-
205
- if len(data) <= macSize {
206
- continue
207
- }
208
-
209
- mark := len(data) - macSize
210
- buff := make([]byte, mark)
211
-
212
- theirCipher.XORKeyStream(buff, data[0:mark])
213
-
214
- theirMac.Write(data[0:mark])
215
- expected := theirMac.Sum(nil)
216
- theirMac.Reset()
217
-
218
- hmacOk := hmac.Equal(data[mark:], expected)
219
-
220
- if hmacOk {
221
- secureIn <- buff
222
- } else {
223
- secureIn <- nil
224
- }
225
- }
226
- }
227
- }()
151
+ go secureInProxy(in, secureIn, hashType, tIV, tCKey, tMKey)
152
+ go secureOutProxy(out, secureOut, hashType, mIV, mCKey, mMKey)
153
154
finished := []byte("Finished")
155
@@ -240,99 +165,90 @@ func Handshake(self, remote *peer.Peer, in, out chan []byte) (chan []byte, chan
165
return secureIn, secureOut, nil
166
}
167
243
-func IdFromPubKey(pk ci.PubKey) (peer.ID, error) {
244
- b, err := pk.Bytes()
245
- if err != nil {
246
- return nil, err
247
- }
248
- hash, err := u.Hash(b)
249
- if err != nil {
250
- return nil, err
168
+func makeMac(hashType string, key []byte) (hash.Hash, int) {
169
+ switch hashType {
170
+ case "SHA1":
171
+ return hmac.New(sha1.New, key), sha1.Size
172
+ case "SHA512":
173
+ return hmac.New(sha512.New, key), sha512.Size
174
+ default:
175
+ return hmac.New(sha256.New, key), sha256.Size
176
}
252
- return peer.ID(hash), nil
177
}
178
255
-// Generates a set of keys for each party by stretching the shared key.
256
-// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey)
257
-func keyGenerator(cmp int, cipherType string, hashType string, secret []byte) ([]byte, []byte, []byte, []byte, []byte, []byte) {
258
- var cipherKeySize int
259
- switch cipherType {
260
- case "AES-128":
261
- cipherKeySize = 16
262
- case "AES-256":
263
- cipherKeySize = 32
264
- }
265
-
266
- ivSize := 16
267
- hmacKeySize := 20
268
-
269
- seed := []byte("key expansion")
179
+func secureInProxy(in, secureIn chan []byte, hashType string, tIV, tCKey, tMKey []byte) {
180
+ theirBlock, _ := aes.NewCipher(tCKey)
181
+ theirCipher := cipher.NewCTR(theirBlock, tIV)
182
271
- result := make([]byte, 2*(ivSize+cipherKeySize+hmacKeySize))
183
+ theirMac, macSize := makeMac(hashType, tMKey)
184
273
- var h func() hash.Hash
185
+ for {
186
+ data, ok := <-in
187
+ if !ok {
188
+ return
189
+ }
190
275
- switch hashType {
276
- case "SHA1":
277
- h = sha1.New
278
- case "SHA256":
279
- h = sha256.New
280
- case "SHA512":
281
- h = sha512.New
282
- }
191
+ if len(data) <= macSize {
192
+ continue
193
+ }
194
284
- m := hmac.New(h, secret)
285
- m.Write(seed)
195
+ mark := len(data) - macSize
196
+ buff := make([]byte, mark)
197
287
- a := m.Sum(nil)
198
+ theirCipher.XORKeyStream(buff, data[0:mark])
199
289
- j := 0
290
- for j < len(result) {
291
- m.Reset()
292
- m.Write(a)
293
- m.Write(seed)
294
- b := m.Sum(nil)
200
+ theirMac.Write(data[0:mark])
201
+ expected := theirMac.Sum(nil)
202
+ theirMac.Reset()
203
296
- todo := len(b)
204
+ hmacOk := hmac.Equal(data[mark:], expected)
205
298
- if j+todo > len(result) {
299
- todo = len(result) - j
206
+ if hmacOk {
207
+ secureIn <- buff
208
+ } else {
209
+ secureIn <- nil
210
}
211
+ }
212
+}
213
302
- copy(result[j:j+todo], b)
214
+func secureOutProxy(out, secureOut chan []byte, hashType string, mIV, mCKey, mMKey []byte) {
215
+ myBlock, _ := aes.NewCipher(mCKey)
216
+ myCipher := cipher.NewCTR(myBlock, mIV)
217
304
- j += todo
218
+ myMac, macSize := makeMac(hashType, mMKey)
219
306
- m.Reset()
307
- m.Write(a)
308
- a = m.Sum(nil)
309
- }
220
+ for {
221
+ data, ok := <-secureOut
222
+ if !ok {
223
+ return
224
+ }
225
311
- myResult := make([]byte, ivSize+cipherKeySize+hmacKeySize)
312
- theirResult := make([]byte, ivSize+cipherKeySize+hmacKeySize)
226
+ if len(data) == 0 {
227
+ continue
228
+ }
229
314
- half := len(result) / 2
230
+ buff := make([]byte, len(data)+macSize)
231
316
- if cmp == 1 {
317
- copy(myResult, result[:half])
318
- copy(theirResult, result[half:])
319
- } else if cmp == -1 {
320
- copy(myResult, result[half:])
321
- copy(theirResult, result[:half])
322
- } else { // Shouldn't happen, but oh well.
323
- copy(myResult, result[half:])
324
- copy(theirResult, result[half:])
325
- }
232
+ myCipher.XORKeyStream(buff, data)
233
327
- myIV := myResult[0:ivSize]
328
- myCKey := myResult[ivSize : ivSize+cipherKeySize]
329
- myMKey := myResult[ivSize+cipherKeySize:]
234
+ myMac.Write(buff[0:len(data)])
235
+ copy(buff[len(data):], myMac.Sum(nil))
236
+ myMac.Reset()
237
331
- theirIV := theirResult[0:ivSize]
332
- theirCKey := theirResult[ivSize : ivSize+cipherKeySize]
333
- theirMKey := theirResult[ivSize+cipherKeySize:]
238
+ out <- buff
239
+ }
240
+}
241
335
- return myIV, theirIV, myCKey, theirCKey, myMKey, theirMKey
242
+func IdFromPubKey(pk ci.PubKey) (peer.ID, error) {
243
+ b, err := pk.Bytes()
244
+ if err != nil {
245
+ return nil, err
246
+ }
247
+ hash, err := u.Hash(b)
248
+ if err != nil {
249
+ return nil, err
250
+ }
251
+ return peer.ID(hash), nil
252
}
253
254
// Determines which algorithm to use. Note: f(a, b) = f(b, a)
@@ -372,96 +288,3 @@ func selectBest(myPrefs, theirPrefs string) (string, error) {
288
289
return "", errors.New("No algorithms in common!")
290
}
375
-
376
-// Generates an ephemeral public key and returns a function that will compute
377
-// the shared secret key.
378
-//
379
-// Focuses only on ECDH now, but can be made more general in the future.
380
-func generateEPubKey(exchange string) ([]byte, func([]byte) ([]byte, error), error) {
381
- genKeyPair := func(curve elliptic.Curve) ([]byte, []byte, error) {
382
- priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader)
383
- if err != nil {
384
- return nil, nil, err
385
- }
386
-
387
- var pubKey bytes.Buffer
388
- pubKey.Write(x.Bytes())
389
- pubKey.Write(y.Bytes())
390
-
391
- return pubKey.Bytes(), priv, nil
392
- }
393
-
394
- genSec := func(curve elliptic.Curve, theirPub []byte, myPriv []byte) ([]byte, error) {
395
- // Verify and unpack node's public key.
396
- curveSize := curve.Params().BitSize
397
-
398
- if len(theirPub) != (curveSize / 4) {
399
- return nil, errors.New("Malformed public key.")
400
- }
401
-
402
- bound := (curveSize / 8)
403
- x := big.NewInt(0)
404
- y := big.NewInt(0)
405
-
406
- x.SetBytes(theirPub[0:bound])
407
- y.SetBytes(theirPub[bound : bound*2])
408
-
409
- if !curve.IsOnCurve(x, y) {
410
- return nil, errors.New("Invalid public key.")
411
- }
412
-
413
- // Generate shared secret.
414
- secret, _ := curve.ScalarMult(x, y, myPriv)
415
-
416
- return secret.Bytes(), nil
417
- }
418
-
419
- switch exchange {
420
- case "P-224":
421
- curve := elliptic.P224()
422
- pub, priv, err := genKeyPair(curve)
423
- if err != nil {
424
- return nil, nil, err
425
- }
426
-
427
- done := func(theirs []byte) ([]byte, error) { return genSec(curve, theirs, priv) }
428
-
429
- return pub, done, nil
430
-
431
- case "P-256":
432
- curve := elliptic.P256()
433
- pub, priv, err := genKeyPair(curve)
434
- if err != nil {
435
- return nil, nil, err
436
- }
437
-
438
- done := func(theirs []byte) ([]byte, error) { return genSec(curve, theirs, priv) }
439
-
440
- return pub, done, nil
441
-
442
- case "P-384":
443
- curve := elliptic.P384()
444
- pub, priv, err := genKeyPair(curve)
445
- if err != nil {
446
- return nil, nil, err
447
- }
448
-
449
- done := func(theirs []byte) ([]byte, error) { return genSec(curve, theirs, priv) }
450
-
451
- return pub, done, nil
452
-
453
- case "P-521":
454
- curve := elliptic.P521()
455
- pub, priv, err := genKeyPair(curve)
456
- if err != nil {
457
- return nil, nil, err
458
- }
459
-
460
- done := func(theirs []byte) ([]byte, error) { return genSec(curve, theirs, priv) }
461
-
462
- return pub, done, nil
463
-
464
- }
465
-
466
- return nil, nil, errors.New("Something silly happened.")
467
-}