Commit 68205dec authored by zelig's avatar zelig Committed by Felix Lange

make crypto handshake calls package level, store privateKey on peer + tests ok

parent 44997435
This diff is collapsed.
...@@ -78,40 +78,35 @@ func TestCryptoHandshake(t *testing.T) { ...@@ -78,40 +78,35 @@ func TestCryptoHandshake(t *testing.T) {
prv1, _ := crypto.GenerateKey() prv1, _ := crypto.GenerateKey()
pub1 := &prv1.PublicKey pub1 := &prv1.PublicKey
var initiator, receiver *cryptoId pub0s := crypto.FromECDSAPub(pub0)
if initiator, err = newCryptoId(&peerId{crypto.FromECDSA(prv0), crypto.FromECDSAPub(pub0)}); err != nil { pub1s := crypto.FromECDSAPub(pub1)
return
}
if receiver, err = newCryptoId(&peerId{crypto.FromECDSA(prv1), crypto.FromECDSAPub(pub1)}); err != nil {
return
}
// simulate handshake by feeding output to input // simulate handshake by feeding output to input
// initiator sends handshake 'auth' // initiator sends handshake 'auth'
auth, initNonce, randomPrivKey, _, err := initiator.startHandshake(receiver.pubKeyS, sessionToken) auth, initNonce, randomPrivKey, _, err := startHandshake(prv0, pub1s, sessionToken)
if err != nil { if err != nil {
t.Errorf("%v", err) t.Errorf("%v", err)
} }
// receiver reads auth and responds with response // receiver reads auth and responds with response
response, remoteRecNonce, remoteInitNonce, remoteRandomPrivKey, remoteInitRandomPubKey, err := receiver.respondToHandshake(auth, crypto.FromECDSAPub(pub0), sessionToken) response, remoteRecNonce, remoteInitNonce, remoteRandomPrivKey, remoteInitRandomPubKey, err := respondToHandshake(auth, prv1, pub0s, sessionToken)
if err != nil { if err != nil {
t.Errorf("%v", err) t.Errorf("%v", err)
} }
// initiator reads receiver's response and the key exchange completes // initiator reads receiver's response and the key exchange completes
recNonce, remoteRandomPubKey, _, err := initiator.completeHandshake(response) recNonce, remoteRandomPubKey, _, err := completeHandshake(response, prv0)
if err != nil { if err != nil {
t.Errorf("%v", err) t.Errorf("%v", err)
} }
// now both parties should have the same session parameters // now both parties should have the same session parameters
initSessionToken, initSecretRW, err := initiator.newSession(true, initNonce, recNonce, auth, randomPrivKey, remoteRandomPubKey) initSessionToken, initSecretRW, err := newSession(true, initNonce, recNonce, auth, randomPrivKey, remoteRandomPubKey)
if err != nil { if err != nil {
t.Errorf("%v", err) t.Errorf("%v", err)
} }
recSessionToken, recSecretRW, err := receiver.newSession(false, remoteInitNonce, remoteRecNonce, auth, remoteRandomPrivKey, remoteInitRandomPubKey) recSessionToken, recSecretRW, err := newSession(false, remoteInitNonce, remoteRecNonce, auth, remoteRandomPrivKey, remoteInitRandomPubKey)
if err != nil { if err != nil {
t.Errorf("%v", err) t.Errorf("%v", err)
} }
...@@ -163,12 +158,12 @@ func TestPeersHandshake(t *testing.T) { ...@@ -163,12 +158,12 @@ func TestPeersHandshake(t *testing.T) {
initiator := newPeer(conn1, []Protocol{}, nil) initiator := newPeer(conn1, []Protocol{}, nil)
receiver := newPeer(conn2, []Protocol{}, nil) receiver := newPeer(conn2, []Protocol{}, nil)
initiator.dialAddr = &peerAddr{IP: net.ParseIP("1.2.3.4"), Port: 2222, Pubkey: pub1s[1:]} initiator.dialAddr = &peerAddr{IP: net.ParseIP("1.2.3.4"), Port: 2222, Pubkey: pub1s[1:]}
initiator.ourID = &peerId{prv0s, pub0s} initiator.privateKey = prv0s
// this is cheating. identity of initiator/dialler not available to listener/receiver // this is cheating. identity of initiator/dialler not available to listener/receiver
// its public key should be looked up based on IP address // its public key should be looked up based on IP address
receiver.identity = initiator.ourID receiver.identity = &peerId{nil, pub0s}
receiver.ourID = &peerId{prv1s, pub1s} receiver.privateKey = prv1s
initiator.pubkeyHook = func(*peerAddr) error { return nil } initiator.pubkeyHook = func(*peerAddr) error { return nil }
receiver.pubkeyHook = func(*peerAddr) error { return nil } receiver.pubkeyHook = func(*peerAddr) error { return nil }
......
...@@ -3,6 +3,7 @@ package p2p ...@@ -3,6 +3,7 @@ package p2p
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"crypto/ecdsa"
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"io" "io"
...@@ -12,6 +13,8 @@ import ( ...@@ -12,6 +13,8 @@ import (
"sync" "sync"
"time" "time"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
) )
...@@ -73,6 +76,7 @@ type Peer struct { ...@@ -73,6 +76,7 @@ type Peer struct {
runBaseProtocol bool // for testing runBaseProtocol bool // for testing
cryptoHandshake bool // for testing cryptoHandshake bool // for testing
cryptoReady chan struct{} cryptoReady chan struct{}
privateKey []byte
runlock sync.RWMutex // protects running runlock sync.RWMutex // protects running
running map[string]*proto running map[string]*proto
...@@ -338,6 +342,13 @@ func (p *Peer) dispatch(msg Msg, protoDone chan struct{}) (wait bool, err error) ...@@ -338,6 +342,13 @@ func (p *Peer) dispatch(msg Msg, protoDone chan struct{}) (wait bool, err error)
type readLoop func(chan<- Msg, chan<- error, <-chan bool) type readLoop func(chan<- Msg, chan<- error, <-chan bool)
func (p *Peer) PrivateKey() (prv *ecdsa.PrivateKey, err error) {
if prv = crypto.ToECDSA(p.privateKey); prv == nil {
err = fmt.Errorf("invalid private key")
}
return
}
func (p *Peer) handleCryptoHandshake() (loop readLoop, err error) { func (p *Peer) handleCryptoHandshake() (loop readLoop, err error) {
// cryptoId is just created for the lifecycle of the handshake // cryptoId is just created for the lifecycle of the handshake
// it is survived by an encrypted readwriter // it is survived by an encrypted readwriter
...@@ -350,17 +361,17 @@ func (p *Peer) handleCryptoHandshake() (loop readLoop, err error) { ...@@ -350,17 +361,17 @@ func (p *Peer) handleCryptoHandshake() (loop readLoop, err error) {
if p.dialAddr != nil { // this should have its own method Outgoing() bool if p.dialAddr != nil { // this should have its own method Outgoing() bool
initiator = true initiator = true
} }
// create crypto layer
// this could in principle run only once but maybe we want to allow
// identity switching
var crypto *cryptoId
if crypto, err = newCryptoId(p.ourID); err != nil {
return
}
// run on peer // run on peer
// this bit handles the handshake and creates a secure communications channel with // this bit handles the handshake and creates a secure communications channel with
// var rw *secretRW // var rw *secretRW
if sessionToken, _, err = crypto.Run(p.conn, p.Pubkey(), sessionToken, initiator); err != nil { var prvKey *ecdsa.PrivateKey
if prvKey, err = p.PrivateKey(); err != nil {
err = fmt.Errorf("unable to access private key for client: %v", err)
return
}
// initialise a new secure session
if sessionToken, _, err = NewSecureSession(p.conn, prvKey, p.Pubkey(), sessionToken, initiator); err != nil {
p.Debugf("unable to setup secure session: %v", err) p.Debugf("unable to setup secure session: %v", err)
return return
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment