Documentation
¶
Overview ¶
Package cryptoutil implements the cryptographic primitives a VPN transport needs: Diffie-Hellman groups, keyed PRFs and prf+ expansion, integrity transforms, and the handshake (SKCipher) and data-path (ESPCrypter) ciphers.
It is deliberately protocol-agnostic: nothing here knows about IKEv2 or its IANA transform-ID registry. Mapping a negotiated transform ID onto one of these primitives is the job of a protocol package (for IKEv2, that is internal/ikev2/transform), which keeps this layer reusable by any protocol.
Index ¶
- Constants
- func NewBLAKE2s() hash.Hash
- func NewBLAKE2s128MAC(key []byte) (hash.Hash, error)
- func NewBLAKE2s256MAC(key []byte) (hash.Hash, error)
- func NewChaCha20Poly1305(key []byte) (cipher.AEAD, error)
- func NewXChaCha20Poly1305(key []byte) (cipher.AEAD, error)
- func SecretEqual(a, b []byte) bool
- type DHGroup
- type ESPCrypter
- type Integrity
- type PRF
- type SKCipher
- type SKParams
Constants ¶
const BLAKE2s128Size = 16
BLAKE2s128Size is the BLAKE2s-128 digest length in octets.
const BLAKE2sSize = blake2s.Size
BLAKE2sSize is the BLAKE2s-256 digest length in octets.
const ChaCha20Poly1305KeySize = chacha20poly1305.KeySize
ChaCha20Poly1305KeySize is the key length in octets for both the AEAD constructors below.
Variables ¶
This section is empty.
Functions ¶
func NewBLAKE2s ¶
NewBLAKE2s returns an unkeyed BLAKE2s-256 hash (RFC 7693).
func NewBLAKE2s128MAC ¶
NewBLAKE2s128MAC returns a keyed BLAKE2s-128 hash. This is the 128-bit digest WireGuard calls MAC(): mac1, mac2 and the cookie are all this width, not the 256-bit one.
func NewBLAKE2s256MAC ¶
NewBLAKE2s256MAC returns a keyed BLAKE2s-256 hash — BLAKE2's native MAC mode, which needs no HMAC construction around it. The key must be at most 32 octets.
func NewChaCha20Poly1305 ¶
NewChaCha20Poly1305 returns the AEAD (RFC 8439) keyed by a 32-octet key, with a 12-octet nonce. This is WireGuard's transport and handshake cipher.
func NewXChaCha20Poly1305 ¶
NewXChaCha20Poly1305 returns the extended-nonce variant (24-octet nonce), keyed by a 32-octet key. WireGuard uses it for cookie replies, where the nonce is random rather than a counter and so needs the larger space.
func SecretEqual ¶ added in v0.4.0
SecretEqual reports whether two secret-derived values are equal, in time that does not depend on how much of them matches.
Use it for anything an attacker can supply and retry: authentication responses, MACs, tags, proofs. Length is not secret — a mismatch there is reported immediately, since the sizes involved are fixed by the protocol and visible on the wire anyway.
Types ¶
type DHGroup ¶
type DHGroup interface {
// Generate returns the public key bytes (wire form) for a fresh private key.
Generate() (pub []byte, err error)
// ComputeSecret takes the peer public key bytes and returns the shared secret.
ComputeSecret(peerPub []byte) ([]byte, error)
}
DHGroup abstracts a Diffie-Hellman group: generate an ephemeral key, expose the public value in wire form, and compute a shared secret.
func NewECDH ¶
NewECDH returns an ECDH group over curve. When stripPointPrefix is set, the uncompressed-point marker (0x04) that crypto/ecdh puts in front of an X||Y public value is removed on the wire and re-added on parse: the NIST curves transmit bare X||Y (RFC 5903), whereas X25519 has no such prefix.
func NewMODP2048 ¶
func NewMODP2048() DHGroup
NewMODP2048 returns the 2048-bit MODP group (RFC 3526).
type ESPCrypter ¶
type ESPCrypter interface {
// Overhead returns the number of octets Seal adds beyond the plaintext
// (IV + ICV for AEAD; IV + MAC for CBC-ETM). Callers use it to size buffers.
Overhead() int
// BlockLen is the cipher block size for ESP trailer padding (1 for AEAD).
BlockLen() int
// Seal appends iv||ciphertext||icv for plaintext (authenticating aad) to
// dst and returns the extended slice. aad is not encrypted.
Seal(dst, aad, plaintext []byte) ([]byte, error)
// Open verifies and decrypts ivCtIcv (authenticating aad), appending the
// recovered plaintext to dst and returning the extended slice.
Open(dst, aad, ivCtIcv []byte) ([]byte, error)
}
ESPCrypter is an allocation-conscious cipher for the ESP data path. Unlike SKCipher (which rebuilds its cipher state on every call for handshake use), an ESPCrypter prepares its keyed cipher once and then seals/opens packets appending into a caller-supplied buffer, so the per-packet hot path performs no cipher construction and minimal allocation.
A single ESPCrypter is intended to be driven by one goroutine at a time (one per SA direction), matching the userspace data-plane pump, which uses separate crypters for the inbound and outbound directions. It is not safe for concurrent use.
func NewAESCBCESPCrypter ¶
func NewAESCBCESPCrypter(keyBits int, encKey []byte, integ *Integrity, integKey []byte) (ESPCrypter, error)
NewAESCBCESPCrypter builds a prepared AES-CBC + HMAC (encrypt-then-MAC) ESP crypter. keyBits is the AES key length (0 selects AES-256); integ and integKey supply the MAC.
func NewAESGCMESPCrypter ¶
func NewAESGCMESPCrypter(keyBits int, encKey []byte) (ESPCrypter, error)
NewAESGCMESPCrypter builds a prepared AES-GCM-16 ESP crypter. keyBits is the AES key length (0 selects AES-256); encKey is the ESP encryption key followed by its 4-octet GCM salt (RFC 4106).
func NewChaCha20Poly1305ESPCrypter ¶ added in v0.6.0
func NewChaCha20Poly1305ESPCrypter(encKey []byte) (ESPCrypter, error)
NewChaCha20Poly1305ESPCrypter builds a prepared ChaCha20-Poly1305 ESP crypter (RFC 7634). encKey is the 32-octet key followed by its 4-octet salt; the wire framing (8-octet IV, 16-octet tag, salt||IV nonce) matches AES-GCM-16, so it reuses the same prepared-AEAD crypter.
type Integrity ¶
type Integrity struct {
KeyLen int // key length in bytes
ICVLen int // truncated output length in bytes
// contains filtered or unexported fields
}
Integrity is a MAC transform used by non-AEAD SK ciphers (RFC 7296 2.14).
func NewHMACIntegrity ¶
NewHMACIntegrity builds an HMAC integrity transform over the given hash, truncating its output to icvLen octets. keyLen is the key length in octets.
type PRF ¶
type PRF struct {
Size int // output length in bytes
// PreferredKeyLen is the key length used when the PRF key is variable and
// we are choosing one (equal to the output size for HMAC PRFs).
PreferredKeyLen int
// contains filtered or unexported fields
}
PRF is a keyed pseudorandom function (RFC 7296 section 2.13).
func NewHMACPRF ¶
NewHMACPRF builds an HMAC-based PRF over the given hash. For HMAC PRFs the preferred key length equals the hash output size (RFC 7296 section 2.13).
type SKCipher ¶
type SKCipher interface {
// KeyLen is the encryption key length in bytes.
KeyLen() int
// IVLen is the length of the per-message IV/nonce written on the wire.
IVLen() int
// ICVLen is the length of the integrity tag/MAC appended after ciphertext.
ICVLen() int
// BlockLen is the cipher block size for padding; 1 for stream/AEAD.
BlockLen() int
// AEAD reports whether integrity is provided by the cipher itself.
AEAD() bool
// Seal encrypts plaintext and returns iv||ciphertext||icv. aad is the
// authenticated-but-not-encrypted prefix (IKE header .. SK header).
Seal(encKey, integKey, aad, plaintext []byte) ([]byte, error)
// Open verifies and decrypts. For non-AEAD, integ is checked over
// aad||iv||ciphertext before decryption (encrypt-then-MAC).
Open(encKey, integKey, aad, ivCtIcv []byte) (plaintext []byte, err error)
}
SKCipher protects the encrypted (SK) payload. It handles both AEAD ciphers (AES-GCM, ChaCha20-Poly1305) and the classic encrypt-then-MAC construction (AES-CBC + HMAC). The interface abstracts over both so the message layer is agnostic to which suite was negotiated.
Layout of the SK payload body (RFC 7296 section 3.14):
[ IV | ciphertext(padded) | ICV ]
For AEAD, IV is the explicit nonce portion and ICV is the auth tag. The AAD covers the IKE header and all preceding payload headers up to and including the SK generic header.
func NewAESCBCSKCipher ¶
NewAESCBCSKCipher returns an AES-CBC SK cipher for the given key length in bits; 0 selects AES-256. Integrity is supplied separately by an Integrity transform, and callers must route Seal/Open through SealETM/OpenETM.
func NewAESGCMSKCipher ¶
NewAESGCMSKCipher returns an AES-GCM-16 SK cipher (RFC 5282) for the given key length in bits; 0 selects AES-256.
func NewChaCha20Poly1305SKCipher ¶ added in v0.6.0
NewChaCha20Poly1305SKCipher returns a ChaCha20-Poly1305 SK cipher (RFC 7634). Its wire framing is identical to AES-GCM-16 — a 4-octet salt in the trailing key material, an 8-octet explicit IV and a 16-octet tag — so it shares the generic AEAD implementation; only the key is fixed at 256 bits and there is no key-length attribute to negotiate.