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
- func Fingerprint(pubKey []byte) string
- func GenerateKeyPair() (*HybridPrivateKey, *HybridPublicKey, error)
- func HasAESNI() bool
- func IncrementNonce(nonce []byte)
- func RandomBytes(n int) ([]byte, error)
- func ValidateKeyPair(clientPriv *HybridPrivateKey, clientPub *HybridPublicKey) error
- func Zeroize(b []byte)
- func ZeroizeDerivedKeys(dk *DerivedKeys)
- type AEAD
- type CipherSuite
- type DerivedKeys
- type HybridPrivateKey
- type HybridPublicKey
- type HybridSharedSecret
Constants ¶
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" )
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 ¶
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 ¶
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 ¶
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.
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 []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