Documentation
¶
Overview ¶
Package securetransport implements the versioned binary protocol shared by the fh secure-transport middleware and its Go WebAssembly fetch client.
The protocol is an application-layer security envelope. It is deliberately independent of fh and net/http so it can be reused by browsers, native clients, gateways, and tests without introducing an HTTP implementation.
Index ¶
- Constants
- Variables
- func DecryptRequest(key [32]byte, method, target string, data []byte, limits Limits) (RequestEnvelope, RequestPayload, error)
- func DecryptResponse(key [32]byte, outerStatus int, data []byte, limits Limits) (ResponseEnvelope, ResponsePayload, error)
- func EncodeID(id ID16) string
- func EncryptRequest(key [32]byte, method, target string, env RequestEnvelope, ...) ([]byte, error)
- func EncryptResponse(key [32]byte, outerStatus int, env ResponseEnvelope, payload ResponsePayload, ...) ([]byte, error)
- func EqualID(a, b ID16) bool
- func FingerprintPublicKey(key []byte) string
- func FormatError(err error) error
- func NewAEADNonce() ([12]byte, error)
- func NewNonce16() ([16]byte, error)
- func ServerProof(key [32]byte, clientHello, serverCore []byte) [32]byte
- func ValidProtectedHeader(name, value string) bool
- func ValidateTime(issuedAt, expiresAt int64, now time.Time, maxClockSkew time.Duration) error
- func VerifyServerProof(key [32]byte, clientHello, serverCore []byte, proof [32]byte) bool
- type ClientHello
- type DeviceRegistrationRequest
- type DeviceRegistrationResponse
- type Header
- type ID16
- type Limits
- type RequestEnvelope
- type RequestPayload
- type ResponseEnvelope
- type ResponsePayload
- type ServerHello
- type SessionKeys
- type TrustBundle
Constants ¶
const ( Version = byte(1) MediaTypeRequest = "application/fh-secure" MediaTypeHandshake = "application/fh-secure-handshake" HeaderSecure = "X-FH-Secure" HeaderEnvelope = "X-FH-Envelope" HeaderResponse = "X-FH-Response" HeaderServerKey = "X-FH-Server-Key" HeaderDeviceRegistration = "X-FH-Device-Registration" DeviceIDSize = 16 SessionIDSize = 16 RequestIDSize = 16 RandomNonceSize = 16 AEADNonceSize = 12 X25519KeySize = 32 Ed25519PublicSize = 32 Ed25519SignatureSize = 64 ProofSize = 32 DefaultMaxBody = 16 << 20 DefaultMaxHeaders = 48 DefaultMaxHeaderName = 128 DefaultMaxHeaderValue = 16 << 10 )
Variables ¶
var ( ErrMalformed = errors.New("fh secure transport: malformed message") ErrUnsupported = errors.New("fh secure transport: unsupported protocol version") ErrAuthentication = errors.New("fh secure transport: authentication failed") ErrExpired = errors.New("fh secure transport: message expired") ErrTooLarge = errors.New("fh secure transport: message exceeds configured limit") )
Functions ¶
func DecryptRequest ¶
func DecryptRequest(key [32]byte, method, target string, data []byte, limits Limits) (RequestEnvelope, RequestPayload, error)
func DecryptResponse ¶
func DecryptResponse(key [32]byte, outerStatus int, data []byte, limits Limits) (ResponseEnvelope, ResponsePayload, error)
func EncryptRequest ¶
func EncryptRequest(key [32]byte, method, target string, env RequestEnvelope, payload RequestPayload, limits Limits) ([]byte, error)
func EncryptResponse ¶
func EncryptResponse(key [32]byte, outerStatus int, env ResponseEnvelope, payload ResponsePayload, limits Limits) ([]byte, error)
func FingerprintPublicKey ¶
func FormatError ¶
func NewAEADNonce ¶
func NewNonce16 ¶
func ServerProof ¶
func ValidProtectedHeader ¶
ValidProtectedHeader rejects hop-by-hop, framing, browser security-envelope, and host headers. These values must never be restored from encrypted client input because doing so would permit request smuggling or protocol confusion.
func ValidateTime ¶
Types ¶
type ClientHello ¶
type ClientHello struct {
DeviceID ID16
ClientPublic [32]byte
IssuedAt int64
ExpiresAt int64
Nonce [16]byte
ClientBuild string
Signature [64]byte
}
func DecodeClientHello ¶
func DecodeClientHello(data []byte) (ClientHello, error)
func (ClientHello) Encode ¶
func (m ClientHello) Encode() ([]byte, error)
func (ClientHello) SigningBytes ¶
func (m ClientHello) SigningBytes() ([]byte, error)
type DeviceRegistrationRequest ¶
type DeviceRegistrationRequest struct {
IssuedAt int64
Nonce [16]byte
PublicKey [32]byte
Name string
}
DeviceRegistrationRequest registers a per-installation signing public key. Registration authorization belongs to the application and is enforced by the middleware's AuthorizeDeviceRegistration callback.
func DecodeDeviceRegistrationRequest ¶
func DecodeDeviceRegistrationRequest(data []byte) (DeviceRegistrationRequest, error)
func (DeviceRegistrationRequest) Encode ¶
func (m DeviceRegistrationRequest) Encode() ([]byte, error)
type DeviceRegistrationResponse ¶
func DecodeDeviceRegistrationResponse ¶
func DecodeDeviceRegistrationResponse(data []byte) (DeviceRegistrationResponse, error)
func (DeviceRegistrationResponse) Encode ¶
func (m DeviceRegistrationResponse) Encode() ([]byte, error)
type RequestEnvelope ¶
type RequestEnvelope struct {
SessionID ID16
RequestID ID16
Sequence uint64
IssuedAt int64
ExpiresAt int64
Nonce [12]byte
Ciphertext []byte
}
func DecodeRequestEnvelope ¶
func DecodeRequestEnvelope(data []byte, maxCiphertext int) (RequestEnvelope, error)
func (RequestEnvelope) Encode ¶
func (m RequestEnvelope) Encode() ([]byte, error)
type RequestPayload ¶
type ResponseEnvelope ¶
type ResponseEnvelope struct {
SessionID ID16
RequestID ID16
Sequence uint64
IssuedAt int64
ExpiresAt int64
Nonce [12]byte
Ciphertext []byte
}
func DecodeResponseEnvelope ¶
func DecodeResponseEnvelope(data []byte, maxCiphertext int) (ResponseEnvelope, error)
func (ResponseEnvelope) Encode ¶
func (m ResponseEnvelope) Encode() ([]byte, error)
type ResponsePayload ¶
type ServerHello ¶
type ServerHello struct {
// ServerPublic is the persistent pinned X25519 public key.
ServerPublic [32]byte
// ServerEphemeral is a per-session X25519 public key. Combining both
// agreements gives server authentication through the pin and forward secrecy
// after the ephemeral private key is discarded.
ServerEphemeral [32]byte
SessionID ID16
ServerNonce [16]byte
ExpiresAt int64
KeyID string
Proof [32]byte
}
func DecodeServerHello ¶
func DecodeServerHello(data []byte) (ServerHello, error)
func (ServerHello) CoreBytes ¶
func (m ServerHello) CoreBytes() ([]byte, error)
func (ServerHello) Encode ¶
func (m ServerHello) Encode() ([]byte, error)
type SessionKeys ¶
func DeriveSessionKeys ¶
func DeriveSessionKeys(sharedSecret, clientHello, serverCore []byte) SessionKeys
type TrustBundle ¶
type TrustBundle struct {
Origin string
TransportPublicKey [X25519KeySize]byte
TransportKeyID string
ResponseSigningPublicKey [Ed25519PublicSize]byte
ResponseSigningKeyID string
}
TrustBundle is an immutable client root of trust intended to be embedded in a signed application or WASM build. It contains public material only.
func ParseTrustBundle ¶
func ParseTrustBundle(origin, transportPublicKey, transportKeyID, responseSigningPublicKey, responseSigningKeyID string) (TrustBundle, error)
ParseTrustBundle validates build-injected trust values. Either every value must be present or every value must be empty; partial bundles fail closed.
func (TrustBundle) Matches ¶
func (b TrustBundle) Matches(origin string, transportPublicKey [X25519KeySize]byte, transportKeyID string, responseSigningPublicKey [Ed25519PublicSize]byte, responseSigningKeyID string) bool
Matches reports whether runtime configuration exactly matches the embedded bundle. It uses constant-time comparisons for keys and key identifiers.