mailbox

package
v0.2.8-alpha Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2023 License: MIT Imports: 39 Imported by: 10

Documentation

Index

Constants

View Source
const (
	// NumPassphraseWords is the number of words we use for the pairing
	// phrase.
	NumPassphraseWords = 10

	// NumPassphraseEntropyBytes is the number of bytes we use for the
	// pairing phrase. This must be:
	//   ceil( (NumPassphraseWords * aezeed.BitsPerWord) / 8 )
	NumPassphraseEntropyBytes = 14
)
View Source
const (
	// ProtocolName is the name of the protocol that's used for the
	// encrypted communication.
	ProtocolName = "XXeke_secp256k1+SPAKE2_CHACHAPOLY1305_SHA256"

	// ProtocolVersion is the version of the protocol used for the encrypted
	// communication.
	ProtocolVersion = 0
)
View Source
const (

	// HandshakeVersion0 is the handshake version in which the auth data
	// is sent in a fixed sized payload in act 2.
	HandshakeVersion0 = byte(0)

	// HandshakeVersion1 is the handshake version in which the auth data
	// is sent in a dynamically sized, length-prefixed payload in act 2.
	HandshakeVersion1 = byte(1)

	// HandshakeVersion2 is the handshake version that indicates that the
	// KK pattern is to be used for all handshakes after the first
	// handshake.
	HandshakeVersion2 = byte(2)

	// MinHandshakeVersion is the minimum handshake version that is
	// currently supported.
	MinHandshakeVersion = HandshakeVersion0

	// MaxHandshakeVersion is the maximum handshake that we currently
	// support. Any messages that carry a version not between
	// MinHandshakeVersion and MaxHandshakeVersion will cause the handshake
	// to abort immediately.
	MaxHandshakeVersion = HandshakeVersion2

	// ActTwoPayloadSize is the size of the fixed sized payload that can be
	// sent from the responder to the Initiator in act two.
	ActTwoPayloadSize = 500
)
View Source
const (
	// XX is the name of the Noise XX Handshake pattern that uses SPAKE2
	// to mask the ephemeral key sent in the first act.
	XX = "XXeke+SPAKE2"

	// KK is the name of the Noise KK Handshake pattern.
	KK = "KK"
)
View Source
const Subsystem = "MBOX"

Variables

View Source
var (
	// ErrMaxMessageLengthExceeded is returned a message to be written to
	// the cipher session exceeds the maximum allowed message payload.
	ErrMaxMessageLengthExceeded = errors.New("the generated payload exceeds " +
		"the max allowed message length of (2^16)-1")

	// ErrMessageNotFlushed signals that the connection cannot accept a new
	// message because the prior message has not been fully flushed.
	ErrMessageNotFlushed = errors.New("prior message not flushed")

	N, _ = btcec.ParsePubKey(nBytes)
)
View Source
var (
	// XXPattern represents the XX Noise pattern using SPAKE2 to mask
	// the ephemeral key of the first message.
	// -> me
	// <- e, ee, s, es
	// -> s, se
	XXPattern = HandshakePattern{
		Name: XX,
		Pattern: []MessagePattern{
			{
				Tokens:    []Token{me},
				Initiator: true,
				ActNum:    act1,
			},
			{
				Tokens:    []Token{e, ee, s, es},
				Initiator: false,
				ActNum:    act2,
			},
			{
				Tokens:    []Token{s, se},
				Initiator: true,
				ActNum:    act3,
			},
		},
	}

	// KKPattern represents the KK Noise pattern in which both initiator
	// and responder start off knowing the static remote key of the other.
	// -> s
	// <- s
	// ...
	// <- e, es, ss
	// -> e, ee, se
	KKPattern = HandshakePattern{
		Name: KK,
		PreMessages: []MessagePattern{
			{
				Tokens:    []Token{s},
				Initiator: true,
			},
			{
				Tokens:    []Token{s},
				Initiator: false,
			},
		},
		Pattern: []MessagePattern{
			{
				Tokens:    []Token{e, es, ss},
				Initiator: true,
				ActNum:    act1,
			},
			{
				Tokens:    []Token{e, ee, se},
				Initiator: false,
				ActNum:    act2,
			},
		},
	}
)

Functions

func GetSID

func GetSID(sid [64]byte, serverToClient bool) [64]byte

func NewClientWebsocketConn

func NewClientWebsocketConn(mailboxServer, pairingPhrase string,
	localStatic keychain.SingleKeyECDH, remoteStatic *btcec.PublicKey,
	onRemoteStatic func(key *btcec.PublicKey) error,
	onAuthData func(data []byte) error) (func() ClientStatus,
	func() (*grpc.ClientConn, error), error)

NewClientWebsocketConn attempts to create websocket LNC client connection to a server connection listening at the given mailbox server.

func NewPassphraseEntropy

func NewPassphraseEntropy() ([NumPassphraseWords]string,
	[NumPassphraseEntropyBytes]byte, error)

NewPassphraseEntropy generates a new one-time-use passphrase, represented as a set of mnemonic words and the raw entropy itself.

