crypto

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Apr 20, 2026 License: MPL-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package crypto — AEAD layer. Auto-selects ChaCha20-Poly1305 or AES-256-GCM based on CPU capabilities.

Package crypto — CPU capability detection used by AEAD auto-selection.

Package crypto — HKDF-based key derivation utilities. All session keys are derived from the hybrid shared secret using HKDF-SHA256 with domain-separated labels.

Package crypto implements the HiVoid hybrid cryptographic layer. It combines classical X25519 Diffie-Hellman with post-quantum ML-KEM-768 (from the Go standard library's crypto/mlkem, NIST FIPS 203) to provide security against both classical and quantum adversaries. This protects against "harvest now, decrypt later" attacks.

Index

Constants

View Source
const (
	// LabelSessionKey is used to derive the AEAD session encryption key.
	LabelSessionKey = "hivoid-session-key"
	// LabelSessionIV is used to derive the initial nonce/IV.
	LabelSessionIV = "hivoid-session-iv"
	// LabelRekeyKey is used during key rotation.
	LabelRekeyKey = "hivoid-rekey-key"
	// LabelRekeyIV is used during key rotation for the new IV.
	LabelRekeyIV = "hivoid-rekey-iv"
)
View Source
const (
	MLKEMEncapKeySize   = 1184 // encapsulation (public) key bytes
	MLKEMCiphertextSize = 1088 // ciphertext bytes
)

ML-KEM-768 fixed sizes (NIST FIPS 203).

Variables

This section is empty.

Functions

func Fingerprint

func Fingerprint(pubKey []byte) string

Fingerprint returns a 4-byte hex fingerprint of a public key for logging.

func GenerateKeyPair

func GenerateKeyPair() (*HybridPrivateKey, *HybridPublicKey, error)

GenerateKeyPair generates a new X25519 + ML-KEM-768 keypair for the initiator. The returned public key is sent to the responder (server) in the ClientHello.

func HasAESNI

func HasAESNI() bool

HasAESNI reports whether the current CPU supports hardware AES instruction acceleration (Intel AES-NI or ARM Cryptography Extensions). When true, AES-256-GCM is preferred. Otherwise, ChaCha20-Poly1305 is used.

func IncrementNonce

func IncrementNonce(nonce []byte)

IncrementNonce increments a big-endian nonce by 1. This is used for stream-based nonce management (per-record counter).

func RandomBytes

func RandomBytes(n int) ([]byte, error)

RandomBytes generates n cryptographically secure random bytes.

func ValidateKeyPair

func ValidateKeyPair(clientPriv *HybridPrivateKey, clientPub *HybridPublicKey) error

ValidateKeyPair performs a full round-trip test to verify correctness. Used in unit tests; not for production code paths.

func Zeroize

func Zeroize(b []byte)

Zeroize securely wipes a byte slice to prevent secret leakage in memory.

func ZeroizeDerivedKeys

func ZeroizeDerivedKeys(dk *DerivedKeys)

ZeroizeDerivedKeys securely wipes all key material.

Types

type AEAD

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

AEAD wraps a cipher.AEAD with metadata about its suite and key.

func NewAEAD

func NewAEAD(key []byte) (*AEAD, error)

NewAEAD creates an AEAD instance. It auto-selects the cipher suite based on CPU hardware acceleration (detected via HasAESNI). The key must be exactly KeySize() bytes.

func NewAEADWithSuite

func NewAEADWithSuite(suite CipherSuite, key []byte) (*AEAD, error)

NewAEADWithSuite creates an AEAD with an explicitly chosen cipher suite.

func (*AEAD) KeySize

func (a *AEAD) KeySize() int

KeySize returns the required key length in bytes.

func (*AEAD) NonceSize

func (a *AEAD) NonceSize() int

NonceSize returns the required nonce length for this AEAD.

func (*AEAD) Open

func (a *AEAD) Open(nonce, ciphertext, additionalData []byte) ([]byte, error)

Open decrypts and verifies ciphertext. Returns plaintext on success.

func (*AEAD) Overhead

func (a *AEAD) Overhead() int

Overhead returns the authentication tag overhead in bytes.

func (*AEAD) Seal

func (a *AEAD) Seal(nonce, plaintext, additionalData []byte) ([]byte, error)

Seal encrypts and authenticates plaintext with the given nonce and additional data. nonce must be exactly NonceSize() bytes. Returns ciphertext + authentication tag appended together.

func (*AEAD) Suite

func (a *AEAD) Suite() CipherSuite

Suite returns the active cipher suite.

type CipherSuite

type CipherSuite uint8

CipherSuite identifies the selected AEAD algorithm.

const (
	CipherChaCha20Poly1305 CipherSuite = iota
	CipherAES256GCM
)

func (CipherSuite) String

func (c CipherSuite) String() string

type DerivedKeys

type DerivedKeys struct {
	// EncryptKey is the AEAD key for encrypting outbound data (32 bytes).
	EncryptKey []byte
	// DecryptKey is the AEAD key for decrypting inbound data (32 bytes).
	DecryptKey []byte
	// SendNonce is the initial nonce for outbound records (12 bytes).
	SendNonce []byte
	// RecvNonce is the initial nonce for inbound records (12 bytes).
	RecvNonce []byte

	// Suite is the negotiated cipher suite.
	Suite CipherSuite
}

DerivedKeys holds session keys derived from the hybrid shared secret.

func DeriveRekeyMaterial

func DeriveRekeyMaterial(currentKey []byte, salt []byte, isClient bool) (*DerivedKeys, error)

DeriveRekeyMaterial derives new keys for a key rotation event. It uses the current session key as additional input for forward secrecy.

func DeriveSessionKeys

func DeriveSessionKeys(sharedSecret *HybridSharedSecret, salt []byte, isClient bool) (*DerivedKeys, error)

DeriveSessionKeys derives all session keys from the hybrid shared secret. salt is a fresh random value exchanged during the handshake (nonces). isClient determines key assignment direction (prevents reflection attacks).

type HybridPrivateKey

type HybridPrivateKey struct {
	// Classical: X25519 ephemeral private key
	X25519Private *ecdh.PrivateKey

	// Post-quantum: ML-KEM-768 decapsulation key (a.k.a. secret key)
	MLKEMDecapKey *mlkem.DecapsulationKey768
}

HybridPrivateKey holds both the classical and post-quantum private keys. Only the initiator (client) side generates the ML-KEM decapsulation key.

type HybridPublicKey

type HybridPublicKey struct {
	// Classical: X25519 ephemeral public key (32 bytes)
	X25519Public []byte

	// Post-quantum: ML-KEM-768 encapsulation key (1184 bytes)
	MLKEMEncapKey []byte
}

HybridPublicKey holds the public components sent during key exchange.

type HybridSharedSecret

type HybridSharedSecret struct {
	// Combined entropy from both key exchanges (SHA-512 of concatenation)
	Combined []byte
}

HybridSharedSecret is the result of the hybrid key exchange. It must be passed to HKDF to derive actual session keys.

func Decapsulate

func Decapsulate(priv *HybridPrivateKey, serverX25519Pub []byte, mlkemCT []byte) (*HybridSharedSecret, error)

Decapsulate is called by the initiator (client) after receiving the ServerHello. It uses the previously generated private keys to derive the matching shared secret.

func Encapsulate

func Encapsulate(clientPub *HybridPublicKey) (serverX25519Pub []byte, mlkemCT []byte, ss *HybridSharedSecret, err error)

Encapsulate is called by the responder (server) when it receives the client's public key. It performs both key exchanges and returns:

  • The server's X25519 public key bytes (sent back in ServerHello)
  • The ML-KEM ciphertext bytes (sent back in ServerHello)
  • The shared secret derived from both exchanges

Jump to

Keyboard shortcuts

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