From dbef516659bde2cf0e0baa7bb0d545345d0c4d06 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 14 Jul 2015 18:41:24 -0700 Subject: [PATCH] failing tests for secret_connection --- p2p/peer_set.go | 6 --- p2p/peer_set_test.go | 3 -- p2p/secret_connection.go | 31 +++++++++------ p2p/secret_connection_test.go | 72 +++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 21 deletions(-) create mode 100644 p2p/secret_connection_test.go diff --git a/p2p/peer_set.go b/p2p/peer_set.go index 8e85af555..c530c383c 100644 --- a/p2p/peer_set.go +++ b/p2p/peer_set.go @@ -1,7 +1,6 @@ package p2p import ( - "fmt" "net" "strings" "sync" @@ -182,21 +181,16 @@ func (ps *PeerSet) incrIPRangeCounts(address string) bool { // max peers for each range and incrementing if not. // Returns false if incr failed because max peers reached for some range counter. func incrNestedCounters(c *nestedCounter, ipBytes []string, index int) bool { - fmt.Println("incr:", c.count, ipBytes, index) ipByte := ipBytes[index] child := c.children[ipByte] if child == nil { child = NewNestedCounter() c.children[ipByte] = child } - fmt.Println("incr child:", child.count) if index+1 < len(ipBytes) { - fmt.Println("1>>") if !incrNestedCounters(child, ipBytes, index+1) { return false } - } else { - fmt.Println("2>>") } if maxPeersPerIPRange[index] <= child.count { return false diff --git a/p2p/peer_set_test.go b/p2p/peer_set_test.go index 6d47ca73b..22424615a 100644 --- a/p2p/peer_set_test.go +++ b/p2p/peer_set_test.go @@ -1,7 +1,6 @@ package p2p import ( - "fmt" "math/rand" "strings" "testing" @@ -93,7 +92,6 @@ func TestIPRanges(t *testing.T) { peerSet := NewPeerSet() // test /8 - fmt.Println("---") maxPeersPerIPRange = [4]int{2, 2, 2, 2} peer := newPeerInIPRange("54") if err := peerSet.Add(peer); err != nil { @@ -111,7 +109,6 @@ func TestIPRanges(t *testing.T) { if err := peerSet.Add(peer); err != nil { t.Errorf("Failed to add new peer") } - fmt.Println("---END") // test /16 peerSet = NewPeerSet() diff --git a/p2p/secret_connection.go b/p2p/secret_connection.go index 0c8b8015b..e6c23dd27 100644 --- a/p2p/secret_connection.go +++ b/p2p/secret_connection.go @@ -8,7 +8,6 @@ import ( "encoding/binary" "errors" "io" - "net" "sync" "golang.org/x/crypto/nacl/box" @@ -23,9 +22,10 @@ import ( const dataLenSize = 2 // uint16 to describe the length, is <= dataMaxSize const dataMaxSize = 1024 const totalFrameSize = dataMaxSize + dataLenSize +const sealedFrameSize = totalFrameSize + secretbox.Overhead type SecretConnection struct { - conn net.Conn + conn io.ReadWriter recvBuffer []byte recvNonce *[24]byte sendNonce *[24]byte @@ -33,9 +33,10 @@ type SecretConnection struct { shrSecret *[32]byte // shared secret } -// If handshake error, will return nil. +// Performs handshake and returns a new authenticated SecretConnection. +// Returns nil if error in handshake. // Caller should call conn.Close() -func secretHandshake(conn net.Conn, locPrivKey acm.PrivKeyEd25519) (*SecretConnection, error) { +func MakeSecretConnection(conn io.ReadWriter, locPrivKey acm.PrivKeyEd25519) (*SecretConnection, error) { locPubKey := locPrivKey.PubKey().(acm.PubKeyEd25519) @@ -43,7 +44,7 @@ func secretHandshake(conn net.Conn, locPrivKey acm.PrivKeyEd25519) (*SecretConne locEphPub, locEphPriv := genEphKeys() // Write local ephemeral pubkey and receive one too. - remEphPub, err := share32(conn, locEphPub) + remEphPub, err := shareEphPubKey(conn, locEphPub) // Compute common shared secret. shrSecret := computeSharedSecret(remEphPub, locEphPriv) @@ -84,6 +85,12 @@ func secretHandshake(conn net.Conn, locPrivKey acm.PrivKeyEd25519) (*SecretConne return sc, nil } +// Returns authenticated remote pubkey +func (sc *SecretConnection) RemotePubKey() acm.PubKeyEd25519 { + return sc.remPubKey +} + +// Writes encrypted frames of `sealedFrameSize` // CONTRACT: data smaller than dataMaxSize is read atomically. func (sc *SecretConnection) Write(data []byte) (n int, err error) { for 0 < len(data) { @@ -101,7 +108,7 @@ func (sc *SecretConnection) Write(data []byte) (n int, err error) { copy(frame[dataLenSize:], chunk) // encrypt the frame - var sealedFrame = make([]byte, totalFrameSize+secretbox.Overhead) + var sealedFrame = make([]byte, sealedFrameSize) secretbox.Seal(sealedFrame, frame, sc.sendNonce, sc.shrSecret) incr2Nonce(sc.sendNonce) // end encryption @@ -124,7 +131,7 @@ func (sc *SecretConnection) Read(data []byte) (n int, err error) { return } - sealedFrame := make([]byte, totalFrameSize+secretbox.Overhead) + sealedFrame := make([]byte, sealedFrameSize) _, err = io.ReadFull(sc.conn, sealedFrame) if err != nil { return @@ -156,20 +163,20 @@ func genEphKeys() (ephPub, ephPriv *[32]byte) { return } -func share32(conn net.Conn, sendBytes *[32]byte) (recvBytes *[32]byte, err error) { +func shareEphPubKey(conn io.ReadWriter, locEphPub *[32]byte) (remEphPub *[32]byte, err error) { var err1, err2 error var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() - _, err1 = conn.Write(sendBytes[:]) + _, err1 = conn.Write(locEphPub[:]) }() go func() { defer wg.Done() - recvBytes = new([32]byte) - _, err2 = io.ReadFull(conn, recvBytes[:]) + remEphPub = new([32]byte) + _, err2 = io.ReadFull(conn, remEphPub[:]) }() wg.Wait() @@ -180,7 +187,7 @@ func share32(conn net.Conn, sendBytes *[32]byte) (recvBytes *[32]byte, err error return nil, err2 } - return recvBytes, nil + return remEphPub, nil } func computeSharedSecret(remPubKey, locPrivKey *[32]byte) (shrSecret *[32]byte) { diff --git a/p2p/secret_connection_test.go b/p2p/secret_connection_test.go new file mode 100644 index 000000000..634d8309a --- /dev/null +++ b/p2p/secret_connection_test.go @@ -0,0 +1,72 @@ +package p2p + +import ( + "bytes" + "io" + "sync" + "testing" + + acm "github.com/tendermint/tendermint/account" + . "github.com/tendermint/tendermint/common" +) + +type dummyReadWriter struct { + io.Reader + io.Writer +} + +// Each returned ReadWriter is akin to a net.Connection +func makeReadWriterPair() (foo, bar io.ReadWriter) { + barReader, fooWriter := io.Pipe() + fooReader, barWriter := io.Pipe() + return dummyReadWriter{fooReader, fooWriter}, dummyReadWriter{barReader, barWriter} +} + +func TestSecretConnectionHandshake(t *testing.T) { + foo, bar := makeReadWriterPair() + fooPrvKey := acm.PrivKeyEd25519(CRandBytes(32)) + fooPubKey := fooPrvKey.PubKey().(acm.PubKeyEd25519) + barPrvKey := acm.PrivKeyEd25519(CRandBytes(32)) + barPubKey := barPrvKey.PubKey().(acm.PubKeyEd25519) + + var fooConn, barConn *SecretConnection + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + var err error + fooConn, err = MakeSecretConnection(foo, fooPrvKey) + if err != nil { + t.Errorf("Failed to establish SecretConnection for foo: %v", err) + return + } + if !bytes.Equal(fooConn.RemotePubKey(), fooPubKey) { + t.Errorf("Unexpected fooConn.RemotePubKey. Expected %X, got %X", + fooPubKey, fooConn.RemotePubKey()) + } + }() + go func() { + defer wg.Done() + var err error + barConn, err = MakeSecretConnection(bar, barPrvKey) + if barConn == nil { + t.Errorf("Failed to establish SecretConnection for bar: %v", err) + return + } + if !bytes.Equal(barConn.RemotePubKey(), barPubKey) { + t.Errorf("Unexpected barConn.RemotePubKey. Expected %X, got %X", + barPubKey, barConn.RemotePubKey()) + } + }() + wg.Wait() +} + +func BenchmarkSecretConnection(b *testing.B) { + b.StopTimer() + b.StartTimer() + + for i := 0; i < b.N; i++ { + } + + b.StopTimer() +}