func PassphraseEntropyToMnemonic

func PassphraseEntropyToMnemonic(
	entropy [NumPassphraseEntropyBytes]byte) ([NumPassphraseWords]string,
	error)

PassphraseEntropyToMnemonic turns the raw bytes of the passphrase entropy into human-readable mnemonic words. NOTE: This will only use NumPassphraseWords * aezeed.BitsPerWord bits of the provided entropy.

func PassphraseMnemonicToEntropy

func PassphraseMnemonicToEntropy(
	passphrase [NumPassphraseWords]string) [NumPassphraseEntropyBytes]byte

PassphraseMnemonicToEntropy reverses the mnemonic word encoding and returns the raw passphrase entropy bytes. NOTE: This will only set the first NumPassphraseWords * aezeed.BitsPerWord bits of the entropy. The remaining bits will be set to zero.

func UseLogger

func UseLogger(logger btclog.Logger)

UseLogger uses a specified Logger to output package logging info. This should be used in preference to SetLogWriter if the caller is also using btclog.

func WithMaxHandshakeVersion

func WithMaxHandshakeVersion(version byte) func(*NoiseGrpcConn)

WithMaxHandshakeVersion is a functional option used to set the maximum handshake version supported.

func WithMinHandshakeVersion

func WithMinHandshakeVersion(version byte) func(*NoiseGrpcConn)

WithMinHandshakeVersion is a functional option used to set the minimum handshake version supported.

Types

type ActNum

type ActNum uint8

ActNum is the index of a message pattern within a handshake pattern.

type Addr

type Addr struct {
	// SID is the unique session ID used for the mailbox connection. It is
	// derived from the one-time connection passphraseEntropy.
	SID [64]byte

	// Server is the mailbox server this connection is established over.
	Server string
}

Addr is a type that implements the net.Addr interface for addresses involved in mailbox connections.

func (*Addr) Network

func (b *Addr) Network() string

Network returns the network identifier for mailbox connections which is always 'mailbox'.

func (*Addr) String

func (b *Addr) String() string

String returns a string representation of a mailbox address.

type AuthInfo

type AuthInfo struct {
	credentials.CommonAuthInfo
}

AuthInfo is a type that implements the gRPC specific credentials.AuthInfo interface that's needed for implementing a secure client/server handshake.

func NewAuthInfo

func NewAuthInfo() *AuthInfo

NewAuthInfo returns a new AuthInfo instance.

func (*AuthInfo) AuthType

func (a *AuthInfo) AuthType() string

AuthType returns the type of this custom authentication scheme.

type BrontideMachineConfig

type BrontideMachineConfig struct {
	ConnData            ConnectionData
	Initiator           bool
	HandshakePattern    HandshakePattern
	MinHandshakeVersion byte
	MaxHandshakeVersion byte
	EphemeralGen        func() (*btcec.PrivateKey, error)
}

BrontideMachineConfig holds the config necessary to construct a new Machine object.

type Client

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

Client manages the mailboxConn it holds and refreshes it on connection retries.

func NewGrpcClient

func NewGrpcClient(ctx context.Context, serverHost string, connData *ConnData,
	dialOpts ...grpc.DialOption) (*Client, error)

NewGrpcClient creates a new Client object which will handle the mailbox connection and will use grpc streams to connect to the mailbox.

func NewWebsocketsClient

func NewWebsocketsClient(ctx context.Context, serverHost string,
	connData *ConnData) (*Client, error)

NewWebsocketsClient creates a new Client object which will handle the mailbox connection and will use websockets to connect to the mailbox.

func (*Client) ConnStatus

func (c *Client) ConnStatus() ClientStatus

ConnStatus returns last determined client connection status.

func (*Client) Dial

func (c *Client) Dial(_ context.Context, _ string) (net.Conn, error)

Dial returns a net.Conn abstraction over the mailbox connection. Dial is called everytime grpc retries the connection. If this is the first connection, a new ClientConn will be created. Otherwise, the existing connection will just be refreshed.

type ClientConn

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

ClientConn is a type that establishes a base transport connection to a mailbox server using a REST/WebSocket connection. This type can be used to initiate a mailbox transport connection from a browser/WASM environment.

func NewClientConn

func NewClientConn(ctx context.Context, sid [64]byte, serverHost string,
	client hashmailrpc.HashMailClient,
	onNewStatus func(status ClientStatus)) (*ClientConn, error)

NewClientConn creates a new client connection with the given receive and send session identifiers. The context given as the first parameter will be used throughout the connection lifetime.

func RefreshClientConn

func RefreshClientConn(ctx context.Context, c *ClientConn) (*ClientConn,
	error)

RefreshClientConn creates a new ClientConn object with the same values as the passed ClientConn but with a new quit channel, a new closeOnce var and a new gbn connection.

func (*ClientConn) Close

func (c *ClientConn) Close() error

Close closes the underlying mailbox connection.

NOTE: This is part of the net.Conn interface.

func (*ClientConn) Done

func (c *ClientConn) Done() <-chan struct{}

Done returns the quit channel of the ClientConn and thus can be used to determine if the current connection is closed or not.

