libdisco

package
v0.0.0-...-467bb60 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 11, 2020 License: 0BSD Imports: 17 Imported by: 20

README

LibDisco

The libdisco package contained in this folder is a plug-and-play secure protocol and library based on the Noise protocol framework and Strobe protocol framework. It has been implemented following the same patterns used in crypto/tls.

This has use cases close to TLS: it allows you to encrypt communications.

This software is experimental. You must not use this in production.

Build Status

Documentation

head over at www.discocrypto.com

Documentation

Overview

Package libdisco partially implements the Disco extension of the Noise protocol framework as specified in www.discocrypto.com/disco.html

More usage helpers are available on www.discocrypto.com

Author: David Wong

Index

Constants

View Source
const (
	DiscoDraftVersion = "3"
	NoiseDH           = "25519"
)

The following constants represent the details of this implementation of the Noise specification.

View Source
const (
	NoiseMessageLength    = 65535 - 2 // 2-byte length
	NoiseTagLength        = 16
	NoiseMaxPlaintextSize = NoiseMessageLength - NoiseTagLength
)

The following constants are taken directly from the Noise specification.

View Source
const (
	// NoiseUnknown is for specifying an unknown pattern
	NoiseUnknown noiseHandshakeType = iota
	// NoiseN is a one-way pattern where a client can send
	// data to a server with a known static key. The server
	// can only receive data and cannot reply back.
	NoiseN

	// NoiseK is a one-way pattern where a client can send
	// data to a server with a known static key. The server
	// can only receive data and cannot reply back. The server
	// authenticates the client via a known key.
	NoiseK

	// NoiseX is a one-way pattern where a client can send
	// data to a server with a known static key. The server
	// can only receive data and cannot reply back. The server
	// authenticates the client via a key transmitted as part
	// of the handshake.
	NoiseX

	// NoiseKK is a pattern where both the client static key and the
	// server static key are known.
	NoiseKK

	// NoiseNX is a "HTTPS"-like pattern where the client is
	// not authenticated, and the static public key of the server
	// is transmitted during the handshake. It is the responsability of the client to validate the received key properly.
	NoiseNX

	// NoiseNK is a "Public Key Pinning"-like pattern where the client
	// is not authenticated, and the static public key of the server
	// is already known.
	NoiseNK

	// NoiseXX is a pattern where both static keys are transmitted.
	// It is the responsability of the server and of the client to
	// validate the received keys properly.
	NoiseXX

	// NoiseKX Not documented
	NoiseKX
	// NoiseXK Not documented
	NoiseXK
	// NoiseIK Not documented
	NoiseIK
	// NoiseIX Not documented
	NoiseIX
	// NoiseNNpsk2 Not documented
	NoiseNNpsk2

	// NoiseNN Not implemented
	NoiseNN
	// NoiseKN Not implemented
	NoiseKN
	// NoiseXN Not implemented
	NoiseXN
	// NoiseIN Not implemented
	NoiseIN
)

Variables

This section is empty.

Functions

func CreatePublicKeyVerifier

func CreatePublicKeyVerifier(rootPublicKey ed25519.PublicKey) func([]byte, []byte) bool

CreatePublicKeyVerifier can be used to create the callback function PublicKeyVerifier sometimes required in a libdisco.Config for peers that are receiving a static public key at some point during the handshake

func CreateStaticPublicKeyProof

func CreateStaticPublicKeyProof(rootPrivateKey ed25519.PrivateKey, publicKey []byte) []byte

CreateStaticPublicKeyProof can be used to create the proof StaticPublicKeyProof sometimes required in a libdisco.Config for peers that are sending their static public key at some point during the handshake

func Decrypt

func Decrypt(key, ciphertext []byte) ([]byte, error)

Decrypt allows you to decrypt a message that was encrypted with the Encrypt function.

func DecryptAndAuthenticate

func DecryptAndAuthenticate(key, ciphertext, ad []byte) ([]byte, error)

DecryptAndAuthenticate allows you to decrypt a message that was encrypted with the Encrypt function.

func DeriveKeys

func DeriveKeys(inputKey []byte, outputLength int) []byte

DeriveKeys allows you to derive keys

func Dial

func Dial(network, addr string, config *Config) (net.Conn, error)

