overenc

package
v0.2.4 Latest Latest
Warning

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

Go to latest
Published: Aug 23, 2026 License: AGPL-3.0 Imports: 13 Imported by: 0

Documentation

Overview

Package overenc implements the c8s-verify post-quantum over-encryption channel that terminates inside the Load Balancer's TEE. This package's key schedule is the canonical contract (pinned by TestChannelKeyGoldenVector); the c8s-verify-js client and its PROTOCOL.md follow it.

Hybrid KEM = X25519 (crypto/ecdh) + ML-KEM-768 (crypto/mlkem), combined per the TLS X25519MLKEM768 convention, run through HKDF-SHA256 to an AES-256-GCM key. The classical and post-quantum shared secrets are concatenated so the channel stays secure as long as EITHER primitive holds.

Index

Constants

View Source
const (

	// X25519PubBytes is the raw X25519 public key length.
	X25519PubBytes = 32
	// MLKEM768EKBytes is the ML-KEM-768 encapsulation (public) key length.
	MLKEM768EKBytes = 1184
	// MLKEM768CTBytes is the ML-KEM-768 ciphertext length.
	MLKEM768CTBytes = 1088
)

Variables

View Source
var (
	// ErrInvalidIV: the record's IV is not the AES-GCM nonce size.
	ErrInvalidIV = fmt.Errorf("overenc: IV must be %d bytes", ivBytes)
	// ErrAuthenticationFailed: the record failed AEAD authentication (wrong
	// key, tampered ciphertext, or wrong AAD).
	ErrAuthenticationFailed = errors.New("overenc: authentication failed")
	// ErrReplayedRecord: this channel already opened a record with this IV.
	ErrReplayedRecord = errors.New("overenc: replayed record rejected")
	// ErrRecordLimit: the anti-replay set is full; re-establish the session.
	ErrRecordLimit = errors.New("overenc: channel record limit reached; re-establish the session")
)

Sentinel errors for Channel.Open's rejection paths, matchable via errors.Is.

Functions

func ClientAgree

func ClientAgree(pub PublicKey, transcriptHash []byte) (*Channel, Handshake, error)

ClientAgree is the client side, provided for Go clients and interop tests: encapsulate against the LB's hybrid public key and derive the same channel from the verified identity transcript.

func IdentityTranscriptHash

func IdentityTranscriptHash(pub PublicKey, nonce, leafDER, caDER []byte) ([]byte, error)

IdentityTranscriptHash commits the hybrid server key, client nonce, exact mesh leaf, and issuing mesh CA to one SHA-384 value suitable for TEE report_data. Every variable-length field is length-prefixed to make the transcript unambiguous across the Go and browser implementations.

func LBTranscriptHash

func LBTranscriptHash(nonce, servingLeafDER, meshLeafDER, caDER []byte) ([]byte, error)

LBTranscriptHash commits the client nonce, exact outer serving leaf, exact mesh leaf, and issuing mesh CA to one SHA-384 value suitable for TEE report_data — the attest-lb binding for clients that ride ordinary nginx TLS:

SHA-384( LP("c8s/attest-lb/v1") || LP(nonce) ||
         LP(SHA-256(serving_leaf_DER)) || LP(SHA-256(mesh_leaf_DER)) ||
         LP(SHA-256(mesh_CA_DER)) )

A client recomputes it from the exact leaf it observed on the connection being authorized, so a response relayed through a different serving leaf fails even when both leaves share an issuer.

func RequestAAD

func RequestAAD() []byte

RequestAAD is the additional-authenticated-data domain separator for request records. The method and path are sealed inside the request envelope, so the AAD is a fixed tag rather than per-route.

func ResponseAAD

func ResponseAAD() []byte

ResponseAAD is the AAD domain separator for response records.

Types

type Channel

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

Channel is a symmetric over-encryption channel; both ends hold an identical key.

func (*Channel) Open

func (c *Channel) Open(rec Record, aad []byte) ([]byte, error)

Open decrypts and authenticates a record, rejecting any record whose IV this channel has already opened (exact-record replay).

func (*Channel) Seal

func (c *Channel) Seal(plaintext, aad []byte) (Record, error)

Seal encrypts plaintext with a fresh random IV.

type Handshake

type Handshake struct {
	ClientX25519    []byte // 32 bytes
	MLKEMCiphertext []byte // 1088 bytes
}

Handshake is what the client sends to the LB to establish the channel.

type PublicKey

type PublicKey struct {
	X25519   []byte // 32 bytes
	MLKEM768 []byte // 1184 bytes
}

PublicKey is the LB's per-session hybrid public key, published in the attestation bundle and bound into the hardware report_data.

type Record

type Record struct {
	IV []byte `cbor:"iv" json:"iv"`
	CT []byte `cbor:"ct" json:"ct"`
}

Record is one AES-256-GCM record on the wire. Both fields are raw bytes, carried as CBOR byte strings by the tunnel transport — no base64 inflation.

type ServerKey

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

ServerKey holds the LB-side private halves of a per-session hybrid keypair. The private material never leaves the process.

func GenerateServerKey

func GenerateServerKey() (*ServerKey, error)

GenerateServerKey creates a fresh hybrid keypair for one client session.

func (*ServerKey) Agree

func (s *ServerKey) Agree(hs Handshake, transcriptHash []byte) (*Channel, error)

Agree completes the handshake on the LB side: decapsulate the client's ML-KEM ciphertext, ECDH against the client's X25519 key, and derive the AES-256-GCM channel keyed to the identity transcript. transcriptHash is the SHA-384 value committed to report_data and verified by the client.

func (*ServerKey) Public

func (s *ServerKey) Public() PublicKey

Public returns the raw public halves to publish.

Jump to

Keyboard shortcuts

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