func (ClientConn) LocalAddr

func (k ClientConn) LocalAddr() net.Addr

LocalAddr returns the address of the local side of this connection.

NOTE: This is part of the net.Conn interface.

func (ClientConn) Read

func (k ClientConn) Read(b []byte) (int, error)

Read reads data from the underlying control connection.

NOTE: This is part of the net.Conn interface.

func (*ClientConn) ReceiveControlMsg

func (c *ClientConn) ReceiveControlMsg(receive ControlMsg) error

ReceiveControlMsg tries to receive a control message over the underlying mailbox connection.

NOTE: This is part of the Conn interface.

func (ClientConn) RemoteAddr

func (k ClientConn) RemoteAddr() net.Addr

RemoteAddr returns the address of the remote side of this connection.

NOTE: This is part of the net.Conn interface.

func (*ClientConn) SendControlMsg

func (c *ClientConn) SendControlMsg(controlMsg ControlMsg) error

SendControlMsg tries to send a control message over the underlying mailbox connection.

NOTE: This is part of the Conn interface.

func (ClientConn) SetDeadline

func (k ClientConn) SetDeadline(t time.Time) error

SetDeadline sets the read and write deadlines associated with the connection. It is equivalent to calling both SetReadDeadline and SetWriteDeadline.

NOTE: This is part of the net.Conn interface.

func (ClientConn) SetReadDeadline

func (k ClientConn) SetReadDeadline(t time.Time) error

SetReadDeadline sets the deadline for future Read calls and any currently-blocked Read call.

NOTE: This is part of the net.Conn interface.

func (*ClientConn) SetRecvTimeout

func (c *ClientConn) SetRecvTimeout(timeout time.Duration)

SetRecvTimeout sets the timeout to be used when attempting to receive data.

func (*ClientConn) SetSendTimeout

func (c *ClientConn) SetSendTimeout(timeout time.Duration)

SetSendTimeout sets the timeout to be used when attempting to send data.

func (ClientConn) SetWriteDeadline

func (k ClientConn) SetWriteDeadline(t time.Time) error

SetWriteDeadline sets the deadline for future Write calls and any currently-blocked Write call.

NOTE: This is part of the net.Conn interface.

func (ClientConn) Write

func (k ClientConn) Write(b []byte) (n int, err error)

Write writes data to the underlying control connection.

NOTE: This is part of the net.Conn interface.

type ClientConnTransport

type ClientConnTransport interface {
	// Refresh creates a new ClientConnTransport with no initialised send
	// or receive connections.
	Refresh() ClientConnTransport

	// ReceiveConnected returns true if the transport is connected to the
	// hashmail-server receive stream.
	ReceiveConnected() bool

	// SendConnected returns true if the transport is connected to the
	// hashmail-server send stream.
	SendConnected() bool

	// ConnectReceive can be called in order to initialise the
	// receive-stream with the hashmail-server.
	ConnectReceive(ctx context.Context) error

	// ConnectSend can be called in order to initialise the send-stream with
	// the hashmail-server.
	ConnectSend(ctx context.Context) error

	// Recv will attempt to read data off of the underlying transport's
	// receive stream.
	Recv(ctx context.Context) ([]byte, bool, ClientStatus, error)

	// Send will attempt to send data on the underlying transport's send
	// stream.
	Send(ctx context.Context, streamID, payload []byte) (bool, ClientStatus,
		error)

	// CloseReceive will close the transport's connection to the
	// receive-stream.
	CloseReceive() error

	// CloseSend will close the transport's connection to the send-stream.
	CloseSend() error
}

ClientConnTransport is an interface that hides the implementation of the underlying send and receive connections to a hashmail server.

type ClientStatus

type ClientStatus string

ClientStatus is a description of the connection status of the client.

const (
	// ClientStatusNotConnected means that the client is not connected at
	// all. This is likely due to the mailbox server being down.
	ClientStatusNotConnected ClientStatus = "Not Connected"

	// ClientStatusSessionNotFound means that the connection to the mailbox
	// server was successful but that the mailbox with the given ID was not
	// found. This either means that the server is down, that the session
	// has expired or that the user entered passphrase was incorrect.
	ClientStatusSessionNotFound ClientStatus = "Session Not Found"

	// ClientStatusSessionInUse means that the connection to the mailbox
	// server was successful but that the stream for the session is already
	// occupied by another client.
	ClientStatusSessionInUse ClientStatus = "Session In Use"

	// ClientStatusConnected indicates that the connection to both the
	// mailbox server and end server was successful.
	ClientStatusConnected ClientStatus = "Connected"
)

func (ClientStatus) String

func (c ClientStatus) String() string

String converts the ClientStatus to a string type.

type ConnData

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

ConnData manages all the items needed for establishing a noise connection to a peer. This is an implementation of the ConnectionData interface with some extra methods that are customised for our specific usage of the Noise Machine and the underlying connection.

func NewConnData

func NewConnData(localKey keychain.SingleKeyECDH, remoteKey *btcec.PublicKey,
	passphraseEntropy []byte, authData []byte,
	onRemoteStatic func(key *btcec.PublicKey) error,
	onAuthData func(data []byte) error) *ConnData

