@cryptotaxi247 / kubo / commits / 6efaa1d81

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)