From fb9507aef3c136c564a9516070bb002e52ac2e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=BF=97=E5=AE=87?= Date: Wed, 3 Jul 2019 23:37:27 +0800 Subject: [PATCH 1/2] Removed duplicate modules. --- Makefile | 2 +- go.mod | 1 - internal/ioutil/ack_waiter.go | 101 ------- internal/ioutil/ack_waiter_test.go | 47 ---- internal/ioutil/atomic_bool.go | 23 -- internal/ioutil/buf_read.go | 16 -- internal/ioutil/len_read_writer.go | 57 ---- internal/ioutil/len_read_writer_test.go | 72 ----- internal/noise/dh.go | 37 --- internal/noise/net.go | 239 ----------------- internal/noise/net_test.go | 341 ------------------------ internal/noise/noise.go | 152 ----------- internal/noise/noise_test.go | 139 ---------- internal/noise/read_writer.go | 172 ------------ internal/noise/read_writer_test.go | 215 --------------- pkg/cipher/cipher.go | 255 ------------------ pkg/cipher/cipher_test.go | 100 ------- pkg/manager/node.go | 2 +- pkg/node/node.go | 2 +- pkg/router/loop_list.go | 2 +- pkg/router/router.go | 2 +- pkg/router/router_test.go | 2 +- vendor/modules.txt | 2 +- 23 files changed, 7 insertions(+), 1974 deletions(-) delete mode 100644 internal/ioutil/ack_waiter.go delete mode 100644 internal/ioutil/ack_waiter_test.go delete mode 100644 internal/ioutil/atomic_bool.go delete mode 100644 internal/ioutil/buf_read.go delete mode 100644 internal/ioutil/len_read_writer.go delete mode 100644 internal/ioutil/len_read_writer_test.go delete mode 100644 internal/noise/dh.go delete mode 100644 internal/noise/net.go delete mode 100644 internal/noise/net_test.go delete mode 100644 internal/noise/noise.go delete mode 100644 internal/noise/noise_test.go delete mode 100644 internal/noise/read_writer.go delete mode 100644 internal/noise/read_writer_test.go delete mode 100644 pkg/cipher/cipher.go delete mode 100644 pkg/cipher/cipher_test.go diff --git a/Makefile b/Makefile index 454c1e33d..e5ad3fa04 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ test: ## Run tests ${OPTS} go test ${TEST_OPTS} ./internal/... #${OPTS} go test -race -tags no_ci -cover -timeout=5m ./pkg/... ${OPTS} go test ${TEST_OPTS} ./pkg/app/... - ${OPTS} go test ${TEST_OPTS} ./pkg/cipher/... +# ${OPTS} go test ${TEST_OPTS} ./pkg/cipher/... ${OPTS} go test ${TEST_OPTS} ./pkg/manager/... ${OPTS} go test ${TEST_OPTS} ./pkg/node/... ${OPTS} go test ${TEST_OPTS} ./pkg/route-finder/... diff --git a/go.mod b/go.mod index 2d0733a74..8372dd0a9 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.12 require ( github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 - github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 github.com/go-chi/chi v4.0.2+incompatible github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.0 diff --git a/internal/ioutil/ack_waiter.go b/internal/ioutil/ack_waiter.go deleted file mode 100644 index db68b8820..000000000 --- a/internal/ioutil/ack_waiter.go +++ /dev/null @@ -1,101 +0,0 @@ -package ioutil - -import ( - "context" - "crypto/rand" - "encoding/binary" - "io" - "math" - "sync" -) - -// Uint16Seq is part of the acknowledgement-waiting logic. -type Uint16Seq uint16 - -// DecodeUint16Seq decodes a slice to Uint16Seq. -func DecodeUint16Seq(b []byte) Uint16Seq { - if len(b) < 2 { - return 0 - } - return Uint16Seq(binary.BigEndian.Uint16(b[:2])) -} - -// Encode encodes the Uint16Seq to a 2-byte slice. -func (s Uint16Seq) Encode() []byte { - b := make([]byte, 2) - binary.BigEndian.PutUint16(b, uint16(s)) - return b -} - -// Uint16AckWaiter implements acknowledgement-waiting logic (with uint16 sequences). -type Uint16AckWaiter struct { - nextSeq Uint16Seq - waiters [math.MaxUint16 + 1]chan struct{} - mx sync.RWMutex -} - -// RandSeq should only be run once on startup. It is not thread-safe. -func (w *Uint16AckWaiter) RandSeq() error { - b := make([]byte, 2) - if _, err := rand.Read(b); err != nil { - return err - } - w.nextSeq = DecodeUint16Seq(b) - return nil -} - -func (w *Uint16AckWaiter) stopWaiter(seq Uint16Seq) { - if waiter := w.waiters[seq]; waiter != nil { - close(waiter) - w.waiters[seq] = nil - } -} - -// StopAll stops all active waiters. -func (w *Uint16AckWaiter) StopAll() { - w.mx.Lock() - for seq := range w.waiters { - w.stopWaiter(Uint16Seq(seq)) - } - w.mx.Unlock() -} - -// Wait performs the given action, and waits for given seq to be Done. -func (w *Uint16AckWaiter) Wait(ctx context.Context, action func(seq Uint16Seq) error) (err error) { - ackCh := make(chan struct{}, 1) - - w.mx.Lock() - seq := w.nextSeq - w.nextSeq++ - w.waiters[seq] = ackCh - w.mx.Unlock() - - if err = action(seq); err != nil { - return err - } - - select { - case _, ok := <-ackCh: - if !ok { - // waiter stopped manually. - err = io.ErrClosedPipe - } - case <-ctx.Done(): - err = ctx.Err() - } - - w.mx.Lock() - w.stopWaiter(seq) - w.mx.Unlock() - return err -} - -// Done finishes given sequence. -func (w *Uint16AckWaiter) Done(seq Uint16Seq) { - w.mx.RLock() - select { - case w.waiters[seq] <- struct{}{}: - default: - } - w.mx.RUnlock() -} diff --git a/internal/ioutil/ack_waiter_test.go b/internal/ioutil/ack_waiter_test.go deleted file mode 100644 index 3ba22c591..000000000 --- a/internal/ioutil/ack_waiter_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package ioutil_test - -import ( - "context" - "sync" - "testing" - - "github.com/skycoin/skywire/internal/ioutil" -) - -func TestUint16AckWaiter_Wait(t *testing.T) { - - // Ensure that no race conditions occurs when - // each concurrent call to 'Uint16AckWaiter.Wait()' is met with - // multiple concurrent calls to 'Uint16AckWaiter.Done()' with the same seq. - t.Run("ensure_no_race_conditions", func(*testing.T) { - w := new(ioutil.Uint16AckWaiter) - defer w.StopAll() - - seqChan := make(chan ioutil.Uint16Seq) - defer close(seqChan) - - wg := new(sync.WaitGroup) - - for i := 0; i < 64; i++ { - wg.Add(1) - go func() { - defer wg.Done() - _ = w.Wait(context.TODO(), func(seq ioutil.Uint16Seq) error { //nolint:errcheck,unparam - seqChan <- seq - return nil - }) - }() - - seq := <-seqChan - for j := 0; j <= i; j++ { - wg.Add(1) - go func() { - defer wg.Done() - w.Done(seq) - }() - } - } - - wg.Wait() - }) -} diff --git a/internal/ioutil/atomic_bool.go b/internal/ioutil/atomic_bool.go deleted file mode 100644 index dab1f0b47..000000000 --- a/internal/ioutil/atomic_bool.go +++ /dev/null @@ -1,23 +0,0 @@ -package ioutil - -import "sync/atomic" - -// AtomicBool implements a thread-safe boolean value. -type AtomicBool struct { - flag int32 -} - -// Set set's the boolean to specified value -// and returns true if the value is changed. -func (b *AtomicBool) Set(v bool) bool { - newF := int32(0) - if v { - newF = 1 - } - return atomic.CompareAndSwapInt32(&b.flag, b.flag, newF) -} - -// Get obtains the current boolean value. -func (b *AtomicBool) Get() bool { - return atomic.LoadInt32(&b.flag) == 1 -} diff --git a/internal/ioutil/buf_read.go b/internal/ioutil/buf_read.go deleted file mode 100644 index b6310fd7f..000000000 --- a/internal/ioutil/buf_read.go +++ /dev/null @@ -1,16 +0,0 @@ -package ioutil - -import ( - "bytes" -) - -// BufRead is designed to help writing 'io.Reader' implementations. -// It reads from 'data' into 'p'. If 'p' is short, write to 'buf'. -// Note that one should check if 'buf' has data and read from that first before calling this function. -func BufRead(buf *bytes.Buffer, data, p []byte) (int, error) { - n := copy(p, data) - if n < len(data) { - buf.Write(data[n:]) - } - return n, nil -} diff --git a/internal/ioutil/len_read_writer.go b/internal/ioutil/len_read_writer.go deleted file mode 100644 index dffaf48b7..000000000 --- a/internal/ioutil/len_read_writer.go +++ /dev/null @@ -1,57 +0,0 @@ -package ioutil - -import ( - "bytes" - "encoding/binary" - "io" - "sync" -) - -// LenReadWriter writes len prepended packets and always reads whole -// packet. If read buffer is smaller than packet, LenReadWriter will -// buffer unread part and will return it first in subsequent reads. -type LenReadWriter struct { - io.ReadWriter - buf bytes.Buffer - mx sync.Mutex -} - -// NewLenReadWriter constructs a new LenReadWriter. -func NewLenReadWriter(rw io.ReadWriter) *LenReadWriter { - return &LenReadWriter{ReadWriter: rw} -} - -// ReadPacket returns single received len prepended packet. -func (rw *LenReadWriter) ReadPacket() ([]byte, error) { - h := make([]byte, 2) - if _, err := io.ReadFull(rw.ReadWriter, h); err != nil { - return nil, err - } - data := make([]byte, binary.BigEndian.Uint16(h)) - _, err := io.ReadFull(rw.ReadWriter, data) - return data, err -} - -func (rw *LenReadWriter) Read(p []byte) (n int, err error) { - rw.mx.Lock() - defer rw.mx.Unlock() - - if rw.buf.Len() != 0 { - return rw.buf.Read(p) - } - - var data []byte - data, err = rw.ReadPacket() - if err != nil { - return - } - - return BufRead(&rw.buf, data, p) -} - -func (rw *LenReadWriter) Write(p []byte) (n int, err error) { - buf := make([]byte, 2) - binary.BigEndian.PutUint16(buf, uint16(len(p))) - n, err = rw.ReadWriter.Write(append(buf, p...)) - return n - 2, err -} diff --git a/internal/ioutil/len_read_writer_test.go b/internal/ioutil/len_read_writer_test.go deleted file mode 100644 index 0b55b1b7a..000000000 --- a/internal/ioutil/len_read_writer_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package ioutil - -import ( - "log" - "net" - "os" - "testing" - - "github.com/skycoin/skycoin/src/util/logging" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestMain(m *testing.M) { - loggingLevel, ok := os.LookupEnv("TEST_LOGGING_LEVEL") - if ok { - lvl, err := logging.LevelFromString(loggingLevel) - if err != nil { - log.Fatal(err) - } - logging.SetLevel(lvl) - } else { - logging.Disable() - } - - os.Exit(m.Run()) -} - -func TestLenReadWriter(t *testing.T) { - in, out := net.Pipe() - rwIn := NewLenReadWriter(in) - rwOut := NewLenReadWriter(out) - - errCh := make(chan error) - go func() { - _, err := rwIn.Write([]byte("foo")) - errCh <- err - }() - - buf := make([]byte, 2) - n, err := rwOut.Read(buf) - require.NoError(t, err) - require.NoError(t, <-errCh) - assert.Equal(t, 2, n) - assert.Equal(t, []byte("fo"), buf) - - buf = make([]byte, 2) - n, err = rwOut.Read(buf) - require.NoError(t, err) - assert.Equal(t, 1, n) - assert.Equal(t, []byte("o"), buf[:n]) - - go func() { - _, err := rwIn.Write([]byte("foo")) - errCh <- err - }() - - packet, err := rwOut.ReadPacket() - require.NoError(t, err) - require.NoError(t, <-errCh) - assert.Equal(t, []byte("foo"), packet) - - go func() { - _, err := rwOut.ReadPacket() - errCh <- err - }() - - n, err = rwIn.Write([]byte("bar")) - require.NoError(t, err) - require.NoError(t, <-errCh) - assert.Equal(t, 3, n) -} diff --git a/internal/noise/dh.go b/internal/noise/dh.go deleted file mode 100644 index 6da7ab693..000000000 --- a/internal/noise/dh.go +++ /dev/null @@ -1,37 +0,0 @@ -package noise - -import ( - "io" - - "github.com/flynn/noise" - "github.com/skycoin/skycoin/src/cipher" -) - -// Secp256k1 implements `noise.DHFunc`. -type Secp256k1 struct{} - -// GenerateKeypair helps to implement `noise.DHFunc`. -func (Secp256k1) GenerateKeypair(_ io.Reader) (noise.DHKey, error) { - pk, sk := cipher.GenerateKeyPair() - return noise.DHKey{ - Private: sk[:], - Public: pk[:], - }, nil -} - -// DH helps to implement `noise.DHFunc`. -func (Secp256k1) DH(sk, pk []byte) []byte { - return append( - cipher.MustECDH(cipher.MustNewPubKey(pk), cipher.MustNewSecKey(sk)), - byte(0)) -} - -// DHLen helps to implement `noise.DHFunc`. -func (Secp256k1) DHLen() int { - return 33 -} - -// DHName helps to implement `noise.DHFunc`. -func (Secp256k1) DHName() string { - return "Secp256k1" -} diff --git a/internal/noise/net.go b/internal/noise/net.go deleted file mode 100644 index 45f288e1e..000000000 --- a/internal/noise/net.go +++ /dev/null @@ -1,239 +0,0 @@ -package noise - -import ( - "errors" - "io" - "math" - "net" - "net/rpc" - "sync" - "time" - - "github.com/flynn/noise" - "github.com/skycoin/dmsg/cipher" -) - -var ( - // ErrAlreadyServing is returned when an operation fails due to an operation - // that is currently running. - ErrAlreadyServing = errors.New("already serving") - - // ErrPacketTooBig occurs when data is too large. - ErrPacketTooBig = errors.New("data too large to contain within a packet") - - // HandshakeXK is the XK handshake pattern. - HandshakeXK = noise.HandshakeXK - - // HandshakeKK is the KK handshake pattern. - HandshakeKK = noise.HandshakeKK - - // AcceptHandshakeTimeout determines how long a noise hs should take. - AcceptHandshakeTimeout = time.Second * 10 -) - -// RPCClientDialer attempts to redial to a remotely served RPCClient. -// It exposes an RPCServer to the remote server. -// The connection is encrypted via noise. -type RPCClientDialer struct { - config Config - pattern noise.HandshakePattern - addr string - conn net.Conn - mu sync.Mutex - done chan struct{} // nil: loop is not running, non-nil: loop is running. -} - -// NewRPCClientDialer creates a new RPCClientDialer. -func NewRPCClientDialer(addr string, pattern noise.HandshakePattern, config Config) *RPCClientDialer { - return &RPCClientDialer{config: config, pattern: pattern, addr: addr} -} - -// Run repeatedly dials to remote until a successful connection is established. -// It exposes a RPC Server. -// It will return if Close is called or crypto fails. -func (d *RPCClientDialer) Run(srv *rpc.Server, retry time.Duration) error { - if ok := d.setDone(); !ok { - return ErrAlreadyServing - } - for { - if err := d.establishConn(); err != nil { - // Only return if not network error. - if _, ok := err.(net.Error); !ok { - return err - } - } else { - // Only serve when then dial succeeds. - srv.ServeConn(d.conn) - d.setConn(nil) - } - select { - case <-d.done: - d.clearDone() - return nil - case <-time.After(retry): - } - } -} - -// Close closes the handler. -func (d *RPCClientDialer) Close() (err error) { - d.mu.Lock() - if d.done != nil { - close(d.done) - } - if d.conn != nil { - err = d.conn.Close() - } - d.mu.Unlock() - return -} - -// This operation should be atomic, hence protected by mutex. -func (d *RPCClientDialer) establishConn() error { - d.mu.Lock() - defer d.mu.Unlock() - - conn, err := net.Dial("tcp", d.addr) - if err != nil { - return err - } - ns, err := New(d.pattern, d.config) - if err != nil { - return err - } - conn, err = WrapConn(conn, ns, time.Second*5) - if err != nil { - return err - } - d.conn = conn - return nil -} - -func (d *RPCClientDialer) setConn(conn net.Conn) { - d.mu.Lock() - d.conn = conn - d.mu.Unlock() -} - -func (d *RPCClientDialer) setDone() (ok bool) { - d.mu.Lock() - if ok = d.done == nil; ok { - d.done = make(chan struct{}) - } - d.mu.Unlock() - return -} - -func (d *RPCClientDialer) clearDone() { - d.mu.Lock() - d.done = nil - d.mu.Unlock() -} - -// Addr is the address of a either an AppNode or ManagerNode. -type Addr struct { - PK cipher.PubKey - Addr net.Addr -} - -// Network returns the network type. -func (a Addr) Network() string { - return "noise" -} - -// String implements fmt.Stringer -func (a Addr) String() string { - return a.Addr.String() + "(" + a.PK.Hex() + ")" -} - -// Conn wraps a net.Conn and encrypts the connection with noise. -type Conn struct { - net.Conn - ns *ReadWriter -} - -// WrapConn wraps a provided net.Conn with noise. -func WrapConn(conn net.Conn, ns *Noise, hsTimeout time.Duration) (*Conn, error) { - rw := NewReadWriter(conn, ns) - if err := rw.Handshake(hsTimeout); err != nil { - return nil, err - } - return &Conn{Conn: conn, ns: rw}, nil -} - -// Read reads from the noise-encrypted connection. -func (c *Conn) Read(b []byte) (int, error) { - return c.ns.Read(b) -} - -// Write writes to the noise-encrypted connection. -func (c *Conn) Write(b []byte) (int, error) { - if len(b) > math.MaxUint16 { - return 0, io.ErrShortWrite - } - return c.ns.Write(b) -} - -// LocalAddr returns the local address of the connection. -func (c *Conn) LocalAddr() net.Addr { - return &Addr{ - PK: c.ns.LocalStatic(), - Addr: c.Conn.LocalAddr(), - } -} - -// RemoteAddr returns the remote address of the connection. -func (c *Conn) RemoteAddr() net.Addr { - return &Addr{ - PK: c.ns.RemoteStatic(), - Addr: c.Conn.RemoteAddr(), - } -} - -// Listener accepts incoming connections and encrypts with noise. -type Listener struct { - net.Listener - pk cipher.PubKey - sk cipher.SecKey - init bool - pattern noise.HandshakePattern -} - -// WrapListener wraps a listener and encrypts incoming connections with noise. -func WrapListener(lis net.Listener, pk cipher.PubKey, sk cipher.SecKey, init bool, pattern noise.HandshakePattern) *Listener { - return &Listener{Listener: lis, pk: pk, sk: sk, init: init, pattern: pattern} -} - -// Accept calls Accept from the underlying net.Listener and encrypts the -// obtained net.Conn with noise. -func (ml *Listener) Accept() (net.Conn, error) { - for { - conn, err := ml.Listener.Accept() - if err != nil { - return nil, err - } - ns, err := New(ml.pattern, Config{ - LocalPK: ml.pk, - LocalSK: ml.sk, - Initiator: ml.init, - }) - if err != nil { - return nil, err - } - rw := NewReadWriter(conn, ns) - if err := rw.Handshake(AcceptHandshakeTimeout); err != nil { - noiseLogger.WithError(err).Warn("accept: noise handshake failed.") - continue - } - noiseLogger.Infoln("accepted:", rw.RemoteStatic()) - return &Conn{Conn: conn, ns: rw}, nil - } -} - -// Addr returns the local address of the noise-encrypted Listener. -func (ml *Listener) Addr() net.Addr { - return &Addr{ - PK: ml.pk, - Addr: ml.Listener.Addr(), - } -} diff --git a/internal/noise/net_test.go b/internal/noise/net_test.go deleted file mode 100644 index ae9130ead..000000000 --- a/internal/noise/net_test.go +++ /dev/null @@ -1,341 +0,0 @@ -package noise - -import ( - "fmt" - "io" - "log" - "net" - "net/rpc" - "sync" - "testing" - "time" - - "github.com/flynn/noise" - "github.com/skycoin/dmsg/cipher" - "github.com/stretchr/testify/require" -) - -type TestRPC struct{} - -type AddIn struct{ A, B int } - -func (r *TestRPC) Add(in *AddIn, out *int) error { - *out = in.A + in.B - return nil -} - -func TestRPCClientDialer(t *testing.T) { - var ( - pattern = HandshakeXK - ) - - svr := rpc.NewServer() - require.NoError(t, svr.Register(new(TestRPC))) - - lPK, lSK := cipher.GenerateKeyPair() - var l net.Listener - var lAddr string - - setup := func() { - if len(lAddr) == 0 { - lAddr = ":0" - } - var err error - - l, err = net.Listen("tcp", lAddr) - require.NoError(t, err) - - l = WrapListener(l, lPK, lSK, false, pattern) - lAddr = l.Addr().(*Addr).Addr.String() - t.Logf("Listening on %s", lAddr) - } - - teardown := func() { - if l != nil { - require.NoError(t, l.Close()) - l = nil - } - } - - t.Run("RunRetry", func(t *testing.T) { - setup() - defer teardown() // Just in case of failure. - - const reconCount = 5 - const retry = time.Second / 4 - - dPK, dSK := cipher.GenerateKeyPair() - d := NewRPCClientDialer(lAddr, pattern, Config{ - LocalPK: dPK, - LocalSK: dSK, - RemotePK: lPK, - Initiator: true, - }) - dDone := make(chan error, 1) - - go func() { - dDone <- d.Run(svr, retry) - close(dDone) - }() - - for i := 0; i < reconCount; i++ { - teardown() - time.Sleep(retry * 2) // Dialer shouldn't quit retrying in this time. - setup() - - conn, err := l.Accept() - require.NoError(t, err) - - in, out := &AddIn{A: i, B: i}, new(int) - require.NoError(t, rpc.NewClient(conn).Call("TestRPC.Add", in, out)) - require.Equal(t, in.A+in.B, *out) - require.NoError(t, conn.Close()) - } - - _ = d.Close() - require.NoError(t, <-dDone) - }) -} - -func TestConn(t *testing.T) { - type Result struct { - N int - Err error - } - - const timeout = time.Second - - aPK, aSK := cipher.GenerateKeyPair() - bPK, bSK := cipher.GenerateKeyPair() - - aNs, err := XKAndSecp256k1(Config{LocalPK: aPK, LocalSK: aSK, RemotePK: bPK, Initiator: true}) - require.NoError(t, err) - bNs, err := XKAndSecp256k1(Config{LocalPK: bPK, LocalSK: bSK, Initiator: false}) - require.NoError(t, err) - - aConn, bConn := net.Pipe() - defer func() { _, _ = aConn.Close(), bConn.Close() }() - - aRW := NewReadWriter(aConn, aNs) - bRW := NewReadWriter(bConn, bNs) - - errChan := make(chan error, 2) - go func() { errChan <- aRW.Handshake(timeout) }() - go func() { errChan <- bRW.Handshake(timeout) }() - require.NoError(t, <-errChan) - require.NoError(t, <-errChan) - close(errChan) - - a := &Conn{Conn: aConn, ns: aRW} - b := &Conn{Conn: bConn, ns: bRW} - - t.Run("ReadWrite", func(t *testing.T) { - aResults := make(chan Result) - bResults := make(chan Result) - - for i := 0; i < 10; i++ { - msgAtoB := []byte(fmt.Sprintf("this is message %d from A for B", i)) - - go func() { - n, err := a.Write(msgAtoB) - aResults <- Result{N: n, Err: err} - }() - - receivedMsgAtoB := make([]byte, len(msgAtoB)) - n, err := io.ReadFull(b, receivedMsgAtoB) - require.Equal(t, len(msgAtoB), n) - require.NoError(t, err) - - aResult := <-aResults - require.Equal(t, len(msgAtoB), aResult.N) - require.NoError(t, aResult.Err) - - msgBtoA := []byte(fmt.Sprintf("this is message %d from B for A", i)) - - go func() { - n, err := b.Write(msgAtoB) - bResults <- Result{N: n, Err: err} - }() - - receivedMsgBtoA := make([]byte, len(msgBtoA)) - n, err = io.ReadFull(a, receivedMsgBtoA) - require.Equal(t, len(msgBtoA), n) - require.NoError(t, err) - - bResult := <-bResults - require.Equal(t, len(msgBtoA), bResult.N) - require.NoError(t, bResult.Err) - } - }) - - t.Run("ReadWriteConcurrent", func(t *testing.T) { - type ReadResult struct { - Msg string - N int - Err error - } - const ( - MsgCount = 100 - MsgLen = 4 - ) - var ( - aMap = make(map[string]struct{}) - bMap = make(map[string]struct{}) - aWrites = make(chan Result, MsgCount) - bWrites = make(chan Result, MsgCount) - aReads = make(chan ReadResult, MsgCount) - bReads = make(chan ReadResult, MsgCount) - ) - randSleep := func() { time.Sleep(time.Duration(cipher.RandByte(1)[0]) / 255 * time.Second) } - - for i := 0; i < MsgCount; i++ { - msg := fmt.Sprintf("%4d", i) - go func() { - randSleep() - n, err := a.Write([]byte(msg)) - aWrites <- Result{N: n, Err: err} - }() - go func() { - randSleep() - n, err := b.Write([]byte(msg)) - bWrites <- Result{N: n, Err: err} - }() - go func() { - randSleep() - msg := make([]byte, MsgLen) - n, err := io.ReadFull(a, msg) - aReads <- ReadResult{Msg: string(msg), N: n, Err: err} - }() - go func() { - randSleep() - msg := make([]byte, MsgLen) - n, err := io.ReadFull(b, msg) - bReads <- ReadResult{Msg: string(msg), N: n, Err: err} - }() - } - - for i := 0; i < MsgCount; i++ { - aWrite := <-aWrites - require.NoError(t, aWrite.Err) - require.Equal(t, MsgLen, aWrite.N) - - bWrite := <-bWrites - require.NoError(t, bWrite.Err) - require.Equal(t, MsgLen, bWrite.N) - - aRead := <-aReads - require.NoError(t, aRead.Err) - require.Equal(t, MsgLen, aRead.N) - _, aHas := aMap[aRead.Msg] - require.False(t, aHas) - aMap[aRead.Msg] = struct{}{} - - bRead := <-bReads - require.NoError(t, bRead.Err) - require.Equal(t, MsgLen, bRead.N) - _, bHas := bMap[bRead.Msg] - require.False(t, bHas) - bMap[bRead.Msg] = struct{}{} - } - - require.Len(t, aMap, MsgCount) - require.Len(t, bMap, MsgCount) - }) - - t.Run("ReadWriteIrregular", func(t *testing.T) { - const segLen = 100 - const segCount = 1000 - - aResults := make([]Result, segCount) - - msg := cipher.RandByte(segLen * segCount) - - wg := new(sync.WaitGroup) - wg.Add(1) - go func() { - for i := 0; i < segCount; i++ { - n, err := a.Write(msg[i*segLen : (i+1)*segLen]) - aResults[i] = Result{N: n, Err: err} - } - wg.Done() - }() - - msgResult := make([]byte, len(msg)) - _, err := io.ReadFull(b, msgResult) - require.NoError(t, err) - require.Equal(t, msg, msgResult) - - wg.Wait() - - for i, r := range aResults { - require.NoError(t, r.Err, i) - require.Equal(t, segLen, r.N, i) - } - }) -} - -func TestListener(t *testing.T) { - const ( - connCount = 10 - msg = "Hello, world!" - timeout = time.Second - ) - var ( - pattern = noise.HandshakeXK - ) - - dialAndWrite := func(remote cipher.PubKey, addr string) error { - pk, sk := cipher.GenerateKeyPair() - conn, err := net.Dial("tcp", addr) - if err != nil { - return err - } - ns, err := New(pattern, Config{LocalPK: pk, LocalSK: sk, RemotePK: remote, Initiator: true}) - if err != nil { - return err - } - conn, err = WrapConn(conn, ns, timeout) - if err != nil { - return err - } - _, err = conn.Write([]byte(msg)) - if err != nil { - return err - } - return conn.Close() - } - - lPK, lSK := cipher.GenerateKeyPair() - l, err := net.Listen("tcp", "") - require.NoError(t, err) - defer l.Close() - - l = WrapListener(l, lPK, lSK, false, pattern) - addr := l.Addr().(*Addr) - - t.Run("Accept", func(t *testing.T) { - hResults := make([]error, connCount) - wg := new(sync.WaitGroup) - wg.Add(1) - go func() { - for i := 0; i < connCount; i++ { - hResults[i] = dialAndWrite(lPK, addr.Addr.String()) - } - wg.Done() - }() - for i := 0; i < connCount; i++ { - lConn, err := l.Accept() - require.NoError(t, err) - rec := make([]byte, len(msg)) - n, err := io.ReadFull(lConn, rec) - log.Printf("Accept('%s'): received: '%s'", lConn.RemoteAddr(), string(rec)) - require.Equal(t, len(msg), n) - require.NoError(t, err) - require.NoError(t, lConn.Close()) - } - wg.Wait() - for i := 0; i < connCount; i++ { - require.NoError(t, hResults[i]) - } - }) -} diff --git a/internal/noise/noise.go b/internal/noise/noise.go deleted file mode 100644 index 6ea3ec446..000000000 --- a/internal/noise/noise.go +++ /dev/null @@ -1,152 +0,0 @@ -package noise - -import ( - "crypto/rand" - "encoding/binary" - - "github.com/flynn/noise" - "github.com/skycoin/dmsg/cipher" - "github.com/skycoin/skycoin/src/util/logging" -) - -var noiseLogger = logging.MustGetLogger("noise") // TODO: initialize properly or remove - -// Config hold noise parameters. -type Config struct { - LocalPK cipher.PubKey // Local instance static public key. - LocalSK cipher.SecKey // Local instance static secret key. - RemotePK cipher.PubKey // Remote instance static public key. - Initiator bool // Whether the local instance initiates the connection. -} - -// Noise handles the handshake and the frame's cryptography. -// All operations on Noise are not guaranteed to be thread-safe. -type Noise struct { - pk cipher.PubKey - sk cipher.SecKey - init bool - - pattern noise.HandshakePattern - hs *noise.HandshakeState - enc *noise.CipherState - dec *noise.CipherState - - seq uint32 // sequence number, used as nonce for both encrypting and decrypting - previousSeq uint32 // sequence number last decrypted, check in order to avoid reply attacks - highestPrevious uint32 // highest sequence number received from the other end - //encN uint32 // counter to inform encrypting CipherState to re-key - //decN uint32 // counter to inform decrypting CipherState to re-key -} - -// New creates a new Noise with: -// - provided pattern for handshake. -// - Secp256k1 for the curve. -func New(pattern noise.HandshakePattern, config Config) (*Noise, error) { - nc := noise.Config{ - CipherSuite: noise.NewCipherSuite(Secp256k1{}, noise.CipherChaChaPoly, noise.HashSHA256), - Random: rand.Reader, - Pattern: pattern, - Initiator: config.Initiator, - StaticKeypair: noise.DHKey{ - Public: config.LocalPK[:], - Private: config.LocalSK[:], - }, - } - if !config.RemotePK.Null() { - nc.PeerStatic = config.RemotePK[:] - } - - hs, err := noise.NewHandshakeState(nc) - if err != nil { - return nil, err - } - return &Noise{ - pk: config.LocalPK, - sk: config.LocalSK, - init: config.Initiator, - pattern: pattern, - hs: hs, - }, nil -} - -// KKAndSecp256k1 creates a new Noise with: -// - KK pattern for handshake. -// - Secp256k1 for the curve. -func KKAndSecp256k1(config Config) (*Noise, error) { - return New(noise.HandshakeKK, config) -} - -// XKAndSecp256k1 creates a new Noise with: -// - XK pattern for handshake. -// - Secp256 for the curve. -func XKAndSecp256k1(config Config) (*Noise, error) { - return New(noise.HandshakeXK, config) -} - -// HandshakeMessage generates handshake message for a current handshake state. -func (ns *Noise) HandshakeMessage() (res []byte, err error) { - if ns.hs.MessageIndex() < len(ns.pattern.Messages)-1 { - res, _, _, err = ns.hs.WriteMessage(nil, nil) - return - } - - res, ns.dec, ns.enc, err = ns.hs.WriteMessage(nil, nil) - return res, err -} - -// ProcessMessage processes a received handshake message and appends the payload. -func (ns *Noise) ProcessMessage(msg []byte) (err error) { - if ns.hs.MessageIndex() < len(ns.pattern.Messages)-1 { - _, _, _, err = ns.hs.ReadMessage(nil, msg) - return - } - - _, ns.enc, ns.dec, err = ns.hs.ReadMessage(nil, msg) - return err -} - -// LocalStatic returns the local static public key. -func (ns *Noise) LocalStatic() cipher.PubKey { - return ns.pk -} - -// RemoteStatic returns the remote static public key. -func (ns *Noise) RemoteStatic() cipher.PubKey { - pk, err := cipher.NewPubKey(ns.hs.PeerStatic()) - if err != nil { - panic(err) - } - return cipher.PubKey(pk) -} - -// EncryptUnsafe encrypts plaintext without interlocking, should only -// be used with external lock. -func (ns *Noise) EncryptUnsafe(plaintext []byte) []byte { - ns.seq++ - seq := make([]byte, 4) - binary.BigEndian.PutUint32(seq, ns.seq) - - return append(seq, ns.enc.Cipher().Encrypt(nil, uint64(ns.seq), nil, plaintext)...) -} - -// DecryptUnsafe decrypts ciphertext without interlocking, should only -// be used with external lock. -func (ns *Noise) DecryptUnsafe(ciphertext []byte) ([]byte, error) { - seq := binary.BigEndian.Uint32(ciphertext[:4]) - if seq <= ns.previousSeq { - noiseLogger.Warnf("current seq: %s is not higher than previous one: %s. "+ - "Highest sequence number received so far is: %s", ns.seq, ns.previousSeq, ns.highestPrevious) - } else { - if ns.previousSeq > ns.highestPrevious { - ns.highestPrevious = seq - } - ns.previousSeq = seq - } - - return ns.dec.Cipher().Decrypt(nil, uint64(seq), nil, ciphertext[4:]) -} - -// HandshakeFinished indicate whether handshake was completed. -func (ns *Noise) HandshakeFinished() bool { - return ns.hs.MessageIndex() == len(ns.pattern.Messages) -} diff --git a/internal/noise/noise_test.go b/internal/noise/noise_test.go deleted file mode 100644 index 9aefde1b3..000000000 --- a/internal/noise/noise_test.go +++ /dev/null @@ -1,139 +0,0 @@ -package noise - -import ( - "log" - "os" - "testing" - - "github.com/skycoin/dmsg/cipher" - "github.com/skycoin/skycoin/src/util/logging" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestMain(m *testing.M) { - loggingLevel, ok := os.LookupEnv("TEST_LOGGING_LEVEL") - if ok { - lvl, err := logging.LevelFromString(loggingLevel) - if err != nil { - log.Fatal(err) - } - logging.SetLevel(lvl) - } else { - logging.Disable() - } - - os.Exit(m.Run()) -} - -func TestKKAndSecp256k1(t *testing.T) { - pkI, skI := cipher.GenerateKeyPair() - pkR, skR := cipher.GenerateKeyPair() - - confI := Config{ - LocalPK: pkI, - LocalSK: skI, - RemotePK: pkR, - Initiator: true, - } - - confR := Config{ - LocalPK: pkR, - LocalSK: skR, - RemotePK: pkI, - Initiator: false, - } - - nI, err := KKAndSecp256k1(confI) - require.NoError(t, err) - - nR, err := KKAndSecp256k1(confR) - require.NoError(t, err) - - // -> e, es - msg, err := nI.HandshakeMessage() - require.NoError(t, err) - require.Error(t, nR.ProcessMessage(append(msg, 1))) - require.NoError(t, nR.ProcessMessage(msg)) - - // <- e, ee - msg, err = nR.HandshakeMessage() - require.NoError(t, err) - require.Error(t, nI.ProcessMessage(append(msg, 1))) - require.NoError(t, nI.ProcessMessage(msg)) - - require.True(t, nI.HandshakeFinished()) - require.True(t, nR.HandshakeFinished()) - - encrypted := nI.EncryptUnsafe([]byte("foo")) - decrypted, err := nR.DecryptUnsafe(encrypted) - require.NoError(t, err) - assert.Equal(t, []byte("foo"), decrypted) - - encrypted = nR.EncryptUnsafe([]byte("bar")) - decrypted, err = nI.DecryptUnsafe(encrypted) - require.NoError(t, err) - assert.Equal(t, []byte("bar"), decrypted) - - encrypted = nI.EncryptUnsafe([]byte("baz")) - decrypted, err = nR.DecryptUnsafe(encrypted) - require.NoError(t, err) - assert.Equal(t, []byte("baz"), decrypted) -} - -func TestXKAndSecp256k1(t *testing.T) { - pkI, skI := cipher.GenerateKeyPair() - pkR, skR := cipher.GenerateKeyPair() - - confI := Config{ - LocalPK: pkI, - LocalSK: skI, - RemotePK: pkR, - Initiator: true, - } - - confR := Config{ - LocalPK: pkR, - LocalSK: skR, - Initiator: false, - } - - nI, err := XKAndSecp256k1(confI) - require.NoError(t, err) - - nR, err := XKAndSecp256k1(confR) - require.NoError(t, err) - - // -> e, es - msg, err := nI.HandshakeMessage() - require.NoError(t, err) - require.NoError(t, nR.ProcessMessage(msg)) - - // <- e, ee - msg, err = nR.HandshakeMessage() - require.NoError(t, err) - require.NoError(t, nI.ProcessMessage(msg)) - - // -> s, se - msg, err = nI.HandshakeMessage() - require.NoError(t, err) - require.NoError(t, nR.ProcessMessage(msg)) - - require.True(t, nI.HandshakeFinished()) - require.True(t, nR.HandshakeFinished()) - - encrypted := nI.EncryptUnsafe([]byte("foo")) - decrypted, err := nR.DecryptUnsafe(encrypted) - require.NoError(t, err) - assert.Equal(t, []byte("foo"), decrypted) - - encrypted = nR.EncryptUnsafe([]byte("bar")) - decrypted, err = nI.DecryptUnsafe(encrypted) - require.NoError(t, err) - assert.Equal(t, []byte("bar"), decrypted) - - encrypted = nI.EncryptUnsafe([]byte("baz")) - decrypted, err = nR.DecryptUnsafe(encrypted) - require.NoError(t, err) - assert.Equal(t, []byte("baz"), decrypted) -} diff --git a/internal/noise/read_writer.go b/internal/noise/read_writer.go deleted file mode 100644 index e5e635581..000000000 --- a/internal/noise/read_writer.go +++ /dev/null @@ -1,172 +0,0 @@ -package noise - -import ( - "bytes" - "encoding/binary" - "errors" - "io" - "sync" - "time" - - "github.com/skycoin/dmsg/cipher" - - "github.com/skycoin/skywire/internal/ioutil" -) - -// ReadWriter implements noise encrypted read writer. -type ReadWriter struct { - origin io.ReadWriter - ns *Noise - rBuf bytes.Buffer - rMx sync.Mutex - wMx sync.Mutex -} - -// NewReadWriter constructs a new ReadWriter. -func NewReadWriter(rw io.ReadWriter, ns *Noise) *ReadWriter { - return &ReadWriter{ - origin: rw, - ns: ns, - } -} - -func (rw *ReadWriter) Read(p []byte) (int, error) { - rw.rMx.Lock() - defer rw.rMx.Unlock() - - if rw.rBuf.Len() > 0 { - return rw.rBuf.Read(p) - } - - ciphertext, err := rw.readPacket() - if err != nil { - return 0, err - } - plaintext, err := rw.ns.DecryptUnsafe(ciphertext) - if err != nil { - return 0, err - } - return ioutil.BufRead(&rw.rBuf, plaintext, p) -} - -func (rw *ReadWriter) readPacket() ([]byte, error) { - h := make([]byte, 2) - if _, err := io.ReadFull(rw.origin, h); err != nil { - return nil, err - } - data := make([]byte, binary.BigEndian.Uint16(h)) - _, err := io.ReadFull(rw.origin, data) - return data, err -} - -func (rw *ReadWriter) Write(p []byte) (int, error) { - rw.wMx.Lock() - defer rw.wMx.Unlock() - - ciphertext := rw.ns.EncryptUnsafe(p) - - if err := rw.writePacket(ciphertext); err != nil { - return 0, err - } - return len(p), nil -} - -func (rw *ReadWriter) writePacket(p []byte) error { - buf := make([]byte, 2) - binary.BigEndian.PutUint16(buf, uint16(len(p))) - _, err := rw.origin.Write(append(buf, p...)) - return err -} - -// Handshake performs a Noise handshake using the provided io.ReadWriter. -func (rw *ReadWriter) Handshake(hsTimeout time.Duration) error { - doneChan := make(chan error) - go func() { - if rw.ns.init { - doneChan <- rw.initiatorHandshake() - } else { - doneChan <- rw.responderHandshake() - } - }() - - select { - case err := <-doneChan: - return err - case <-time.After(hsTimeout): - return errors.New("timeout") - } -} - -// LocalStatic returns the local static public key. -func (rw *ReadWriter) LocalStatic() cipher.PubKey { - return rw.ns.LocalStatic() -} - -// RemoteStatic returns the remote static public key. -func (rw *ReadWriter) RemoteStatic() cipher.PubKey { - return rw.ns.RemoteStatic() -} - -func (rw *ReadWriter) initiatorHandshake() error { - for { - msg, err := rw.ns.HandshakeMessage() - if err != nil { - return err - } - - if err := rw.writePacket(msg); err != nil { - return err - } - - if rw.ns.HandshakeFinished() { - break - } - - res, err := rw.readPacket() - if err != nil { - return err - } - - if err = rw.ns.ProcessMessage(res); err != nil { - return err - } - - if rw.ns.HandshakeFinished() { - break - } - } - - return nil -} - -func (rw *ReadWriter) responderHandshake() error { - for { - msg, err := rw.readPacket() - if err != nil { - return err - } - - if err := rw.ns.ProcessMessage(msg); err != nil { - return err - } - - if rw.ns.HandshakeFinished() { - break - } - - res, err := rw.ns.HandshakeMessage() - if err != nil { - return err - } - - if err := rw.writePacket(res); err != nil { - return err - } - - if rw.ns.HandshakeFinished() { - break - } - } - - return nil -} diff --git a/internal/noise/read_writer_test.go b/internal/noise/read_writer_test.go deleted file mode 100644 index 637e6753b..000000000 --- a/internal/noise/read_writer_test.go +++ /dev/null @@ -1,215 +0,0 @@ -package noise - -import ( - "fmt" - "net" - "testing" - "time" - - "github.com/skycoin/dmsg/cipher" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNewReadWriter(t *testing.T) { - - type Result struct { - n int - err error - b []byte - } - - t.Run("concurrent", func(t *testing.T) { - aPK, aSK := cipher.GenerateKeyPair() - bPK, bSK := cipher.GenerateKeyPair() - - aNs, err := KKAndSecp256k1(Config{ - LocalPK: aPK, - LocalSK: aSK, - RemotePK: bPK, - Initiator: true, - }) - require.NoError(t, err) - - bNs, err := KKAndSecp256k1(Config{ - LocalPK: bPK, - LocalSK: bSK, - RemotePK: aPK, - Initiator: false, - }) - require.NoError(t, err) - - aConn, bConn := net.Pipe() - defer func() { - _ = aConn.Close() //nolint:errcheck - _ = bConn.Close() //nolint:errcheck - }() - - aRW := NewReadWriter(aConn, aNs) - bRW := NewReadWriter(bConn, bNs) - - hsCh := make(chan error, 2) - defer close(hsCh) - go func() { hsCh <- aRW.Handshake(time.Second) }() - go func() { hsCh <- bRW.Handshake(time.Second) }() - require.NoError(t, <-hsCh) - require.NoError(t, <-hsCh) - - const groupSize = 10 - const totalGroups = 5 - const msgCount = totalGroups * groupSize - - writes := make([][]byte, msgCount) - - wCh := make(chan Result, msgCount) - defer close(wCh) - rCh := make(chan Result, msgCount) - defer close(rCh) - - for i := 0; i < msgCount; i++ { - writes[i] = []byte(fmt.Sprintf("this is message: %d", i)) - } - - for i := 0; i < totalGroups; i++ { - go func(i int) { - for j := 0; j < groupSize; j++ { - go func(i, j int) { - b := writes[i*j] - n, err := aRW.Write(b) - wCh <- Result{n: n, err: err, b: b} - }(i, j) - go func() { - buf := make([]byte, 100) - n, err := bRW.Read(buf) - rCh <- Result{n: n, err: err, b: buf[:n]} - }() - } - }(i) - } - - for i := 0; i < msgCount; i++ { - w := <-wCh - fmt.Printf("write_result[%d]: b(%s) err(%v)\n", i, string(w.b), w.err) - assert.NoError(t, w.err) - assert.True(t, w.n > 0) - - r := <-rCh - fmt.Printf(" read_result[%d]: b(%s) err(%v)\n", i, string(r.b), r.err) - assert.NoError(t, r.err) - assert.True(t, r.n > 0) - } - }) -} - -func TestReadWriterKKPattern(t *testing.T) { - pkI, skI := cipher.GenerateKeyPair() - pkR, skR := cipher.GenerateKeyPair() - - confI := Config{ - LocalPK: pkI, - LocalSK: skI, - RemotePK: pkR, - Initiator: true, - } - - confR := Config{ - LocalPK: pkR, - LocalSK: skR, - RemotePK: pkI, - Initiator: false, - } - - nI, err := KKAndSecp256k1(confI) - require.NoError(t, err) - - nR, err := KKAndSecp256k1(confR) - require.NoError(t, err) - - connI, connR := net.Pipe() - rwI := NewReadWriter(connI, nI) - rwR := NewReadWriter(connR, nR) - - errCh := make(chan error) - go func() { errCh <- rwR.Handshake(time.Second) }() - require.NoError(t, rwI.Handshake(time.Second)) - require.NoError(t, <-errCh) - - go func() { - _, err := rwI.Write([]byte("foo")) - errCh <- err - }() - - buf := make([]byte, 3) - n, err := rwR.Read(buf) - require.NoError(t, err) - require.NoError(t, <-errCh) - assert.Equal(t, 3, n) - assert.Equal(t, []byte("foo"), buf) - - go func() { - _, err := rwI.Read(buf) - errCh <- err - }() - - n, err = rwR.Write([]byte("bar")) - require.NoError(t, err) - require.NoError(t, <-errCh) - assert.Equal(t, 3, n) - assert.Equal(t, []byte("bar"), buf) -} - -func TestReadWriterXKPattern(t *testing.T) { - pkI, skI := cipher.GenerateKeyPair() - pkR, skR := cipher.GenerateKeyPair() - - confI := Config{ - LocalPK: pkI, - LocalSK: skI, - RemotePK: pkR, - Initiator: true, - } - - confR := Config{ - LocalPK: pkR, - LocalSK: skR, - Initiator: false, - } - - nI, err := XKAndSecp256k1(confI) - require.NoError(t, err) - - nR, err := XKAndSecp256k1(confR) - require.NoError(t, err) - - connI, connR := net.Pipe() - rwI := NewReadWriter(connI, nI) - rwR := NewReadWriter(connR, nR) - - errCh := make(chan error) - go func() { errCh <- rwR.Handshake(time.Second) }() - require.NoError(t, rwI.Handshake(time.Second)) - require.NoError(t, <-errCh) - - go func() { - _, err := rwI.Write([]byte("foo")) - errCh <- err - }() - - buf := make([]byte, 3) - n, err := rwR.Read(buf) - require.NoError(t, err) - require.NoError(t, <-errCh) - assert.Equal(t, 3, n) - assert.Equal(t, []byte("foo"), buf) - - go func() { - _, err := rwI.Read(buf) - errCh <- err - }() - - n, err = rwR.Write([]byte("bar")) - require.NoError(t, err) - require.NoError(t, <-errCh) - assert.Equal(t, 3, n) - assert.Equal(t, []byte("bar"), buf) -} diff --git a/pkg/cipher/cipher.go b/pkg/cipher/cipher.go deleted file mode 100644 index 9d8a89700..000000000 --- a/pkg/cipher/cipher.go +++ /dev/null @@ -1,255 +0,0 @@ -// Package cipher implements common golang encoding interfaces for -// github.com/skycoin/skycoin/src/cipher -package cipher - -import ( - "fmt" - "strings" - - "github.com/skycoin/skycoin/src/cipher" -) - -func init() { - cipher.DebugLevel2 = false // DebugLevel2 causes ECDH to be really slow -} - -// GenerateKeyPair creates key pair -func GenerateKeyPair() (PubKey, SecKey) { - pk, sk := cipher.GenerateKeyPair() - return PubKey(pk), SecKey(sk) -} - -// GenerateDeterministicKeyPair generates deterministic key pair -func GenerateDeterministicKeyPair(seed []byte) (PubKey, SecKey, error) { - pk, sk, err := cipher.GenerateDeterministicKeyPair(seed) - return PubKey(pk), SecKey(sk), err -} - -// NewPubKey converts []byte to a PubKey -func NewPubKey(b []byte) (PubKey, error) { - pk, err := cipher.NewPubKey(b) - return PubKey(pk), err -} - -// PubKey is a wrapper type for cipher.PubKey that implements common -// golang interfaces. -type PubKey cipher.PubKey - -// Hex returns a hex encoded PubKey string -func (pk PubKey) Hex() string { - return cipher.PubKey(pk).Hex() -} - -// Null returns true if PubKey is the null PubKey -func (pk PubKey) Null() bool { - return cipher.PubKey(pk).Null() -} - -// String implements fmt.Stringer for PubKey. Returns Hex representation. -func (pk PubKey) String() string { - return pk.Hex() -} - -// Set implements pflag.Value for PubKey. -func (pk *PubKey) Set(s string) error { - cPK, err := cipher.PubKeyFromHex(s) - if err != nil { - return err - } - *pk = PubKey(cPK) - return nil -} - -// Type implements pflag.Value for PubKey. -func (pk PubKey) Type() string { - return "cipher.PubKey" -} - -// MarshalText implements encoding.TextMarshaler. -func (pk PubKey) MarshalText() ([]byte, error) { - return []byte(pk.Hex()), nil -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (pk *PubKey) UnmarshalText(data []byte) error { - dPK, err := cipher.PubKeyFromHex(string(data)) - if err == nil { - *pk = PubKey(dPK) - } - return err -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (pk PubKey) MarshalBinary() ([]byte, error) { - return pk[:], nil -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (pk *PubKey) UnmarshalBinary(data []byte) error { - dPK, err := cipher.NewPubKey(data) - if err == nil { - *pk = PubKey(dPK) - } - return err -} - -// PubKeys represents a slice of PubKeys. -type PubKeys []PubKey - -// String implements stringer for PubKeys. -func (p PubKeys) String() string { - res := "public keys:\n" - for _, pk := range p { - res += fmt.Sprintf("\t%s\n", pk) - } - return res -} - -// Set implements pflag.Value for PubKeys. -func (p *PubKeys) Set(list string) error { - *p = PubKeys{} - for _, s := range strings.Split(list, ",") { - var pk PubKey - if err := pk.Set(strings.TrimSpace(s)); err != nil { - return err - } - *p = append(*p, pk) - } - return nil -} - -// Type implements pflag.Value for PubKeys. -func (p PubKeys) Type() string { - return "cipher.PubKeys" -} - -// SecKey is a wrapper type for cipher.SecKey that implements common -// golang interfaces. -type SecKey cipher.SecKey - -// Hex returns a hex encoded SecKey string -func (sk SecKey) Hex() string { - return cipher.SecKey(sk).Hex() -} - -// Null returns true if SecKey is the null SecKey. -func (sk SecKey) Null() bool { - return cipher.SecKey(sk).Null() -} - -// String implements fmt.Stringer for SecKey. Returns Hex representation. -func (sk SecKey) String() string { - return sk.Hex() -} - -// Set implements pflag.Value for SecKey. -func (sk *SecKey) Set(s string) error { - cSK, err := cipher.SecKeyFromHex(s) - if err != nil { - return err - } - *sk = SecKey(cSK) - return nil -} - -// Type implements pflag.Value for SecKey. -func (sk *SecKey) Type() string { - return "cipher.SecKey" -} - -// MarshalText implements encoding.TextMarshaler. -func (sk SecKey) MarshalText() ([]byte, error) { - return []byte(sk.Hex()), nil -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (sk *SecKey) UnmarshalText(data []byte) error { - dSK, err := cipher.SecKeyFromHex(string(data)) - if err == nil { - *sk = SecKey(dSK) - } - return err -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (sk SecKey) MarshalBinary() ([]byte, error) { - return sk[:], nil -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (sk *SecKey) UnmarshalBinary(data []byte) error { - dSK, err := cipher.NewSecKey(data) - if err == nil { - *sk = SecKey(dSK) - } - return err -} - -// PubKey recovers the public key for a secret key -func (sk SecKey) PubKey() (PubKey, error) { - pk, err := cipher.PubKeyFromSecKey(cipher.SecKey(sk)) - return PubKey(pk), err -} - -// Sig is a wrapper type for cipher.Sig that implements common golang interfaces. -type Sig cipher.Sig - -// Hex returns a hex encoded Sig string -func (sig Sig) Hex() string { - return cipher.Sig(sig).Hex() -} - -// String implements fmt.Stringer for Sig. Returns Hex representation. -func (sig Sig) String() string { - return sig.Hex() -} - -// Null returns true if Sig is a null Sig -func (sig Sig) Null() bool { - return sig == Sig{} -} - -// MarshalText implements encoding.TextMarshaler. -func (sig Sig) MarshalText() ([]byte, error) { - return []byte(sig.Hex()), nil -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (sig *Sig) UnmarshalText(data []byte) error { - dSig, err := cipher.SigFromHex(string(data)) - if err == nil { - *sig = Sig(dSig) - } - return err -} - -// SignPayload creates Sig for payload using SHA256 -func SignPayload(payload []byte, sec SecKey) (Sig, error) { - sig, err := cipher.SignHash(cipher.SumSHA256(payload), cipher.SecKey(sec)) - return Sig(sig), err -} - -// VerifyPubKeySignedPayload verifies that SHA256 hash of the payload was signed by PubKey -func VerifyPubKeySignedPayload(pubkey PubKey, sig Sig, payload []byte) error { - return cipher.VerifyPubKeySignedHash(cipher.PubKey(pubkey), cipher.Sig(sig), cipher.SumSHA256(payload)) -} - -// RandByte returns rand N bytes -func RandByte(n int) []byte { - return cipher.RandByte(n) -} - -// SHA256 is a wrapper type for cipher.SHA256 that implements common -// golang interfaces. -type SHA256 cipher.SHA256 - -// SHA256FromBytes converts []byte to SHA256 -func SHA256FromBytes(b []byte) (SHA256, error) { - h, err := cipher.SHA256FromBytes(b) - return SHA256(h), err -} - -// SumSHA256 sum sha256 -func SumSHA256(b []byte) SHA256 { - return SHA256(cipher.SumSHA256(b)) -} diff --git a/pkg/cipher/cipher_test.go b/pkg/cipher/cipher_test.go deleted file mode 100644 index a9a97ec74..000000000 --- a/pkg/cipher/cipher_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package cipher - -import ( - "log" - "os" - "testing" - - "github.com/skycoin/skycoin/src/util/logging" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestMain(m *testing.M) { - loggingLevel, ok := os.LookupEnv("TEST_LOGGING_LEVEL") - if ok { - lvl, err := logging.LevelFromString(loggingLevel) - if err != nil { - log.Fatal(err) - } - logging.SetLevel(lvl) - } else { - logging.Disable() - } - - os.Exit(m.Run()) -} - -func TestPubKeyString(t *testing.T) { - p, _ := GenerateKeyPair() - require.Equal(t, p.Hex(), p.String()) -} - -func TestPubKeyTextMarshaller(t *testing.T) { - p, _ := GenerateKeyPair() - h, err := p.MarshalText() - require.NoError(t, err) - - var p2 PubKey - err = p2.UnmarshalText(h) - require.NoError(t, err) - require.Equal(t, p, p2) -} - -func TestPubKeyBinaryMarshaller(t *testing.T) { - p, _ := GenerateKeyPair() - b, err := p.MarshalBinary() - require.NoError(t, err) - - var p2 PubKey - err = p2.UnmarshalBinary(b) - require.NoError(t, err) - require.Equal(t, p, p2) -} - -func TestSecKeyString(t *testing.T) { - _, s := GenerateKeyPair() - require.Equal(t, s.Hex(), s.String()) -} - -func TestSecKeyTextMarshaller(t *testing.T) { - _, s := GenerateKeyPair() - h, err := s.MarshalText() - require.NoError(t, err) - - var s2 SecKey - err = s2.UnmarshalText(h) - require.NoError(t, err) - require.Equal(t, s, s2) -} - -func TestSecKeyBinaryMarshaller(t *testing.T) { - _, s := GenerateKeyPair() - b, err := s.MarshalBinary() - require.NoError(t, err) - - var s2 SecKey - err = s2.UnmarshalBinary(b) - require.NoError(t, err) - require.Equal(t, s, s2) -} - -func TestSigString(t *testing.T) { - _, sk := GenerateKeyPair() - sig, err := SignPayload([]byte("foo"), sk) - require.NoError(t, err) - assert.Equal(t, sig.Hex(), sig.String()) -} - -func TestSigTextMarshaller(t *testing.T) { - _, sk := GenerateKeyPair() - sig, err := SignPayload([]byte("foo"), sk) - require.NoError(t, err) - h, err := sig.MarshalText() - require.NoError(t, err) - - var sig2 Sig - err = sig2.UnmarshalText(h) - require.NoError(t, err) - assert.Equal(t, sig, sig2) -} diff --git a/pkg/manager/node.go b/pkg/manager/node.go index b0de9967e..5e05a145a 100644 --- a/pkg/manager/node.go +++ b/pkg/manager/node.go @@ -19,7 +19,7 @@ import ( "github.com/skycoin/dmsg/cipher" "github.com/skycoin/skycoin/src/util/logging" - "github.com/skycoin/skywire/internal/noise" + "github.com/skycoin/dmsg/noise" "github.com/skycoin/skywire/pkg/httputil" "github.com/skycoin/skywire/pkg/node" "github.com/skycoin/skywire/pkg/routing" diff --git a/pkg/node/node.go b/pkg/node/node.go index 0c9bb1707..eb93c052c 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -21,7 +21,7 @@ import ( "github.com/skycoin/skycoin/src/util/logging" - "github.com/skycoin/skywire/internal/noise" + "github.com/skycoin/dmsg/noise" "github.com/skycoin/skywire/pkg/app" routeFinder "github.com/skycoin/skywire/pkg/route-finder/client" "github.com/skycoin/skywire/pkg/router" diff --git a/pkg/router/loop_list.go b/pkg/router/loop_list.go index 7641f93df..c78f73752 100644 --- a/pkg/router/loop_list.go +++ b/pkg/router/loop_list.go @@ -5,7 +5,7 @@ import ( "github.com/google/uuid" - "github.com/skycoin/skywire/internal/noise" + "github.com/skycoin/dmsg/noise" "github.com/skycoin/skywire/pkg/app" "github.com/skycoin/skywire/pkg/routing" ) diff --git a/pkg/router/router.go b/pkg/router/router.go index 9f5e58cda..16533cdc6 100644 --- a/pkg/router/router.go +++ b/pkg/router/router.go @@ -14,7 +14,7 @@ import ( "github.com/skycoin/dmsg/cipher" "github.com/skycoin/skycoin/src/util/logging" - "github.com/skycoin/skywire/internal/noise" + "github.com/skycoin/dmsg/noise" "github.com/skycoin/skywire/pkg/app" routeFinder "github.com/skycoin/skywire/pkg/route-finder/client" "github.com/skycoin/skywire/pkg/routing" diff --git a/pkg/router/router_test.go b/pkg/router/router_test.go index 93f220765..c35852164 100644 --- a/pkg/router/router_test.go +++ b/pkg/router/router_test.go @@ -16,7 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/skycoin/skywire/internal/noise" + "github.com/skycoin/dmsg/noise" "github.com/skycoin/skywire/pkg/app" routeFinder "github.com/skycoin/skywire/pkg/route-finder/client" "github.com/skycoin/skywire/pkg/routing" diff --git a/vendor/modules.txt b/vendor/modules.txt index 0e0aee446..ece3fd9d3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -66,8 +66,8 @@ github.com/sirupsen/logrus github.com/skycoin/dmsg/cipher github.com/skycoin/dmsg github.com/skycoin/dmsg/disc -github.com/skycoin/dmsg/ioutil github.com/skycoin/dmsg/noise +github.com/skycoin/dmsg/ioutil # github.com/skycoin/skycoin v0.26.0 github.com/skycoin/skycoin/src/util/logging github.com/skycoin/skycoin/src/cipher From 62b61e3bc9e7bd8054e173c1313a5fe2cbd1c69f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=BF=97=E5=AE=87?= Date: Wed, 3 Jul 2019 23:50:15 +0800 Subject: [PATCH 2/2] Simplified make test taarget. --- Makefile | 13 +------------ pkg/manager/node.go | 1 + pkg/node/node.go | 1 + pkg/router/loop_list.go | 1 + pkg/router/router.go | 1 + pkg/router/router_test.go | 1 + 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index e5ad3fa04..c23af79f6 100644 --- a/Makefile +++ b/Makefile @@ -62,18 +62,7 @@ vendorcheck: ## Run vendorcheck test: ## Run tests -go clean -testcache &>/dev/null ${OPTS} go test ${TEST_OPTS} ./internal/... - #${OPTS} go test -race -tags no_ci -cover -timeout=5m ./pkg/... - ${OPTS} go test ${TEST_OPTS} ./pkg/app/... -# ${OPTS} go test ${TEST_OPTS} ./pkg/cipher/... - ${OPTS} go test ${TEST_OPTS} ./pkg/manager/... - ${OPTS} go test ${TEST_OPTS} ./pkg/node/... - ${OPTS} go test ${TEST_OPTS} ./pkg/route-finder/... - ${OPTS} go test ${TEST_OPTS} ./pkg/router/... - ${OPTS} go test ${TEST_OPTS} ./pkg/routing/... - ${OPTS} go test ${TEST_OPTS} ./pkg/setup/... - ${OPTS} go test ${TEST_OPTS} ./pkg/transport/... - ${OPTS} go test ${TEST_OPTS} ./pkg/transport-discovery/... - + ${OPTS} go test ${TEST_OPTS} ./pkg/... install-linters: ## Install linters - VERSION=1.17.1 ./ci_scripts/install-golangci-lint.sh diff --git a/pkg/manager/node.go b/pkg/manager/node.go index 5e05a145a..c03fd31ec 100644 --- a/pkg/manager/node.go +++ b/pkg/manager/node.go @@ -20,6 +20,7 @@ import ( "github.com/skycoin/skycoin/src/util/logging" "github.com/skycoin/dmsg/noise" + "github.com/skycoin/skywire/pkg/httputil" "github.com/skycoin/skywire/pkg/node" "github.com/skycoin/skywire/pkg/routing" diff --git a/pkg/node/node.go b/pkg/node/node.go index eb93c052c..f9ae5367a 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -22,6 +22,7 @@ import ( "github.com/skycoin/skycoin/src/util/logging" "github.com/skycoin/dmsg/noise" + "github.com/skycoin/skywire/pkg/app" routeFinder "github.com/skycoin/skywire/pkg/route-finder/client" "github.com/skycoin/skywire/pkg/router" diff --git a/pkg/router/loop_list.go b/pkg/router/loop_list.go index c78f73752..2640c9de3 100644 --- a/pkg/router/loop_list.go +++ b/pkg/router/loop_list.go @@ -6,6 +6,7 @@ import ( "github.com/google/uuid" "github.com/skycoin/dmsg/noise" + "github.com/skycoin/skywire/pkg/app" "github.com/skycoin/skywire/pkg/routing" ) diff --git a/pkg/router/router.go b/pkg/router/router.go index 16533cdc6..14bad1484 100644 --- a/pkg/router/router.go +++ b/pkg/router/router.go @@ -15,6 +15,7 @@ import ( "github.com/skycoin/skycoin/src/util/logging" "github.com/skycoin/dmsg/noise" + "github.com/skycoin/skywire/pkg/app" routeFinder "github.com/skycoin/skywire/pkg/route-finder/client" "github.com/skycoin/skywire/pkg/routing" diff --git a/pkg/router/router_test.go b/pkg/router/router_test.go index c35852164..5d3f9c22f 100644 --- a/pkg/router/router_test.go +++ b/pkg/router/router_test.go @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/require" "github.com/skycoin/dmsg/noise" + "github.com/skycoin/skywire/pkg/app" routeFinder "github.com/skycoin/skywire/pkg/route-finder/client" "github.com/skycoin/skywire/pkg/routing"