NewConnData creates a new ConnData instance.

func (*ConnData) AuthData

func (s *ConnData) AuthData() []byte

AuthData returns the auth date we intend to send to our peer if we are the responder or have received from our peer if we are the initiator. NOTE: This is part of the ConnectionData interface.

func (*ConnData) HandshakePattern

func (s *ConnData) HandshakePattern() HandshakePattern

HandshakePattern returns the handshake pattern we should use for a noise handshake given knowledge of the remote static key.

func (*ConnData) LocalKey

func (s *ConnData) LocalKey() keychain.SingleKeyECDH

LocalKey returns the local static key being used for the connection. NOTE: This is part of the ConnectionData interface.

func (*ConnData) PassphraseEntropy

func (s *ConnData) PassphraseEntropy() []byte

PassphraseEntropy returns the entropy bytes we will use to mask our key during the first step of the Noise XX handshake. NOTE: This is part of the ConnectionData interface.

func (*ConnData) RemoteKey

func (s *ConnData) RemoteKey() *btcec.PublicKey

RemoteKey returns the remote static key being used for the connection. NOTE: This is part of the ConnectionData interface.

func (*ConnData) SID

func (s *ConnData) SID() ([64]byte, error)

SID calculates the SID to be used given the presence of the remote static key. If the remote key is not present, then only the passphraseEntropy will be used to derive the SID. Otherwise, the ECDH operation on the remote and local key will be used.

func (*ConnData) SetAuthData

func (s *ConnData) SetAuthData(data []byte) error

SetAuthData calls the onAuthData callback with the given data and updates the auth data we have stored. NOTE: This is part of the ConnectionData interface.

func (*ConnData) SetRemote

func (s *ConnData) SetRemote(key *btcec.PublicKey) error

SetRemote updates the remote static key we have stored and also calls the onRemoteStatic call back. NOTE: This is part of the ConnectionData interface.

type ConnectionData

type ConnectionData interface {
	// LocalKey returns the local static key being used for the connection.
	LocalKey() keychain.SingleKeyECDH

	// RemoteKey returns the remote parties static key being used for the
	// connection.
	RemoteKey() *btcec.PublicKey

	// PassphraseEntropy returns the entropy bytes to be used for mask
	// the local ephemeral key during the first step of the Noise XX
	// handshake.
	PassphraseEntropy() []byte

	// AuthData returns the auth date we intend to send to our peer if we
	// are the responder or have received from our peer if we are the
	// initiator.
	AuthData() []byte

	// SetRemote processes and stores the remote parties static key.
	SetRemote(key *btcec.PublicKey) error

	// SetAuthData processes and stores the auth data received from the
	// remote party.
	SetAuthData(data []byte) error
}

ConnectionData is the interface that needs to be implemented by any object that the Brontide Noise Machine can use to fetch and set connection data.

type ControlMsg

type ControlMsg interface {
	ProtocolVersion() uint8
	Serialize() ([]byte, error)
	Deserialize([]byte) error
}

ControlMsg is the interface that needs to be implemented by any message that is sent over a control connection.

type GrpcLogLogger

type GrpcLogLogger struct {
	btclog.Logger
}

GrpcLogLogger is a wrapper around a btclog logger to make it compatible with the grpclog logger package. By default we downgrade the info level to debug to reduce the verbosity of the logger.

func (GrpcLogLogger) Errorln

func (l GrpcLogLogger) Errorln(args ...interface{})

func (GrpcLogLogger) Fatal

func (l GrpcLogLogger) Fatal(args ...interface{})

func (GrpcLogLogger) Fatalf

func (l GrpcLogLogger) Fatalf(format string, args ...interface{})

func (GrpcLogLogger) Fatalln

func (l GrpcLogLogger) Fatalln(args ...interface{})

func (GrpcLogLogger) Info

func (l GrpcLogLogger) Info(args ...interface{})

func (GrpcLogLogger) Infof

func (l GrpcLogLogger) Infof(format string, args ...interface{})

func (GrpcLogLogger) Infoln

func (l GrpcLogLogger) Infoln(args ...interface{})

func (GrpcLogLogger) V

func (l GrpcLogLogger) V(level int) bool

func (GrpcLogLogger) Warning

func (l GrpcLogLogger) Warning(args ...interface{})

func (GrpcLogLogger) Warningf

func (l GrpcLogLogger) Warningf(format string, args ...interface{})

func (GrpcLogLogger) Warningln

func (l GrpcLogLogger) Warningln(args ...interface{})

type HandshakePattern

type HandshakePattern struct {
	PreMessages []MessagePattern
	Pattern     []MessagePattern
	Name        string
}

HandshakePattern represents the Noise pattern being used.

type Listener

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

Listener is an implementation of a net.Conn which executes an authenticated key exchange and message encryption protocol dubbed "Machine" after initial connection acceptance. See the Machine struct for additional details w.r.t the handshake and encryption scheme used within the connection.

func NewListener

