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

remove the Protector interface, introduce a PSK type #118

Merged
merged 4 commits into from
Mar 7, 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
66 changes: 66 additions & 0 deletions pnet/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package pnet

import (
"bufio"
"bytes"
"encoding/base64"
"encoding/hex"
"fmt"
"io"
)

var (
pathPSKv1 = []byte("/key/swarm/psk/1.0.0/")
pathBin = "/bin/"
pathBase16 = "/base16/"
pathBase64 = "/base64/"
)

func readHeader(r *bufio.Reader) ([]byte, error) {
header, err := r.ReadBytes('\n')
if err != nil {
return nil, err
}

return bytes.TrimRight(header, "\r\n"), nil
}

func expectHeader(r *bufio.Reader, expected []byte) error {
header, err := readHeader(r)
if err != nil {
return err
}
if !bytes.Equal(header, expected) {
return fmt.Errorf("expected file header %s, got: %s", pathPSKv1, header)
}
return nil
}

// DecodeV1PSK reads a Multicodec encoded V1 PSK.
func DecodeV1PSK(in io.Reader) (PSK, error) {
reader := bufio.NewReader(in)
if err := expectHeader(reader, pathPSKv1); err != nil {
return nil, err
}
header, err := readHeader(reader)
if err != nil {
return nil, err
}

var decoder io.Reader
switch string(header) {
case pathBase16:
decoder = hex.NewDecoder(reader)
case pathBase64:
decoder = base64.NewDecoder(base64.StdEncoding, reader)
case pathBin:
decoder = reader
default:
return nil, fmt.Errorf("unknown encoding: %s", header)
}
out := make([]byte, 32)
if _, err = io.ReadFull(decoder, out[:]); err != nil {
return nil, err
}
return out, nil
}
122 changes: 122 additions & 0 deletions pnet/codec_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package pnet

import (
"bytes"
"encoding/base64"
"testing"
)

func bufWithBase(base string, windows bool) *bytes.Buffer {
b := &bytes.Buffer{}
b.Write(pathPSKv1)
if windows {
b.WriteString("\r")
}
b.WriteString("\n")
b.WriteString(base)
if windows {
b.WriteString("\r")
}
b.WriteString("\n")
return b
}

func TestDecodeHex(t *testing.T) {
testDecodeHex(t, true)
testDecodeHex(t, false)
}

func TestDecodeBad(t *testing.T) {
testDecodeBad(t, true)
testDecodeBad(t, false)
}

func testDecodeBad(t *testing.T, windows bool) {
b := bufWithBase("/verybadbase/", windows)
b.WriteString("Have fun decoding that key")

_, err := DecodeV1PSK(b)
if err == nil {
t.Fatal("expected 'unknown encoding' got nil")
}
}

func testDecodeHex(t *testing.T, windows bool) {
b := bufWithBase("/base16/", windows)
for i := 0; i < 32; i++ {
b.WriteString("FF")
}

psk, err := DecodeV1PSK(b)
if err != nil {
t.Fatal(err)
}

for _, b := range psk {
if b != 255 {
t.Fatal("byte was wrong")
}
}
}

func TestDecodeB64(t *testing.T) {
testDecodeB64(t, true)
testDecodeB64(t, false)
}

func testDecodeB64(t *testing.T, windows bool) {
b := bufWithBase("/base64/", windows)
key := make([]byte, 32)
for i := 0; i < 32; i++ {
key[i] = byte(i)
}

e := base64.NewEncoder(base64.StdEncoding, b)
_, err := e.Write(key)
if err != nil {
t.Fatal(err)
}
err = e.Close()
if err != nil {
t.Fatal(err)
}

psk, err := DecodeV1PSK(b)
if err != nil {
t.Fatal(err)
}

for i, b := range psk {
if b != psk[i] {
t.Fatal("byte was wrong")
}
}

}

func TestDecodeBin(t *testing.T) {
testDecodeBin(t, true)
testDecodeBin(t, false)
}

func testDecodeBin(t *testing.T, windows bool) {
b := bufWithBase("/bin/", windows)
key := make([]byte, 32)
for i := 0; i < 32; i++ {
key[i] = byte(i)
}

b.Write(key)

psk, err := DecodeV1PSK(b)
if err != nil {
t.Fatal(err)
}

for i, b := range psk {
if b != psk[i] {
t.Fatal("byte was wrong")
}
}

}
16 changes: 4 additions & 12 deletions pnet/protector.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
// Package pnet provides interfaces for private networking in libp2p.
package pnet

import "net"

// Protector interface is a way for private network implementation to be transparent in
// libp2p. It is created by implementation and use by libp2p-conn to secure connections
// so they can be only established with selected number of peers.
type Protector interface {
// Wraps passed connection to protect it
Protect(net.Conn) (net.Conn, error)

// Returns key fingerprint that is safe to expose
Fingerprint() []byte
}
// A PSK enables private network implementation to be transparent in libp2p.
// It is used to ensure that peers can only establish connections to other peers
// that are using the same PSK.
type PSK []byte
marten-seemann marked this conversation as resolved.
Show resolved Hide resolved