Skip to content
This repository has been archived by the owner on May 26, 2022. It is now read-only.

Remove Noise Pipes & IK handshake #53

Merged
merged 4 commits into from
Mar 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,8 @@ negotiation in libp2p can be found in the [connection establishment spec][conn-s

## Status

This implementation is being updated to track some recent changes to the [spec][noise-libp2p-spec]:

- [ ] [use of channel binding token to prevent replay attacks](https://github.com/libp2p/specs/pull/234)

We recommend waiting until those changes are in place before adopting go-libp2p-noise for production use.
This implementation is currently considered "feature complete," but it has not yet
been widely tested in a production environment.

## Install

Expand All @@ -45,7 +42,7 @@ As `go-libp2p-noise` is still in development, it is not included as a default de
go get github.com/libp2p/go-libp2p-noise
```

This repo is [gomod](https://github.com/golang/go/wiki/Modules)-compatible, and users of
This repo is [gomod](https://github.com/golang/go/wiki/Modules) compatible, and users of
go 1.12 and later with modules enabled will automatically pull the latest tagged release
by referencing this package. Upgrades to future releases can be managed using `go get`,
or by editing your `go.mod` file as [described by the gomod documentation](https://github.com/golang/go/wiki/Modules#how-to-upgrade-and-downgrade-dependencies).
Expand All @@ -55,8 +52,27 @@ or by editing your `go.mod` file as [described by the gomod documentation](https
`go-libp2p-noise` is not currently enabled by default when constructing a new libp2p
[Host][godoc-host], so you will need to explicitly enable it in order to use it.

The API for constructing a new Noise transport is currently in flux. This README will
be updated once it stabilizes.
To do so, you can pass `noise.New` as an argument to a `libp2p.Security` `Option` when
constructing a libp2p `Host` with `libp2p.New`:

```go
import (
libp2p "github.com/libp2p/go-libp2p"
noise "github.com/libp2p/go-libp2p-noise"
)

// wherever you create your libp2p instance:
host := libp2p.New(
libp2p.Security(noise.ID, noise.New)
)
```

Note that the above snippet will _replace_ the default security protocols. To add Noise
as an additional protocol, chain it to the default options instead:

```go
libp2p.ChainOptions(libp2p.DefaultSecurity, libp2p.Security(noise.ID, noise.New))
```

## Contribute

Expand Down
53 changes: 18 additions & 35 deletions crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,39 @@ package noise

import (
"errors"
ik "github.com/libp2p/go-libp2p-noise/ik"
xx "github.com/libp2p/go-libp2p-noise/xx"
)

func (s *secureSession) Encrypt(plaintext []byte) (ciphertext []byte, err error) {
if s.xx_complete {
if s.initiator {
cs := s.xx_ns.CS1()
_, ciphertext = xx.EncryptWithAd(cs, nil, plaintext)
} else {
cs := s.xx_ns.CS2()
_, ciphertext = xx.EncryptWithAd(cs, nil, plaintext)
}
} else if s.ik_complete {
if s.initiator {
cs := s.ik_ns.CS1()
_, ciphertext = ik.EncryptWithAd(cs, nil, plaintext)
} else {
cs := s.ik_ns.CS2()
_, ciphertext = ik.EncryptWithAd(cs, nil, plaintext)
}
} else {
if !s.handshakeComplete {
return nil, errors.New("encrypt err: haven't completed handshake")
}

if s.initiator {
cs := s.ns.CS1()
_, ciphertext = xx.EncryptWithAd(cs, nil, plaintext)
} else {
cs := s.ns.CS2()
_, ciphertext = xx.EncryptWithAd(cs, nil, plaintext)
}

return ciphertext, nil
}

func (s *secureSession) Decrypt(ciphertext []byte) (plaintext []byte, err error) {
var ok bool
if s.xx_complete {
if s.initiator {
cs := s.xx_ns.CS2()
_, plaintext, ok = xx.DecryptWithAd(cs, nil, ciphertext)
} else {
cs := s.xx_ns.CS1()
_, plaintext, ok = xx.DecryptWithAd(cs, nil, ciphertext)
}
} else if s.ik_complete {
if s.initiator {
cs := s.ik_ns.CS2()
_, plaintext, ok = ik.DecryptWithAd(cs, nil, ciphertext)
} else {
cs := s.ik_ns.CS1()
_, plaintext, ok = ik.DecryptWithAd(cs, nil, ciphertext)
}
} else {
if !s.handshakeComplete {
return nil, errors.New("decrypt err: haven't completed handshake")
}

if s.initiator {
cs := s.ns.CS2()
_, plaintext, ok = xx.DecryptWithAd(cs, nil, ciphertext)
} else {
cs := s.ns.CS1()
_, plaintext, ok = xx.DecryptWithAd(cs, nil, ciphertext)
}

if !ok {
return nil, errors.New("decrypt err: could not decrypt")
}
Expand Down
40 changes: 40 additions & 0 deletions crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package noise

import (
"bytes"
"context"
"net"
"testing"

"github.com/libp2p/go-libp2p-core/crypto"
Expand Down Expand Up @@ -63,3 +65,41 @@ func TestEncryptAndDecrypt_RespToInit(t *testing.T) {
t.Fatal(err)
}
}

func TestCryptoFailsIfCiphertextIsAltered(t *testing.T) {
initTransport := newTestTransport(t, crypto.Ed25519, 2048)
respTransport := newTestTransport(t, crypto.Ed25519, 2048)

initConn, respConn := connect(t, initTransport, respTransport)
defer initConn.Close()
defer respConn.Close()

plaintext := []byte("helloworld")
ciphertext, err := respConn.Encrypt(plaintext)
if err != nil {
t.Fatal(err)
}

ciphertext[0] = ^ciphertext[0]

_, err = initConn.Decrypt(ciphertext)
if err == nil {
t.Fatal("expected decryption to fail when ciphertext altered")
}
}

func TestCryptoFailsIfHandshakeIncomplete(t *testing.T) {
initTransport := newTestTransport(t, crypto.Ed25519, 2048)
init, resp := net.Pipe()
_ = resp.Close()

session, _ := newSecureSession(initTransport, context.TODO(), init, "remote-peer", true)
_, err := session.Encrypt([]byte("hi"))
if err == nil {
t.Error("expected encryption error when handshake incomplete")
}
_, err = session.Decrypt([]byte("it's a secret"))
if err == nil {
t.Error("expected decryption error when handshake incomplete")
}
}
Loading