func NewListener(passphrase []byte, localStatic keychain.SingleKeyECDH,
	listenAddr string, authData []byte) (*Listener, error)

NewListener returns a new net.Listener which enforces the Brontide scheme during both initial connection establishment and data transfer.

func (*Listener) Accept

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

Accept waits for and returns the next connection to the listener. All incoming connections are authenticated via the three act Brontide key-exchange scheme. This function will fail with a non-nil error in the case that either the handshake breaks down, or the remote peer doesn't know our static public key.

Part of the net.Listener interface.

func (*Listener) Addr

func (l *Listener) Addr() net.Addr

Addr returns the listener's network address.

Part of the net.Listener interface.

func (*Listener) Close

func (l *Listener) Close() error

Close closes the listener. Any blocked Accept operations will be unblocked and return errors.

Part of the net.Listener interface.

type Machine

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

Machine is a state-machine which implements Brontide: an Authenticated-key Exchange in Three Acts. Brontide is derived from the Noise framework, specifically implementing the Noise_XX handshake with an eke modified, where the public-key masking operation used is SPAKE2. Once the initial 3-act handshake has completed all messages are encrypted with a chacha20 AEAD cipher. On the wire, all messages are prefixed with an authenticated+encrypted length field. Additionally, the encrypted+auth'd length prefix is used as the AD when encrypting+decryption messages. This construction provides confidentiality of packet length, avoids introducing a padding-oracle, and binds the encrypted packet length to the packet itself.

The acts proceeds the following order (initiator on the left):

GenActOne()   ->
                  RecvActOne()
              <-  GenActTwo()
RecvActTwo()
GenActThree() ->
                  RecvActThree()

This exchange corresponds to the following Noise handshake:

-> me
<- e, ee, s, es
-> s, se

In this context, me is the masked ephemeral point that's masked using an operation derived from the traditional SPAKE2 protocol: e + h(pw)*M, where M is a generator of the cyclic group, h is a key derivation function, and pw is the passphraseEntropy known to both sides.

Note that there's also another operating mode based on Noise_IK which can be used after the initial pairing is complete and both sides have exchange long-term public keys.

func NewBrontideMachine

func NewBrontideMachine(cfg *BrontideMachineConfig) (*Machine, error)

NewBrontideMachine creates a new instance of the brontide state-machine.

func (*Machine) DoHandshake

func (b *Machine) DoHandshake(rw io.ReadWriter) error

DoHandshake iterates over the MessagePattern of the Machine and processes it accordingly. After the handshake is complete, `split` is called in order to initialise the send and receive cipher states of the Machine.

func (*Machine) Flush

func (b *Machine) Flush(w io.Writer) (int, error)

Flush attempts to write a message buffered using WriteMessage to the provided io.Writer. If no buffered message exists, this will result in a NOP. Otherwise, it will continue to write the remaining bytes, picking up where the byte stream left off in the event of a partial write. The number of bytes returned reflects the number of plaintext bytes in the payload, and does not account for the overhead of the header or MACs.

NOTE: It is safe to call this method again iff a timeout error is returned.

func (*Machine) ReadBody

func (b *Machine) ReadBody(r io.Reader, buf []byte) ([]byte, error)

ReadBody attempts to ready the next message body from the passed io.Reader. The provided buffer MUST be the length indicated by the packet length returned by the preceding call to ReadHeader. In the case of an authentication eerror, a non-nil error is returned.

func (*Machine) ReadHeader

func (b *Machine) ReadHeader(r io.Reader) (uint32, error)

ReadHeader attempts to read the next message header from the passed io.Reader. The header contains the length of the next body including additional overhead of the MAC. In the case of an authentication error, a non-nil error is returned.

NOTE: This method SHOULD NOT be used in the case that the io.Reader may be adversarial and induce long delays. If the caller needs to set read deadlines appropriately, it is preferred that they use the split ReadHeader and ReadBody methods so that the deadlines can be set appropriately on each.

func (*Machine) ReadMessage

func (b *Machine) ReadMessage(r io.Reader) ([]byte, error)

ReadMessage attempts to read the next message from the passed io.Reader. In the case of an authentication error, a non-nil error is returned.

func (*Machine) WriteMessage

func (b *Machine) WriteMessage(p []byte) error

WriteMessage encrypts and buffers the next message p. The ciphertext of the message is prepended with an encrypt+auth'd length which must be used as the AD to the AEAD construction when being decrypted by the other side.

NOTE: This DOES NOT write the message to the wire, it should be followed by a call to Flush to ensure the message is written.

type MessagePattern

type MessagePattern struct {
	Tokens    []Token
	Initiator bool
	ActNum    ActNum
}

A MessagePattern represents a Token or a stream of Tokens. MessagePatterns are used to make up a HandshakePattern.

type MsgData

type MsgData struct {

	// Payload is the raw HTTP/2 frame data encrypted with the current noise
	// protocol symmetric session key.
	Payload []byte
	// contains filtered or unexported fields
}

MsgData is a message that's being sent between server and client to transport higher-level application data. The payload is encrypted by the current noise protocol symmetric session key that's derived from the from the client's and server's public/private key pairs using ECDH. The payload in this case is HTTP/2 raw frame data.

