Documentation ¶
Index ¶
- Constants
- Variables
- func GetSID(sid [64]byte, serverToClient bool) [64]byte
- func NewClientWebsocketConn(mailboxServer, pairingPhrase string, localStatic keychain.SingleKeyECDH, ...) (func() ClientStatus, func() (*grpc.ClientConn, error), error)
- func NewPassphraseEntropy() ([NumPassphraseWords]string, [NumPassphraseEntropyBytes]byte, error)
- func PassphraseEntropyToMnemonic(entropy [NumPassphraseEntropyBytes]byte) ([NumPassphraseWords]string, error)
- func PassphraseMnemonicToEntropy(passphrase [NumPassphraseWords]string) [NumPassphraseEntropyBytes]byte
- func UseLogger(logger btclog.Logger)
- func WithMaxHandshakeVersion(version byte) func(*NoiseGrpcConn)
- func WithMinHandshakeVersion(version byte) func(*NoiseGrpcConn)
- type ActNum
- type Addr
- type AuthInfo
- type BrontideMachineConfig
- type Client
- type ClientConn
- func (c *ClientConn) Close() error
- func (c *ClientConn) Done() <-chan struct{}
- func (k ClientConn) LocalAddr() net.Addr
- func (k ClientConn) Read(b []byte) (int, error)
- func (c *ClientConn) ReceiveControlMsg(receive ControlMsg) error
- func (k ClientConn) RemoteAddr() net.Addr
- func (c *ClientConn) SendControlMsg(controlMsg ControlMsg) error
- func (k ClientConn) SetDeadline(t time.Time) error
- func (k ClientConn) SetReadDeadline(t time.Time) error
- func (c *ClientConn) SetRecvTimeout(timeout time.Duration)
- func (c *ClientConn) SetSendTimeout(timeout time.Duration)
- func (k ClientConn) SetWriteDeadline(t time.Time) error
- func (k ClientConn) Write(b []byte) (n int, err error)
- type ClientConnTransport
- type ClientStatus
- type ConnData
- func (s *ConnData) AuthData() []byte
- func (s *ConnData) HandshakePattern() HandshakePattern
- func (s *ConnData) LocalKey() keychain.SingleKeyECDH
- func (s *ConnData) PassphraseEntropy() []byte
- func (s *ConnData) RemoteKey() *btcec.PublicKey
- func (s *ConnData) SID() ([64]byte, error)
- func (s *ConnData) SetAuthData(data []byte) error
- func (s *ConnData) SetRemote(key *btcec.PublicKey) error
- type ConnectionData
- type ControlMsg
- type GrpcLogLogger
- func (l GrpcLogLogger) Errorln(args ...interface{})
- func (l GrpcLogLogger) Fatal(args ...interface{})
- func (l GrpcLogLogger) Fatalf(format string, args ...interface{})
- func (l GrpcLogLogger) Fatalln(args ...interface{})
- func (l GrpcLogLogger) Info(args ...interface{})
- func (l GrpcLogLogger) Infof(format string, args ...interface{})
- func (l GrpcLogLogger) Infoln(args ...interface{})
- func (l GrpcLogLogger) V(level int) bool
- func (l GrpcLogLogger) Warning(args ...interface{})
- func (l GrpcLogLogger) Warningf(format string, args ...interface{})
- func (l GrpcLogLogger) Warningln(args ...interface{})
- type HandshakePattern
- type Listener
- type Machine
- func (b *Machine) DoHandshake(rw io.ReadWriter) error
- func (b *Machine) Flush(w io.Writer) (int, error)
- func (b *Machine) ReadBody(r io.Reader, buf []byte) ([]byte, error)
- func (b *Machine) ReadHeader(r io.Reader) (uint32, error)
- func (b *Machine) ReadMessage(r io.Reader) ([]byte, error)
- func (b *Machine) WriteMessage(p []byte) error
- type MessagePattern
- type MsgData
- type NoiseAddr
- type NoiseConn
- func (c *NoiseConn) Close() error
- func (c *NoiseConn) Flush() (int, error)
- func (c *NoiseConn) LocalAddr() net.Addr
- func (c *NoiseConn) LocalPub() *btcec.PublicKey
- func (c *NoiseConn) Read(b []byte) (n int, err error)
- func (c *NoiseConn) ReadNextBody(buf []byte) ([]byte, error)
- func (c *NoiseConn) ReadNextHeader() (uint32, error)
- func (c *NoiseConn) ReadNextMessage() ([]byte, error)
- func (c *NoiseConn) RemoteAddr() net.Addr
- func (c *NoiseConn) RemotePub() *btcec.PublicKey
- func (c *NoiseConn) SetDeadline(t time.Time) error
- func (c *NoiseConn) SetReadDeadline(t time.Time) error
- func (c *NoiseConn) SetWriteDeadline(t time.Time) error
- func (c *NoiseConn) Write(b []byte) (n int, err error)
- func (c *NoiseConn) WriteMessage(b []byte) error
- type NoiseGrpcConn
- func (c *NoiseGrpcConn) ClientHandshake(_ context.Context, _ string, conn net.Conn) (net.Conn, credentials.AuthInfo, error)
- func (c *NoiseGrpcConn) Clone() credentials.TransportCredentials
- func (c *NoiseGrpcConn) Close() error
- func (c *NoiseGrpcConn) GetRequestMetadata(_ context.Context, _ ...string) (map[string]string, error)
- func (c *NoiseGrpcConn) Info() credentials.ProtocolInfo
- func (c *NoiseGrpcConn) LocalAddr() net.Addr
- func (c *NoiseGrpcConn) OverrideServerName(_ string) error
- func (c *NoiseGrpcConn) Read(b []byte) (n int, err error)
- func (c *NoiseGrpcConn) RemoteAddr() net.Addr
- func (c *NoiseGrpcConn) RequireTransportSecurity() bool
- func (c *NoiseGrpcConn) ServerHandshake(conn net.Conn) (net.Conn, credentials.AuthInfo, error)
- func (c *NoiseGrpcConn) Write(b []byte) (int, error)
- type ProxyConn
- type Server
- type ServerConn
- func (c *ServerConn) Close() error
- func (c *ServerConn) Done() <-chan struct{}
- func (k ServerConn) LocalAddr() net.Addr
- func (k ServerConn) Read(b []byte) (int, error)
- func (c *ServerConn) ReceiveControlMsg(receive ControlMsg) error
- func (k ServerConn) RemoteAddr() net.Addr
- func (c *ServerConn) SendControlMsg(controlMsg ControlMsg) error
- func (k ServerConn) SetDeadline(t time.Time) error
- func (k ServerConn) SetReadDeadline(t time.Time) error
- func (c *ServerConn) SetRecvTimeout(timeout time.Duration)
- func (c *ServerConn) SetSendTimeout(timeout time.Duration)
- func (k ServerConn) SetWriteDeadline(t time.Time) error
- func (c *ServerConn) Stop() error
- func (k ServerConn) Write(b []byte) (n int, err error)
- type ServerStatus
- type Token
Constants ¶
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 )
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 )
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 )
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" )
const Subsystem = "MBOX"
Variables ¶
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) )
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 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 ¶
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.
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.
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.
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 ¶
LocalAddr returns the address of the local side of this connection.
NOTE: This is part of the net.Conn interface.
func (ClientConn) Read ¶
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 ¶
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 ¶
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 ¶
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 ¶
SetWriteDeadline sets the deadline for future Write calls and any currently-blocked Write call.
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 ¶
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 ¶
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 ¶
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 ¶
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.
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 ¶
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 ¶
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.
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
NewMsgData creates a new MsgData message with the given version and payload.
func (*MsgData) Deserialize ¶
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 ¶
ProtocolVersion returns the protocol version used with 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.
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
func (c *NoiseGrpcConn) Clone() credentials.TransportCredentials
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 ¶
func (c *NoiseGrpcConn) Info() credentials.ProtocolInfo
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.
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 ¶
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.
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 ¶
LocalAddr returns the address of the local side of this connection.
NOTE: This is part of the net.Conn interface.
func (ServerConn) Read ¶
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 ¶
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 ¶
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 ¶
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 ¶
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.
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 )