1
1
package p2p
2
2
3
3
import (
4
- // "binary"
5
4
"crypto/ecdsa"
6
5
"crypto/rand"
6
+ "errors"
7
7
"fmt"
8
8
"io"
9
+ "net"
9
10
10
11
"github.com/ethereum/go-ethereum/crypto"
11
12
"github.com/ethereum/go-ethereum/crypto/ecies"
12
13
"github.com/ethereum/go-ethereum/crypto/secp256k1"
13
- ethlogger "github.com/ethereum/go-ethereum/logger"
14
14
"github.com/ethereum/go-ethereum/p2p/discover"
15
+ "github.com/ethereum/go-ethereum/rlp"
15
16
)
16
17
17
- var clogger = ethlogger .NewLogger ("CRYPTOID" )
18
-
19
18
const (
20
19
sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2
21
20
sigLen = 65 // elliptic S256
@@ -30,26 +29,76 @@ const (
30
29
rHSLen = authRespLen + eciesBytes // size of the final ECIES payload sent as receiver's handshake
31
30
)
32
31
33
- type hexkey []byte
32
+ type conn struct {
33
+ * frameRW
34
+ * protoHandshake
35
+ }
34
36
35
- func ( self hexkey ) String () string {
36
- return fmt . Sprintf ( "(%d) %x" , len ( self ), [] byte ( self ))
37
+ func newConn ( fd net. Conn , hs * protoHandshake ) * conn {
38
+ return & conn { newFrameRW ( fd , msgWriteTimeout ), hs }
37
39
}
38
40
39
- func encHandshake (conn io.ReadWriter , prv * ecdsa.PrivateKey , dial * discover.Node ) (
40
- remoteID discover.NodeID ,
41
- sessionToken []byte ,
42
- err error ,
43
- ) {
41
+ // encHandshake represents information about the remote end
42
+ // of a connection that is negotiated during the encryption handshake.
43
+ type encHandshake struct {
44
+ ID discover.NodeID
45
+ IngressMAC []byte
46
+ EgressMAC []byte
47
+ Token []byte
48
+ }
49
+
50
+ // protoHandshake is the RLP structure of the protocol handshake.
51
+ type protoHandshake struct {
52
+ Version uint64
53
+ Name string
54
+ Caps []Cap
55
+ ListenPort uint64
56
+ ID discover.NodeID
57
+ }
58
+
59
+ // setupConn starts a protocol session on the given connection.
60
+ // It runs the encryption handshake and the protocol handshake.
61
+ // If dial is non-nil, the connection the local node is the initiator.
62
+ func setupConn (fd net.Conn , prv * ecdsa.PrivateKey , our * protoHandshake , dial * discover.Node ) (* conn , error ) {
44
63
if dial == nil {
45
- var remotePubkey []byte
46
- sessionToken , remotePubkey , err = inboundEncHandshake (conn , prv , nil )
47
- copy (remoteID [:], remotePubkey )
64
+ return setupInboundConn (fd , prv , our )
48
65
} else {
49
- remoteID = dial .ID
50
- sessionToken , err = outboundEncHandshake (conn , prv , remoteID [:], nil )
66
+ return setupOutboundConn (fd , prv , our , dial )
67
+ }
68
+ }
69
+
70
+ func setupInboundConn (fd net.Conn , prv * ecdsa.PrivateKey , our * protoHandshake ) (* conn , error ) {
71
+ // var remotePubkey []byte
72
+ // sessionToken, remotePubkey, err = inboundEncHandshake(fd, prv, nil)
73
+ // copy(remoteID[:], remotePubkey)
74
+
75
+ rw := newFrameRW (fd , msgWriteTimeout )
76
+ rhs , err := readProtocolHandshake (rw , our )
77
+ if err != nil {
78
+ return nil , err
79
+ }
80
+ if err := writeProtocolHandshake (rw , our ); err != nil {
81
+ return nil , fmt .Errorf ("protocol write error: %v" , err )
82
+ }
83
+ return & conn {rw , rhs }, nil
84
+ }
85
+
86
+ func setupOutboundConn (fd net.Conn , prv * ecdsa.PrivateKey , our * protoHandshake , dial * discover.Node ) (* conn , error ) {
87
+ // remoteID = dial.ID
88
+ // sessionToken, err = outboundEncHandshake(fd, prv, remoteID[:], nil)
89
+
90
+ rw := newFrameRW (fd , msgWriteTimeout )
91
+ if err := writeProtocolHandshake (rw , our ); err != nil {
92
+ return nil , fmt .Errorf ("protocol write error: %v" , err )
51
93
}
52
- return remoteID , sessionToken , err
94
+ rhs , err := readProtocolHandshake (rw , our )
95
+ if err != nil {
96
+ return nil , fmt .Errorf ("protocol handshake read error: %v" , err )
97
+ }
98
+ if rhs .ID != dial .ID {
99
+ return nil , errors .New ("dialed node id mismatch" )
100
+ }
101
+ return & conn {rw , rhs }, nil
53
102
}
54
103
55
104
// outboundEncHandshake negotiates a session token on conn.
@@ -66,18 +115,9 @@ func outboundEncHandshake(conn io.ReadWriter, prvKey *ecdsa.PrivateKey, remotePu
66
115
if err != nil {
67
116
return nil , err
68
117
}
69
- if sessionToken != nil {
70
- clogger .Debugf ("session-token: %v" , hexkey (sessionToken ))
71
- }
72
-
73
- clogger .Debugf ("initiator-nonce: %v" , hexkey (initNonce ))
74
- clogger .Debugf ("initiator-random-private-key: %v" , hexkey (crypto .FromECDSA (randomPrivKey )))
75
- randomPublicKeyS , _ := exportPublicKey (& randomPrivKey .PublicKey )
76
- clogger .Debugf ("initiator-random-public-key: %v" , hexkey (randomPublicKeyS ))
77
118
if _ , err = conn .Write (auth ); err != nil {
78
119
return nil , err
79
120
}
80
- clogger .Debugf ("initiator handshake: %v" , hexkey (auth ))
81
121
82
122
response := make ([]byte , rHSLen )
83
123
if _ , err = io .ReadFull (conn , response ); err != nil {
@@ -88,9 +128,6 @@ func outboundEncHandshake(conn io.ReadWriter, prvKey *ecdsa.PrivateKey, remotePu
88
128
return nil , err
89
129
}
90
130
91
- clogger .Debugf ("receiver-nonce: %v" , hexkey (recNonce ))
92
- remoteRandomPubKeyS , _ := exportPublicKey (remoteRandomPubKey )
93
- clogger .Debugf ("receiver-random-public-key: %v" , hexkey (remoteRandomPubKeyS ))
94
131
return newSession (initNonce , recNonce , randomPrivKey , remoteRandomPubKey )
95
132
}
96
133
@@ -221,12 +258,9 @@ func inboundEncHandshake(conn io.ReadWriter, prvKey *ecdsa.PrivateKey, sessionTo
221
258
if err != nil {
222
259
return nil , nil , err
223
260
}
224
- clogger .Debugf ("receiver-nonce: %v" , hexkey (recNonce ))
225
- clogger .Debugf ("receiver-random-priv-key: %v" , hexkey (crypto .FromECDSA (randomPrivKey )))
226
261
if _ , err = conn .Write (response ); err != nil {
227
262
return nil , nil , err
228
263
}
229
- clogger .Debugf ("receiver handshake:\n %v" , hexkey (response ))
230
264
token , err = newSession (initNonce , recNonce , randomPrivKey , remoteRandomPubKey )
231
265
return token , remotePubKey , err
232
266
}
@@ -361,3 +395,40 @@ func xor(one, other []byte) (xor []byte) {
361
395
}
362
396
return xor
363
397
}
398
+
399
+ func writeProtocolHandshake (w MsgWriter , our * protoHandshake ) error {
400
+ return EncodeMsg (w , handshakeMsg , our .Version , our .Name , our .Caps , our .ListenPort , our .ID [:])
401
+ }
402
+
403
+ func readProtocolHandshake (r MsgReader , our * protoHandshake ) (* protoHandshake , error ) {
404
+ // read and handle remote handshake
405
+ msg , err := r .ReadMsg ()
406
+ if err != nil {
407
+ return nil , err
408
+ }
409
+ if msg .Code == discMsg {
410
+ // disconnect before protocol handshake is valid according to the
411
+ // spec and we send it ourself if Server.addPeer fails.
412
+ var reason DiscReason
413
+ rlp .Decode (msg .Payload , & reason )
414
+ return nil , discRequestedError (reason )
415
+ }
416
+ if msg .Code != handshakeMsg {
417
+ return nil , fmt .Errorf ("expected handshake, got %x" , msg .Code )
418
+ }
419
+ if msg .Size > baseProtocolMaxMsgSize {
420
+ return nil , fmt .Errorf ("message too big (%d > %d)" , msg .Size , baseProtocolMaxMsgSize )
421
+ }
422
+ var hs protoHandshake
423
+ if err := msg .Decode (& hs ); err != nil {
424
+ return nil , err
425
+ }
426
+ // validate handshake info
427
+ if hs .Version != our .Version {
428
+ return nil , newPeerError (errP2PVersionMismatch , "required version %d, received %d\n " , baseProtocolVersion , hs .Version )
429
+ }
430
+ if (hs .ID == discover.NodeID {}) {
431
+ return nil , newPeerError (errPubkeyInvalid , "missing" )
432
+ }
433
+ return & hs , nil
434
+ }
0 commit comments