func NewMsgData

func NewMsgData(version uint8, payload []byte) *MsgData

NewMsgData creates a new MsgData message with the given version and payload.

func (*MsgData) Deserialize

func (m *MsgData) Deserialize(b []byte) error

Deserialize reads the binary wire format representation from the given bytes and deserializes them into the message struct.

NOTE: This is part of the ControlMsg interface.

func (*MsgData) ProtocolVersion

func (m *MsgData) ProtocolVersion() uint8

ProtocolVersion returns the protocol version used with this message.

NOTE: This is part of the ControlMsg interface.

func (*MsgData) Serialize

func (m *MsgData) Serialize() ([]byte, error)

Serialize returns the binary wire format representation of this message.

NOTE: This is part of the ControlMsg interface.

type NoiseAddr

type NoiseAddr struct {
	// PubKey is the EC public key of the noise participant of this address.
	PubKey *btcec.PublicKey

	// Server is the mailbox server this connection is established over.
	Server string
}

NoiseAddr is a type that implements the net.Addr interface for addresses involved in noise encrypted communication over mailbox connections.

func (*NoiseAddr) Network

func (b *NoiseAddr) Network() string

Network returns the network identifier for noise connections which is always 'noise'.

func (*NoiseAddr) String

func (b *NoiseAddr) String() string

String returns a string representation of a noise address.

type NoiseConn

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

NoiseConn is an implementation of net.Conn which enforces an authenticated key exchange and message encryption protocol dubbed "Brontide" after initial TCP connection establishment. In the case of a successful handshake, all messages sent via the .Write() method are encrypted with an AEAD cipher along with an encrypted length-prefix. See the Machine struct for additional details w.r.t to the handshake and encryption scheme.

func Dial

func Dial(localPriv keychain.SingleKeyECDH, netAddr net.Addr, passphrase []byte,
	timeout time.Duration, dialer tor.DialFunc) (*NoiseConn, error)

Dial attempts to establish an encrypted+authenticated connection with the remote peer located at address which has remotePub as its long-term static public key. In the case of a handshake failure, the connection is closed and a non-nil error is returned.

func (*NoiseConn) Close

func (c *NoiseConn) Close() error

Close closes the connection. Any blocked Read or Write operations will be unblocked and return errors.

Part of the net.Conn interface.

func (*NoiseConn) Flush

func (c *NoiseConn) Flush() (int, error)

Flush attempts to write a message buffered using WriteMessage to the underlying connection. If no buffered message exists, this will result in a NOP. Otherwise, it will continue to write the remaining bytes, picking up where the byte stream left off in the event of a partial write. The number of bytes returned reflects the number of plaintext bytes in the payload, and does not account for the overhead of the header or MACs.

NOTE: It is safe to call this method again iff a timeout error is returned.

func (*NoiseConn) LocalAddr

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

LocalAddr returns the local network address.

Part of the net.Conn interface.

func (*NoiseConn) LocalPub

func (c *NoiseConn) LocalPub() *btcec.PublicKey

LocalPub returns the local peer's static public key.

func (*NoiseConn) Read

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

Read reads data from the connection. Read can be made to time out and return an Error with Timeout() == true after a fixed time limit; see SetDeadline and SetReadDeadline.

Part of the net.Conn interface.

func (*NoiseConn) ReadNextBody

func (c *NoiseConn) ReadNextBody(buf []byte) ([]byte, error)

ReadNextBody uses the connection to read the next message body from the brontide stream. This function will block until the read of the body succeeds and return the decrypted payload. The provided buffer MUST be the packet length returned by the preceding call to ReadNextHeader.

func (*NoiseConn) ReadNextHeader

func (c *NoiseConn) ReadNextHeader() (uint32, error)

ReadNextHeader uses the connection to read the next header from the brontide stream. This function will block until the read of the header succeeds and return the packet length (including MAC overhead) that is expected from the subsequent call to ReadNextBody.

func (*NoiseConn) ReadNextMessage

func (c *NoiseConn) ReadNextMessage() ([]byte, error)

ReadNextMessage uses the connection in a message-oriented manner, instructing it to read the next _full_ message with the brontide stream. This function will block until the read of the header and body succeeds.

NOTE: This method SHOULD NOT be used in the case that the connection may be adversarial and induce long delays. If the caller needs to set read deadlines appropriately, it is preferred that they use the split ReadNextHeader and ReadNextBody methods so that the deadlines can be set appropriately on each.

func (*NoiseConn) RemoteAddr

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

RemoteAddr returns the remote network address.

Part of the net.Conn interface.

func (*NoiseConn) RemotePub

func (c *NoiseConn) RemotePub() *btcec.PublicKey

RemotePub returns the remote peer's static public key.

func (*NoiseConn) SetDeadline

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

SetDeadline sets the read and write deadlines associated with the connection. It is equivalent to calling both SetReadDeadline and SetWriteDeadline.

Part of the net.Conn interface.

func (*NoiseConn) SetReadDeadline

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

