Documentation
¶
Overview ¶
Package casket provides Ed25519 + ECDH channel identity for Frame-to-Frame relay.
Each Frame holds two keypairs:
- Ed25519 (signing/verification) — non-repudiation on outer envelope
- ECDH (P-256 or X25519) — derives a shared symmetric key for body encryption
Wire format and JSON shapes are byte-identical to casket-ts/src/channel.ts so a Go Frame and a TS Frame can pair through the interchange and interop byte-for-byte.
Index ¶
- Variables
- func DeriveAgentKey(seed []byte, slug string) (ed25519.PrivateKey, ed25519.PublicKey, error)
- type Channel
- func (c *Channel) DHAlg() DhAlgorithm
- func (c *Channel) DHPublicKeyB64u() string
- func (c *Channel) DHPublicKeyBytes() []byte
- func (c *Channel) GetPaired(ctx context.Context, peerID string) (*PairedChannel, error)
- func (c *Channel) MakePairingToken(endpoint string) PairingToken
- func (c *Channel) Pair(ctx context.Context, token PairingToken, maxAgeSec int64) (*PairedChannel, error)
- func (c *Channel) PublicKeyB64u() string
- func (c *Channel) PublicKeyBytes() []byte
- func (c *Channel) Revoke(ctx context.Context, peerID string) error
- func (c *Channel) Sign(data []byte) ([]byte, error)
- type ChannelStorage
- type DhAlgorithm
- type PairedChannel
- func (p *PairedChannel) DecryptBody(blob, aad []byte) ([]byte, error)
- func (p *PairedChannel) EncryptBody(plaintext, aad []byte) ([]byte, error)
- func (p *PairedChannel) PathID() string
- func (p *PairedChannel) PeerEndpoint() string
- func (p *PairedChannel) PeerID() string
- func (p *PairedChannel) PeerRecord() PeerRecord
- func (p *PairedChannel) Sign(data []byte) ([]byte, error)
- func (p *PairedChannel) Verify(sig, data []byte) error
- type PairingToken
- type PeerRecord
Constants ¶
This section is empty.
Variables ¶
var ( ErrChannelPair = errors.New("channel pair error") ErrChannelVerify = errors.New("channel verify error") ErrChannelDecrypt = errors.New("channel decrypt error") )
Sentinel errors — use errors.Is to test.
Functions ¶
func DeriveAgentKey ¶
DeriveAgentKey derives a deterministic Ed25519 keypair from an owner's identity seed and an agent slug. See package doc for details.
Errors: returns an error if seed is empty or slug is empty.
Types ¶
type Channel ¶
type Channel struct {
// contains filtered or unexported fields
}
Channel is a Frame's local identity. One per Nexus instance. Call Load on every cold start — generates keys on first run, reloads on subsequent runs.
func Load ¶
func Load(ctx context.Context, nexusID string, storage ChannelStorage, dhAlg DhAlgorithm) (*Channel, error)
Load initialises the Channel from storage, generating keys on first run. dhAlg is ignored on reload — the stored algorithm is authoritative.
func (*Channel) DHAlg ¶
func (c *Channel) DHAlg() DhAlgorithm
func (*Channel) DHPublicKeyB64u ¶
func (*Channel) DHPublicKeyBytes ¶
func (*Channel) GetPaired ¶
GetPaired reloads an existing PairedChannel from storage. Returns nil, nil if the peer is not found.
func (*Channel) MakePairingToken ¶
func (c *Channel) MakePairingToken(endpoint string) PairingToken
MakePairingToken builds a PairingToken to exchange OOB with the peer operator.
func (*Channel) Pair ¶
func (c *Channel) Pair(ctx context.Context, token PairingToken, maxAgeSec int64) (*PairedChannel, error)
Pair completes pairing from the peer's PairingToken. Derives the shared AEAD key via ECDH and stores the peer record. Returns ErrChannelPair if the token is stale, malformed, or uses a mismatched algorithm.
func (*Channel) PublicKeyB64u ¶
func (*Channel) PublicKeyBytes ¶
type ChannelStorage ¶
type ChannelStorage interface {
Get(ctx context.Context, key string) (string, error)
Put(ctx context.Context, key, value string) error
Delete(ctx context.Context, key string) error
}
ChannelStorage is the persistence interface injected into a Channel. Returning ("", nil) from Get signals key-not-found.
type DhAlgorithm ¶
type DhAlgorithm string
DhAlgorithm is the ECDH curve used for key exchange.
const ( P256 DhAlgorithm = "P-256" X25519 DhAlgorithm = "X25519" )
type PairedChannel ¶
type PairedChannel struct {
// contains filtered or unexported fields
}
PairedChannel is an active channel to a specific peer. Obtained from Channel.Pair or Channel.GetPaired.
func (*PairedChannel) DecryptBody ¶
func (p *PairedChannel) DecryptBody(blob, aad []byte) ([]byte, error)
DecryptBody decrypts a blob produced by EncryptBody. blob layout: nonce (12 bytes) || ciphertext+GCM-tag. Returns ErrChannelDecrypt if authentication fails or blob is too short.
func (*PairedChannel) EncryptBody ¶
func (p *PairedChannel) EncryptBody(plaintext, aad []byte) ([]byte, error)
EncryptBody encrypts the message body (inner layer) with AES-256-GCM. Returns nonce (12 bytes) || ciphertext+GCM-tag as raw bytes. aad is optional additional authenticated data. Output format matches casket-ts encryptBody exactly.
func (*PairedChannel) PathID ¶
func (p *PairedChannel) PathID() string
func (*PairedChannel) PeerEndpoint ¶
func (p *PairedChannel) PeerEndpoint() string
func (*PairedChannel) PeerID ¶
func (p *PairedChannel) PeerID() string
func (*PairedChannel) PeerRecord ¶
func (p *PairedChannel) PeerRecord() PeerRecord
func (*PairedChannel) Sign ¶
func (p *PairedChannel) Sign(data []byte) ([]byte, error)
Sign signs arbitrary bytes for the outer envelope using the local Ed25519 key. Returns the raw 64-byte signature.
func (*PairedChannel) Verify ¶
func (p *PairedChannel) Verify(sig, data []byte) error
Verify verifies a signature from the peer. Returns ErrChannelVerify if the signature is invalid.
type PairingToken ¶
type PairingToken struct {
V int `json:"v"` // always 1
NexusID string `json:"nexus_id"`
SigAlg string `json:"sig_alg"` // always "ed25519"
DhAlg DhAlgorithm `json:"dh_alg"`
Pubkey string `json:"pubkey"` // base64url Ed25519 public key (32 bytes)
DhPubkey string `json:"dh_pubkey"` // base64url ECDH public key (65 bytes P-256 / 32 bytes X25519)
Endpoint string `json:"endpoint"` // https URL of the relay endpoint
Nonce string `json:"nonce"` // base64url 16 random bytes
Ts int64 `json:"ts"` // unix seconds
}
PairingToken is exchanged out-of-band between two Frame operators to initiate pairing. JSON field names match casket-ts exactly for wire compatibility.
type PeerRecord ¶
type PeerRecord struct {
NexusID string `json:"nexus_id"`
Pubkey string `json:"pubkey"`
DhAlg DhAlgorithm `json:"dh_alg"`
DhPubkey string `json:"dh_pubkey"`
Endpoint string `json:"endpoint"`
PathID string `json:"path_id"`
PairedAt int64 `json:"paired_at"`
}
PeerRecord is stored in ChannelStorage for each paired peer.