Dial connects to the given network address using net.Dial and then initiates a Disco handshake, returning the resulting Disco connection. Dial interprets a nil configuration as equivalent to the zero configuration; see the documentation of Config for the defaults.

func DialWithDialer

func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (net.Conn, error)

DialWithDialer connects to the given network address using dialer.Dial and then initiates a Disco handshake, returning the resulting Disco connection. Any timeout or deadline given in the dialer apply to connection and Disco handshake as a whole.

DialWithDialer interprets a nil configuration as equivalent to the zero configuration; see the documentation of Config for the defaults. TODO: make sure sane defaults for time outs are set!!!

func Encrypt

func Encrypt(key, plaintext []byte) []byte

Encrypt allows you to encrypt a plaintext message with a key of any size greater than 128 bits (16 bytes).

func EncryptAndAuthenticate

func EncryptAndAuthenticate(key, plaintext, ad []byte) []byte

EncryptAndAuthenticate allows you to encrypt a plaintext message with a key of any size greater than 128 bits (16 bytes).

func GenerateAndSaveDiscoRootKeyPair

func GenerateAndSaveDiscoRootKeyPair(discoRootPrivateKeyFile string, discoRootPublicKeyFile string) (err error)

GenerateAndSaveDiscoRootKeyPair generates an ed25519 root key pair and save the private and public parts in different files.

func Hash

func Hash(input []byte, outputLength int) []byte

Hash allows you to hash an input of any length and obtain an output of length greater or equal to 256 bits (32 bytes).

func Initialize

func Initialize(handshakeType noiseHandshakeType, initiator bool, prologue []byte, s, e, rs, re *KeyPair) (hs handshakeState)

Initialize allows you to initialize a peer * see `patterns` for a list of available handshakePatterns * initiator = false means the instance is for a responder * prologue is a byte string record of anything that happened prior the Noise handshakeState * s, e, rs, re are the local and remote static/ephemeral key pairs to be set (if they exist) the function returns a handshakeState object.

func Listen

func Listen(network, laddr string, config *Config) (net.Listener, error)

Listen creates a Disco listener accepting connections on the given network address using net.Listen. The configuration config must be non-nil.

func LoadDiscoRootPrivateKey

func LoadDiscoRootPrivateKey(discoRootPrivateKey string) (rootPrivateKey ed25519.PrivateKey, err error)

LoadDiscoRootPrivateKey reads and parses a private Root key from a file. The file contains an 32-byte ed25519 private key in hexadecimal

func LoadDiscoRootPublicKey

func LoadDiscoRootPublicKey(discoRootPublicKey string) (rootPublicKey ed25519.PublicKey, err error)

LoadDiscoRootPublicKey reads and parses a public Root key from a file. The file contains an 32-byte ed25519 public key in hexadecimal

func ProtectIntegrity

func ProtectIntegrity(key, plaintext []byte) []byte

ProtectIntegrity allows you to send a message in cleartext (not encrypted) You can later verify via the VerifyIntegrity function that the message has not been modified

func RecoverState

func RecoverState(serialized []byte, psk []byte, s *KeyPair) handshakeState

RecoverState is a helper function to unserialize a previously serialized handshake state (via the `Serialize()` function). For security purposes, the long-term static keypair needs to be passed as argument. RecoverState will crash if the passed serializedState is malformed

func VerifyIntegrity

func VerifyIntegrity(key, plaintextAndTag []byte) ([]byte, error)

VerifyIntegrity allows you to retrieve a message created with the ProtectIntegrity function. if it returns an error, it means that the message was altered. Otherwise it returns the original message.

Types

type Addr

type Addr struct {
	// contains filtered or unexported fields
}

Addr represents a newtork address.

func (Addr) Network

func (a Addr) Network() string

Network returns the network.

func (Addr) String

func (a Addr) String() string

String implements stringer interface

type Config