SetReadDeadline sets the deadline for future Read calls. A zero value for t means Read will not time out.

Part of the net.Conn interface.

func (*NoiseConn) SetWriteDeadline

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

SetWriteDeadline sets the deadline for future Write calls. Even if write times out, it may return n > 0, indicating that some of the data was successfully written. A zero value for t means Write will not time out.

Part of the net.Conn interface.

func (*NoiseConn) Write

func (c *NoiseConn) Write(b []byte) (n int, err error)

Write writes data to the connection. Write can be made to time out and return an Error with Timeout() == true after a fixed time limit; see SetDeadline and SetWriteDeadline.

Part of the net.Conn interface.

func (*NoiseConn) WriteMessage

func (c *NoiseConn) WriteMessage(b []byte) error

WriteMessage encrypts and buffers the next message p for the connection. The ciphertext of the message is prepended with an encrypt+auth'd length which must be used as the AD to the AEAD construction when being decrypted by the other side.

NOTE: This DOES NOT write the message to the wire, it should be followed by a call to Flush to ensure the message is written.

type NoiseGrpcConn

type NoiseGrpcConn struct {
	ProxyConn
	// contains filtered or unexported fields
}

NoiseGrpcConn is a type that implements the credentials.TransportCredentials interface and can therefore be used as a replacement of the default TLS implementation that's used by HTTP/2.

func NewNoiseGrpcConn

func NewNoiseGrpcConn(connData *ConnData,
	options ...func(conn *NoiseGrpcConn)) *NoiseGrpcConn

NewNoiseGrpcConn creates a new noise connection using given local ECDH key. The auth data can be set for server connections and is sent as the payload to the client during the handshake.

func (*NoiseGrpcConn) ClientHandshake

func (c *NoiseGrpcConn) ClientHandshake(_ context.Context, _ string,
	conn net.Conn) (net.Conn, credentials.AuthInfo, error)

ClientHandshake implements the client side part of the noise connection handshake.

NOTE: This is part of the credentials.TransportCredentials interface.

func (*NoiseGrpcConn) Clone

Clone makes a copy of this TransportCredentials.

NOTE: This is part of the credentials.TransportCredentials interface.

func (*NoiseGrpcConn) Close

func (c *NoiseGrpcConn) Close() error

Close ensures that we hold a lock on the ProxyConn before calling close on it to ensure that the handshake functions don't use the ProxyConn at the same time.

NOTE: This is part of the net.Conn interface.

func (*NoiseGrpcConn) GetRequestMetadata

func (c *NoiseGrpcConn) GetRequestMetadata(_ context.Context,
	_ ...string) (map[string]string, error)

GetRequestMetadata returns the per RPC credentials encoded as gRPC metadata.

NOTE: This is part of the credentials.PerRPCCredentials interface.

func (*NoiseGrpcConn) Info

Info returns general information about the protocol that's being used for this connection.

NOTE: This is part of the credentials.TransportCredentials interface.

func (*NoiseGrpcConn) LocalAddr

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

LocalAddr returns the local address of this connection.

NOTE: This is part of the Conn interface.

func (*NoiseGrpcConn) OverrideServerName

func (c *NoiseGrpcConn) OverrideServerName(_ string) error

OverrideServerName overrides the server name used to verify the hostname on the returned certificates from the server.

NOTE: This is part of the credentials.TransportCredentials interface.

func (*NoiseGrpcConn) Read

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

Read tries to read an encrypted data message from the underlying control connection and then tries to decrypt it.

NOTE: This is part of the net.Conn interface.

func (*NoiseGrpcConn) RemoteAddr

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

RemoteAddr returns the remote address of this connection.

NOTE: This is part of the Conn interface.

func (*NoiseGrpcConn) RequireTransportSecurity

func (c *NoiseGrpcConn) RequireTransportSecurity() bool

RequireTransportSecurity returns true if this connection type requires transport security.

NOTE: This is part of the credentials.PerRPCCredentials interface.

func (*NoiseGrpcConn) ServerHandshake

func (c *NoiseGrpcConn) ServerHandshake(conn net.Conn) (net.Conn,
	credentials.AuthInfo, error)

ServerHandshake implements the server part of the noise connection handshake.

NOTE: This is part of the credentials.TransportCredentials interface.

func (*NoiseGrpcConn) Write

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

Write encrypts the given application level payload and sends it as a data message over the underlying control connection.

NOTE: This is part of the net.Conn interface.

type ProxyConn

type ProxyConn interface {
	net.Conn
	// contains filtered or unexported methods
}

ProxyConn is the main interface that any mailbox connection needs to implement.

type Server

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

func NewServer

func NewServer(serverHost string, connData *ConnData,
	onNewStatus func(status ServerStatus),
	dialOpts ...grpc.DialOption) (*Server, error)

func (*Server) Accept

func (s *Server) Accept() (net.Conn, error)

Accept is part of the net.Listener interface. The gRPC server will call this function to get a new net.Conn object to use for communication and it will also call this function each time it returns in order to facilitate multiple concurrent grpc connections. In our use case, we require that only one connection is active at a time. Therefore we block on a select function until the previous mailboxConn has completed.

