diff --git a/p2p/crypto.go b/p2p/crypto.go index 37c6e1fc98..728b8e884e 100644 --- a/p2p/crypto.go +++ b/p2p/crypto.go @@ -53,6 +53,21 @@ func newCryptoId(id ClientIdentity) (self *cryptoId, err error) { return } +func (self *cryptoId) Run(remotePubKeyDER []byte) (rw *secretRW) { + if self.initiator { + auth, initNonce, randomPrvKey, randomPubKey, err := initiator.initAuth(remotePubKeyDER, sessionToken) + + respNonce, remoteRandomPubKey, _, _ := initiator.verifyAuthResp(response) + } else { + // we are listening connection. we are responders in the haandshake. + // Extract info from the authentication. The initiator starts by sending us a handshake that we need to respond to. + response, remoteRespNonce, remoteInitNonce, remoteRandomPrivKey, _ := responder.verifyAuth(auth, sessionToken, pubInit) + + } + initSessionToken, initSecretRW, _ := initiator.newSession(initNonce, respNonce, auth, randomPrvKey, remoteRandomPubKey) + respSessionToken, respSecretRW, _ := responder.newSession(remoteInitNonce, remoteRespNonce, auth, remoteRandomPrivKey, randomPubKey) +} + /* startHandshake is called by peer if it initiated the connection. By protocol spec, the party who initiates the connection (initiator) will send an 'auth' packet New: authInitiator -> E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0) diff --git a/p2p/peer.go b/p2p/peer.go index 886b95a80b..e98c3d5608 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -222,10 +222,14 @@ func (p *Peer) loop() (reason DiscReason, err error) { defer close(p.closed) defer p.conn.Close() + var readLoop func(chan Msg, chan error, chan bool) if p.cryptoHandshake { - if err := p.handleCryptoHandshake(); err != nil { + if readLoop, err := p.handleCryptoHandshake(); err != nil { + // from here on everything can be encrypted, authenticated return DiscProtocolError, err // no graceful disconnect } + } else { + readLoop = p.readLoop } // read loop @@ -233,7 +237,7 @@ func (p *Peer) loop() (reason DiscReason, err error) { readErr := make(chan error) readNext := make(chan bool, 1) protoDone := make(chan struct{}, 1) - go p.readLoop(readMsg, readErr, readNext) + go readLoop(readMsg, readErr, readNext) readNext <- true if p.runBaseProtocol { @@ -329,8 +333,19 @@ func (p *Peer) dispatch(msg Msg, protoDone chan struct{}) (wait bool, err error) } func (p *Peer) handleCryptoHandshake() (err error) { + // cryptoId is just created for the lifecycle of the handshake + // it is survived by an encrypted readwriter + if p.dialAddr != 0 { // this should have its own method Outgoing() bool + initiator = true + } + // create crypto layer + cryptoId := newCryptoId(p.identity, initiator, sessionToken) + // run on peer + if rw, err := cryptoId.Run(p.Pubkey()); err != nil { + return err + } + p.conn = rw.Run(p.conn) - return nil } func (p *Peer) startBaseProtocol() {