type Config struct {
	// the type of Noise protocol that the client and the server will go through
	HandshakePattern noiseHandshakeType
	// the current peer's keyPair
	KeyPair *KeyPair
	// the other peer's public key
	RemoteKey []byte
	// any messages that the client and the server previously exchanged in clear
	Prologue []byte
	// if the chosen handshake pattern requires the current peer to send a static
	// public key as part of the handshake, this proof over the key is mandatory
	// in order for the other peer to verify the current peer's key
	StaticPublicKeyProof []byte
	// if the chosen handshake pattern requires the remote peer to send an unknown
	// static public key as part of the handshake, this callback is mandatory in
	// order to validate it
	PublicKeyVerifier func(publicKey, proof []byte) bool
	// a pre-shared key for handshake patterns including a `psk` token
	PreSharedKey []byte
	// by default a noise protocol is full-duplex, meaning that both the client
	// and the server can write on the channel at the same time. Setting this value
	// to true will require the peers to write and read in turns. If this requirement
	// is not respected by the application, the consequences could be catastrophic
	HalfDuplex bool
	// the Accept() and Dial() APIs both return a `net.Conn` interface.
	// Because of this, functions like `RemotePublicKey()` cannot be called
	// to circumvent this issue, set the following flag. After that,
	// `net.Conn`'s `RemoteAddress().String()` will return a tuple `ip:port:pubkey`
	RemoteAddrContainsRemotePubkey bool
}

Config is mandatory to setup a Disco peer. It represents the configuration of the Disco handshake that the peer will go through.

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

A Conn represents a secured connection. It implements the net.Conn interface.

func Client

func Client(conn net.Conn, config *Config) *Conn

Client returns a new Disco client side connection using conn as the underlying transport. The config cannot be nil: users must set either ServerName or InsecureSkipVerify in the config.

func Server

func Server(conn net.Conn, config *Config) *Conn

Server returns a new Disco server side connection using net.Conn as the underlying transport. The configuration config must be non-nil and must include at least one certificate or else set GetCertificate.

func (*Conn) Close

func (c *Conn) Close() error

Close closes the connection.

func (*Conn) Handshake

func (c *Conn) Handshake() error

Handshake runs the client or server handshake protocol if it has not yet been run. Most uses of this package need not call Handshake explicitly: the first Read or Write will call it automatically.

func (*Conn) IsRemoteAuthenticated

func (c *Conn) IsRemoteAuthenticated() bool

IsRemoteAuthenticated can be used to check if the remote peer has been properly authenticated. It serves no real purpose for the moment as the handshake will not go through if a peer is not properly authenticated in patterns where the peer needs to be authenticated.

func (*Conn) LocalAddr

func (c *Conn) LocalAddr() net.Addr

LocalAddr returns the local network address.

func (*Conn) Read

func (c *Conn) Read(b []byte) (n int, err error)

Read can be made to time out and return a net.Error with Timeout() == true after a fixed time limit; see SetDeadline and SetReadDeadline.

func (*Conn) RemoteAddr

func (c *Conn) RemoteAddr() net.Addr

RemoteAddr returns the remote network address.

func (*Conn) RemotePublicKey

func (c *Conn) RemotePublicKey() (string, error)

RemotePublicKey returns the static key of the remote peer. It is useful in case the static key is only transmitted during the handshake.

func (*Conn) SetDeadline

func (c *Conn) SetDeadline(t time.Time) error

SetDeadline sets the read and write deadlines associated with the connection. A zero value for t means Read and Write will not time out. After a Write has timed out, the Disco state is corrupt and all future writes will return the same error.

func (*Conn) SetReadDeadline

func (c *Conn) SetReadDeadline(t time.Time) error

SetReadDeadline sets the read deadline on the underlying connection. A zero value for t means Read will not time out.

func (*Conn) SetWriteDeadline

func (c *Conn) SetWriteDeadline(t time.Time) error

SetWriteDeadline sets the write deadline on the underlying connection. A zero value for t means Write will not time out. After a Write has timed out, the Disco state is corrupt and all future writes will return the same error.

func (*Conn) Write

func (c *Conn) Write(b []byte) (int, error)

Write writes data to the connection.

type DiscoHash

type DiscoHash struct {
	// contains filtered or unexported fields
}

DiscoHash represents a strobe hash

func NewHash

func NewHash(outputLength int) DiscoHash

NewHash creates a new hashing state, allowing you to absorb data to hash via Write or WriteTuple, and to create a digest via the Sum function.

func (*DiscoHash) Clone

func (d *DiscoHash) Clone() DiscoHash

Clone returns a copy of the DiscoHash in its current state.