func (*Server) Addr

func (s *Server) Addr() net.Addr

func (*Server) Close

func (s *Server) Close() error

type ServerConn

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

ServerConn is a type that implements the Conn interface and can be used to serve a gRPC connection over a noise encrypted connection that uses a mailbox connection as its transport connection. The mailbox level connection to the mailbox server uses native gRPC since the "server" in this case is lnd itself that's not running in a restricted environment such as the browser/WASM env.

func NewServerConn

func NewServerConn(ctx context.Context, serverHost string,
	client hashmailrpc.HashMailClient, sid [64]byte,
	onNewStatus func(status ServerStatus)) (*ServerConn, error)

NewServerConn creates a new net.Conn compatible server connection that uses a gRPC based connection to tunnel traffic over a mailbox server.

func RefreshServerConn

func RefreshServerConn(s *ServerConn) (*ServerConn, error)

RefreshServerConn returns the same ServerConn object created in NewServerConn but creates a new quit channel as well as instantiates a new GoBN connection.

func (*ServerConn) Close

func (c *ServerConn) Close() error

Close is part of the net.Conn interface that the grpc library will call after each connection is exiting. Therefore this function is used to cleanup any resources that need to be resent between connections. It closes the the current GoBN connection as well as releases the grpc streams. It does not delete the mailboxes since these will be used by the next connection. The streams, however, must be released so that they can be initialised with the context of the next connection. To completely shut down the ServerConn, Stop should be called.

NOTE: This is part of the net.Conn interface.

func (*ServerConn) Done

func (c *ServerConn) Done() <-chan struct{}

Done returns the quit channel of the ServerConn and thus can be used to determine if the current connection is closed or not.

func (ServerConn) LocalAddr

func (k ServerConn) LocalAddr() net.Addr

LocalAddr returns the address of the local side of this connection.

NOTE: This is part of the net.Conn interface.

func (ServerConn) Read

func (k ServerConn) Read(b []byte) (int, error)

Read reads data from the underlying control connection.

NOTE: This is part of the net.Conn interface.

func (*ServerConn) ReceiveControlMsg

func (c *ServerConn) ReceiveControlMsg(receive ControlMsg) error

ReceiveControlMsg tries to receive a control message over the underlying mailbox connection.

NOTE: This is part of the Conn interface.

func (ServerConn) RemoteAddr

func (k ServerConn) RemoteAddr() net.Addr

RemoteAddr returns the address of the remote side of this connection.

NOTE: This is part of the net.Conn interface.

func (*ServerConn) SendControlMsg

func (c *ServerConn) SendControlMsg(controlMsg ControlMsg) error

SendControlMsg tries to send a control message over the underlying mailbox connection.

NOTE: This is part of the Conn interface.

func (ServerConn) SetDeadline

func (k ServerConn) SetDeadline(t time.Time) error

SetDeadline sets the read and write deadlines associated with the connection. It is equivalent to calling both SetReadDeadline and SetWriteDeadline.

NOTE: This is part of the net.Conn interface.

func (ServerConn) SetReadDeadline

func (k ServerConn) SetReadDeadline(t time.Time) error

SetReadDeadline sets the deadline for future Read calls and any currently-blocked Read call.

NOTE: This is part of the net.Conn interface.

func (*ServerConn) SetRecvTimeout

func (c *ServerConn) SetRecvTimeout(timeout time.Duration)

SetRecvTimeout sets the timeout to be used when attempting to receive data.

func (*ServerConn) SetSendTimeout

func (c *ServerConn) SetSendTimeout(timeout time.Duration)

SetSendTimeout sets the timeout to be used when attempting to send data.

func (ServerConn) SetWriteDeadline

func (k ServerConn) SetWriteDeadline(t time.Time) error

SetWriteDeadline sets the deadline for future Write calls and any currently-blocked Write call.

NOTE: This is part of the net.Conn interface.

func (*ServerConn) Stop

func (c *ServerConn) Stop() error

Stop cleans up all resources of the ServerConn including deleting the mailboxes on the hash-mail server.

func (ServerConn) Write

func (k ServerConn) Write(b []byte) (n int, err error)

Write writes data to the underlying control connection.

NOTE: This is part of the net.Conn interface.

type ServerStatus

type ServerStatus uint8

ServerStatus is a description of the server's session state.

const (
	// ServerStatusNotConnected means that the server is currently not
	// connected to a mailbox. This is either because the session is
	// restarting or because the mailbox server is down.
	ServerStatusNotConnected ServerStatus = 0

	// ServerStatusInUse means that a client is currently connected and
	// using the session.
	ServerStatusInUse ServerStatus = 1

	// ServerStatusIdle means that the session is ready for use but that
	// there is currently no client connected.
	ServerStatusIdle ServerStatus = 2
)

type Token

type Token string

Token represents either a public key that should be transmitted or received from the handshake peer or a DH operation that should be performed. Tokens are used to create MessagePatterns.

Directories

Path Synopsis
numsgen module

Jump to

Keyboard shortcuts

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