Documentation ¶
Overview ¶
Package handshake implements the basket2 obfuscated/authenticated key exchange.
Index ¶
Constants ¶
const ( // HandshakeVersion is the current handshake version. HandshakeVersion = 1 // KEXInvalid is a invalid/undefined KEX method. KEXInvalid KEXMethod = 0xff // MessageSize is the length that all handshake messages get padded to, // without including user extData or padding (2146 bytes). MessageSize = x448NHRespSize + obfsServerOverhead // MinHandshakeSize is the minimum total handshake length. MinHandshakeSize = 4096 // MaxHandshakeSize is the maximum total handshake length. MaxHandshakeSize = 8192 // IdentityCurve is the curve used for server identities. IdentityCurve = ecdh.X25519 )
Variables ¶
var ( // ErrInvalidKEXMethod is the error returned when the handshake KEX method // is invalid/unsupported. ErrInvalidKEXMethod = errors.New("handshake: invalid KEX method") // ErrInvalidPayload is the error returned when the handshake message // is malformed. ErrInvalidPayload = errors.New("handshake: invalid payload") )
var ( // ErrInvalidCmd is the error returned on a invalid obfuscated handshake // payload command. ErrInvalidCmd = errors.New("obfs: invalid command") // ErrInvalidMAC is the error returned when the client mac is invalid. ErrInvalidMAC = errors.New("obfs: client send invalid MAC") // ErrReplay is the error returned when the client appears to be replaying // a previously seen handshake. ErrReplay = errors.New("obfs: client sent replayed handshake") // ErrNoPayload is the error returned when the obfuscated handshake // contains no payload. ErrNoPayload = errors.New("obfs: no handshake paylaod") )
Functions ¶
This section is empty.
Types ¶
type ClientHandshake ¶
type ClientHandshake struct {
// contains filtered or unexported fields
}
ClientHandshake is the client handshake state.
func NewClientHandshake ¶
func NewClientHandshake(rand io.Reader, kexMethod KEXMethod, serverPublicKey ecdh.PublicKey) (*ClientHandshake, error)
NewClientHandshake creates a new ClientHandshake instance suitable for a single handshake with a provided peer identified by a public key.
Note: Due to the rejection sampling in Elligator 2 keypair generation, this should be done offline. The timing variation only leaks information about the obfuscation method, and does not compromise secrecy or integrity.
func (*ClientHandshake) Handshake ¶
func (c *ClientHandshake) Handshake(rw io.ReadWriter, extData []byte, padLen int) (*SessionKeys, []byte, error)
Handshake completes the client side of the handshake, and returns the dervied session keys, and whatever extended data the server sent as part of it's handshake response. Callers are responsible for setting timeouts as appropriate. Upon return, Reset will be called automatically.
Note: Both the client and server's extData is encrypted and authenticated, however there is no Perfect Forward Secrecy due to the use of ephemeral/static ECDH. Suitable care must be taken in what is sent as extData. The session keys derived from the handshake DO have PFS.
func (*ClientHandshake) Reset ¶
func (c *ClientHandshake) Reset()
Reset clears a ClientHandshake instance such that senstive material no longer appears in memory.
type KEXMethod ¶
type KEXMethod byte
KEXMethod is a supported/known handshake key exchange primitive set approximately analagous to a TLS ciphersuite.
func KEXMethodFromString ¶
KEXMethodFromString returns the KEXMethod corresponding to a given string.
func SupportedKEXMethods ¶
func SupportedKEXMethods() []KEXMethod
SupportedKEXMethods returns the list of supported KEX methods in order of preference.
func (KEXMethod) ToHexString ¶
ToHexString returns the hexdecimal string representation of a KEX method.
type ReplayFilter ¶
type ReplayFilter interface { // TestAndSet adds the provided byte slice to the replay filter, and // returns true iff it was already present. The implementation MUST // be thread safe. TestAndSet([]byte) bool }
ReplayFilter is the replay filter interface.
func NewLargeReplayFilter ¶
func NewLargeReplayFilter() (ReplayFilter, error)
NewLargeReplayFilter creates a new high capacity replay filter suitable for extremely busy servers. It is backed by an active-active bloom filter, and thus has false positives, though the rate is low enough that such occurences should be relatively rare.
func NewSmallReplayFilter ¶
func NewSmallReplayFilter() (ReplayFilter, error)
NewSmallReplayFilter creates a new "small" capacity replay filter. It is backed by a map, and has no false positives, but will reject connections if the filter ever fills up (10k entries) till space is made by older entries expiring.
type ServerHandshake ¶
type ServerHandshake struct {
// contains filtered or unexported fields
}
ServerHandshake is the server handshake state.
func NewServerHandshake ¶
func NewServerHandshake(rand io.Reader, kexMethods []KEXMethod, replay ReplayFilter, serverPrivateKey ecdh.PrivateKey) (*ServerHandshake, error)
NewServerHandshake creates a new ServerHandshake instance suitable for a single handshake to the provided peer identified by a private key.
func (*ServerHandshake) RecvHandshakeReq ¶
func (s *ServerHandshake) RecvHandshakeReq(r io.Reader) ([]byte, error)
RecvHandshakeReq receives and validates the client's handshake request and returns the client's extData if any. Callers are responsible for setting timeouts as appropriate.
func (*ServerHandshake) Reset ¶
func (s *ServerHandshake) Reset()
Reset clears a ServerHandshake instance such that sensitive material no longer appears in memory.
func (*ServerHandshake) SendHandshakeResp ¶
func (s *ServerHandshake) SendHandshakeResp(w io.Writer, extData []byte, padLen int) (*SessionKeys, error)
SendHandshakeResp sends the handshake response, any extData if neccecary, and derives the session keys. Like with ClientHandshake.Handshake, the extData is encrypted/authenticated without PFS. Callers are responsible for setting timeouts as appropriate. Upon return, Reset will be called automatically.
type SessionKeys ¶
type SessionKeys struct { // KDF is the key derivation function initialized with handshake output. KDF io.Reader // TranscriptDigest is the 32 byte handshake transcript digest, the tweaked // SHA3-256 hash of every single bit sent on the network for the handshake. // Both the client and server will have matching values, unless active // attackers are doing evil. TranscriptDigest []byte }
SessionKeys is the handshake output. It is safe to assume contributatory behavior from both parties in the KDF output and the handshake transcript digest, as points of small order are explicitly rejected.
func (*SessionKeys) Reset ¶
func (k *SessionKeys) Reset()
Reset clears a SessionKeys instance such that no sensitive values appear in memory.