remove signed pipe
Jeromy committed
Oct 31, 2014 at 18:10 UTC
6efaa1d811d497923ce4e24b784d24b77df85a04
3 files changed
-363
crypto/spipe/internal/pb/spipe.proto
-6
@@ -12,9 +12,3 @@ message Exchange {
12
optional bytes epubkey = 1;
13
optional bytes signature = 2;
14
}
15
-
16
-message DataSig {
17
- optional bytes data = 1;
18
- optional bytes signature = 2;
19
- optional uint64 id = 3;
20
-}
crypto/spipe/signedpipe.go
deleted
-305
@@ -1,305 +0,0 @@
1
-package spipe
2
-
3
-import (
4
- "bytes"
5
- "crypto/rand"
6
- "errors"
7
-
8
- "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
9
-
10
- "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
11
- ci "github.com/jbenet/go-ipfs/crypto"
12
- pb "github.com/jbenet/go-ipfs/crypto/spipe/internal/pb"
13
- "github.com/jbenet/go-ipfs/peer"
14
- "github.com/jbenet/go-ipfs/util/pipes"
15
-)
16
-
17
-type SignedPipe struct {
18
- pipes.Duplex
19
- insecure pipes.Duplex
20
-
21
- local peer.Peer
22
- remote peer.Peer
23
- peers peer.Peerstore
24
-
25
- ctx context.Context
26
- cancel context.CancelFunc
27
-
28
- localMsgID uint64
29
- removeMsgID uint64
30
-}
31
-
32
-// secureChallengeSize is a constant that determines the initial challenge, and every subsequent
33
-// sequence number. It should be large enough to be unguessable by adversaries (128+ bits).
34
-// (SECURITY WARNING)
35
-const secureChallengeSize = (256 / 32)
36
-
37
-func NewSignedPipe(parctx context.Context, bufsize int, local peer.Peer,
38
- peers peer.Peerstore, insecure pipes.Duplex) (*SignedPipe, error) {
39
-
40
- ctx, cancel := context.WithCancel(parctx)
41
-
42
- sp := &SignedPipe{
43
- Duplex: pipes.NewDuplex(bufsize),
44
- local: local,
45
- peers: peers,
46
- insecure: insecure,
47
-
48
- ctx: ctx,
49
- cancel: cancel,
50
- }
51
-
52
- if err := sp.handshake(); err != nil {
53
- sp.Close()
54
- return nil, err
55
- }
56
- return sp, nil
57
-}
58
-
59
-func (sp *SignedPipe) trySend(b []byte) bool {
60
- select {
61
- case <-sp.ctx.Done():
62
- return false
63
- case sp.insecure.Out <- b:
64
- return true
65
- }
66
-}
67
-
68
-func (sp *SignedPipe) tryRecv() ([]byte, bool) {
69
- select {
70
- case <-sp.ctx.Done():
71
- return nil, false
72
- case data, ok := <-sp.insecure.In:
73
- if !ok {
74
- return nil, false
75
- }
76
- return data, true
77
- }
78
-}
79
-
80
-// reduceChallenge reduces a series of bytes into a
81
-// single uint64 we can use as a seed for message IDs
82
-func reduceChallenge(cha []byte) uint64 {
83
- var out uint64
84
- for _, b := range cha {
85
- out ^= uint64(b)
86
- out = out << 1
87
- }
88
- return out
89
-}
90
-
91
-func (sp *SignedPipe) handshake() error {
92
- // Send them our public key
93
- pubk := sp.local.PubKey()
94
- pkb, err := pubk.Bytes()
95
- if err != nil {
96
- return err
97
- }
98
-
99
- // Exchange public keys with remote peer
100
- if !sp.trySend(pkb) {
101
- return context.Canceled
102
- }
103
- theirPkb := <-sp.insecure.In
104
-
105
- theirPubKey, err := ci.UnmarshalPublicKey(theirPkb)
106
- if err != nil {
107
- return err
108
- }
109
-
110
- challenge := make([]byte, secureChallengeSize)
111
- rand.Read(challenge)
112
-
113
- enc, err := theirPubKey.Encrypt(challenge)
114
- if err != nil {
115
- return err
116
- }
117
-
118
- chsig, err := sp.local.PrivKey().Sign(challenge)
119
- if err != nil {
120
- return err
121
- }
122
-
123
- if !sp.trySend(enc) {
124
- return context.Canceled
125
- }
126
- if !sp.trySend(chsig) {
127
- return context.Canceled
128
- }
129
-
130
- theirEnc, ok := sp.tryRecv()
131
- if !ok {
132
- return context.Canceled
133
- }
134
- theirChSig, ok := sp.tryRecv()
135
- if !ok {
136
- return context.Canceled
137
- }
138
-
139
- // Decrypt and verify their challenge
140
- unenc, err := sp.local.PrivKey().Decrypt(theirEnc)
141
- if err != nil {
142
- return err
143
- }
144
- ok, err = theirPubKey.Verify(unenc, theirChSig)
145
- if err != nil {
146
- return err
147
- }
148
- if !ok {
149
- return errors.New("Invalid signature!")
150
- }
151
-
152
- // Sign the unencrypted challenge, and send it back
153
- sig, err := sp.local.PrivKey().Sign(unenc)
154
- if err != nil {
155
- return err
156
- }
157
-
158
- if !sp.trySend(unenc) {
159
- return context.Canceled
160
- }
161
- if !sp.trySend(sig) {
162
- return context.Canceled
163
- }
164
- theirUnenc, ok := sp.tryRecv()
165
- if !ok {
166
- return context.Canceled
167
- }
168
- theirSig, ok := sp.tryRecv()
169
- if !ok {
170
- return context.Canceled
171
- }
172
-
173
- // Verify that they correctly unecrypted the challenge
174
- if !bytes.Equal(theirUnenc, challenge) {
175
- return errors.New("received bad challenge response")
176
- }
177
-
178
- correct, err := theirPubKey.Verify(theirUnenc, theirSig)
179
- if err != nil {
180
- return err
181
- }
182
-
183
- if !correct {
184
- return errors.New("Incorrect signature on challenge")
185
- }
186
-
187
- sp.removeMsgID = reduceChallenge(challenge)
188
- sp.localMsgID = reduceChallenge(unenc)
189
-
190
- go sp.handleIn(theirPubKey)
191
- go sp.handleOut(sp.local.PrivKey())
192
-
193
- finished := []byte("finished")
194
-
195
- select {
196
- case <-sp.ctx.Done():
197
- return context.Canceled
198
- case sp.Out <- finished:
199
- }
200
-
201
- var resp []byte
202
- select {
203
- case <-sp.ctx.Done():
204
- return context.Canceled
205
- case resp, ok = <-sp.In:
206
- if !ok {
207
- return errors.New("Channel closed before handshake finished.")
208
- }
209
- }
210
- if !bytes.Equal(resp, finished) {
211
- return errors.New("Handshake failed!")
212
- }
213
-
214
- return nil
215
-}
216
-
217
-func (sp *SignedPipe) handleOut(pk ci.PrivKey) {
218
- for {
219
- var data []byte
220
- var ok bool
221
- select {
222
- case <-sp.ctx.Done():
223
- return
224
- case data, ok = <-sp.Out:
225
- if !ok {
226
- log.Warning("pipe closed!")
227
- return
228
- }
229
- }
230
-
231
- sdata := new(pb.DataSig)
232
-
233
- sig, err := pk.Sign(data)
234
- if err != nil {
235
- log.Error("Error signing outgoing data: %s", err)
236
- return
237
- }
238
-
239
- sdata.Data = data
240
- sdata.Signature = sig
241
- sdata.Id = proto.Uint64(sp.localMsgID)
242
- b, err := proto.Marshal(sdata)
243
- if err != nil {
244
- log.Error("Error marshaling signed data object: %s", err)
245
- return
246
- }
247
- sp.localMsgID++
248
-
249
- select {
250
- case sp.insecure.Out <- b:
251
- case <-sp.ctx.Done():
252
- log.Debug("Context finished before send could occur")
253
- return
254
- }
255
- }
256
-}
257
-
258
-func (sp *SignedPipe) handleIn(theirPubkey ci.PubKey) {
259
- for {
260
- var data []byte
261
- var ok bool
262
- select {
263
- case <-sp.ctx.Done():
264
- return
265
- case data, ok = <-sp.insecure.In:
266
- if !ok {
267
- log.Debug("Signed pipe closed")
268
- return
269
- }
270
- }
271
-
272
- sdata := new(pb.DataSig)
273
- err := proto.Unmarshal(data, sdata)
274
- if err != nil {
275
- log.Error("Failed to unmarshal sigdata object")
276
- continue
277
- }
278
- correct, err := theirPubkey.Verify(sdata.GetData(), sdata.GetSignature())
279
- if err != nil {
280
- log.Error(err)
281
- continue
282
- }
283
- if !correct {
284
- log.Error("Received data with invalid signature!")
285
- continue
286
- }
287
-
288
- if sdata.GetId() != sp.removeMsgID {
289
- log.Critical("Out of order message id!")
290
- return
291
- }
292
- sp.removeMsgID++
293
-
294
- select {
295
- case <-sp.ctx.Done():
296
- return
297
- case sp.In <- sdata.GetData():
298
- }
299
- }
300
-}
301
-
302
-func (sp *SignedPipe) Close() error {
303
- sp.cancel()
304
- return nil
305
-}
crypto/spipe/spipe_test.go
-52
@@ -130,58 +130,6 @@ func runEncryptBenchmark(b *testing.B) {
130
131
}
132
133
-func BenchmarkSignedChannel(b *testing.B) {
134
- pstore := peer.NewPeerstore()
135
- ctx := context.TODO()
136
- bufsize := 1024 * 1024
137
-
138
- pa := getPeer(b)
139
- pb := getPeer(b)
140
- duplexa := pipes.NewDuplex(16)
141
- duplexb := pipes.NewDuplex(16)
142
-
143
- go bindDuplexNoCopy(duplexa, duplexb)
144
-
145
- var spb *SignedPipe
146
- done := make(chan struct{})
147
- go func() {
148
- var err error
149
- spb, err = NewSignedPipe(ctx, bufsize, pb, pstore, duplexb)
150
- if err != nil {
151
- b.Fatal(err)
152
- }
153
- done <- struct{}{}
154
- }()
155
-
156
- spa, err := NewSignedPipe(ctx, bufsize, pa, pstore, duplexa)
157
- if err != nil {
158
- b.Fatal(err)
159
- }
160
-
161
- <-done
162
-
163
- go func() {
164
- for _ = range spa.In {
165
- // Throw it all away,
166
- // all of your hopes and dreams
167
- // piped out to /dev/null...
168
- done <- struct{}{}
169
- }
170
- }()
171
-
172
- data := make([]byte, 1024*512)
173
- util.NewTimeSeededRand().Read(data)
174
- // Begin actual benchmarking
175
- b.ResetTimer()
176
-
177
- for i := 0; i < b.N; i++ {
178
- b.SetBytes(int64(len(data)))
179
- spb.Out <- data
180
- <-done
181
- }
182
-
183
-}
184
-
133
func BenchmarkDataTransfer(b *testing.B) {
134
duplexa := pipes.NewDuplex(16)
135
duplexb := pipes.NewDuplex(16)