func (*DiscoHash) Sum

func (d *DiscoHash) Sum() []byte

Sum reads more output from the hash; reading affects the hash's state. (DiscoHash.Read is thus very different from Hash.Sum) It never returns an error.

func (*DiscoHash) Write

func (d *DiscoHash) Write(inputData []byte) (written int, err error)

Write absorbs more data into the hash's state. This function is usually called to hash contigous chunks of data. For structured data please refer to WriteTuple

func (*DiscoHash) WriteTuple

func (d *DiscoHash) WriteTuple(inputData []byte) (written int, err error)

WriteTuple absorbs more data to hash in a non-ambigious way. This means that data absorbed via this function is separated from the data surrounding it. Use this function instead of Write to hash structured data.

type KeyPair

type KeyPair struct {
	PrivateKey [32]byte // must stay a [32]byte because of Serialize()
	PublicKey  [32]byte // must stay a [32]byte because of Serialize()
}

KeyPair contains a private and a public part, both of 32-byte. It can be generated via the GenerateKeyPair() function. The public part can also be extracted via the ExportPublicKey function.

func GenerateAndSaveDiscoKeyPair

func GenerateAndSaveDiscoKeyPair(discoKeyPairFile string, passphrase string) (keyPair *KeyPair, err error)

GenerateAndSaveDiscoKeyPair generates a disco key pair (X25519 key pair) and saves it to a file in hexadecimal form. If a non-empty passphrase is passed, the file will be encrypted. You can use ExportPublicKey() to export the public key part.

func GenerateKeypair

func GenerateKeypair(privateKey *[32]byte) *KeyPair

GenerateKeypair creates a X25519 static keyPair out of a private key. If privateKey is nil the function generates a random key pair.

func LoadDiscoKeyPair

func LoadDiscoKeyPair(discoKeyPairFile, passphrase string) (*KeyPair, error)

LoadDiscoKeyPair reads and parses a public/private key pair from a pair of files. You can pass a non-empty passphrase if the keys are stored encrypted.

func (KeyPair) ExportPublicKey

func (kp KeyPair) ExportPublicKey() string

ExportPublicKey returns the public part in hex format of a static key pair.

type Listener

type Listener struct {
	net.Listener
	// contains filtered or unexported fields
}

Listener implements a network listener (net.Listener) for Disco connections.

func ListenDisco

func ListenDisco(network, laddr string, config *Config) (*Listener, error)

ListenDisco creates a Disco listener accepting connections on the given network address using net.Listen. The configuration config must be non-nil.

func (*Listener) Accept

func (l *Listener) Accept() (net.Conn, error)

Accept waits for and returns the next incoming Disco connection. The returned connection is of type *Conn.

func (*Listener) AcceptDisco

func (l *Listener) AcceptDisco() (*Conn, error)

AcceptDisco waits for and returns the next incoming Disco connection. The returned connection is of type *Conn.

type Signature

type Signature struct {
	R ristretto.Element
	S ristretto.Scalar
}

Signature represents a schnorrkel signature

func (*Signature) Decode

func (s *Signature) Decode(sigBytes [64]byte) error

Decode a schnorrkel signature from a bytearray. ref: https://github.com/w3f/schnorrkel/blob/master/src/sign.rs#L100

func (*Signature) Encode

func (s *Signature) Encode() [64]byte

Encode a signature as a bytearray. see: https://github.com/w3f/schnorrkel/blob/master/src/sign.rs#L77

type SigningKeypair

type SigningKeypair struct {
	SecretKey ristretto.Scalar
	PublicKey ristretto.Element
}

SigningKeypair uses deterministic Schnorr with strobe

func GenerateSigningKeypair

func GenerateSigningKeypair() (SigningKeypair, error)

GenerateSigningKeypair for schnorr signatures.

func (SigningKeypair) ExportPublicKey

func (kp SigningKeypair) ExportPublicKey() string

ExportPublicKey returns a hexstring encoding of the signing keypair.

func (SigningKeypair) Sign

func (kp SigningKeypair) Sign(message []byte) Signature

Sign a message using a deterministic nonce

func (SigningKeypair) Verify

func (kp SigningKeypair) Verify(message []byte, signature Signature) error

Verify a signature

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL