macs — Cached PRF-grade MAC factories for ITB Authenticated Encryption
Security notice. ITB is an experimental symmetric cipher construction without prior peer review, independent cryptanalysis, or formal certification. The construction's security properties have not been verified by independent cryptographers or mathematicians.
PRF-grade hash functions are required. No warranty is provided.
No bespoke cryptography. ITB introduces no cryptographic primitive of its own — no custom S-box, permutation, or round function. It is a construction over existing primitives, much as PGP composes standard ciphers rather than defining one. Such constructions are not the object of algorithm-level cryptographic certification: national regimes (NIST CAVP/FIPS in the US, GOST/FSB in Russia, KCMVP in South Korea, OSCCA's SM-series in China, SOG-IS/EUCC and national lists in the EU, ASD's ISM in Australia) certify primitives and the modules built on them, not compositional schemes. Eligibility for regulated use is therefore inherited from the primitives ITB is configured with, not conferred by ITB itself.
Drop-in factories that produce itb.MACFunc closures for the three
shipped MAC primitives. All three produce a 32-byte tag and accept
a 32-byte (or longer for the HMAC variants) key. The fixed 32-byte
tag size lets bindings size their authenticated payload buffer the
same way regardless of which MAC was selected.
Every factory pre-keys its primitive once at construction and is
safe to call concurrently from multiple goroutines.
Canonical primitives
In FFI-stable index order:
| # |
Name (FFI) |
Key size |
Tag size |
Caching |
| 0 |
kmac256 |
≥16 B |
32 B |
cSHAKE256 template with key absorbed once, Clone() per call |
| 1 |
hmac-sha256 |
≥16 B |
32 B |
sync.Pool of hmac.New(sha256.New, key) instances |
| 2 |
hmac-blake3 |
32 B |
32 B |
blake3.NewKeyed(key) template with Clone() per call |
kmac256 follows NIST SP 800-185 with output length L = 256 bits.
hmac-sha256 follows RFC 2104 with SHA-256. hmac-blake3 uses
BLAKE3's native keyed mode (no nested HMAC wrapper — BLAKE3-keyed
is itself a sound keyed PRF; see BLAKE3 spec section 6).
Usage
Native Go API — generate fresh random hash + MAC keys, persist the
encryptor material via itb.Blob{128,256,512}.
Each Blob type packs every seed's hash key + components, the optional
dedicated lockSeed, AND the MAC key + name into one self-describing
JSON blob alongside the captured itb.Set* globals; ship the
resulting blob_bytes alongside the ciphertext (or out-of-band) and
rebuild on the receiver via Blob{N}.Import followed by per-slot
factory rewiring + macs.Make(blob.MACName, blob.MACKey).
Areion-SoEM has paired (single, batched, fixedKey) constructors so the
AVX-512 batched dispatch path is reachable, paired with HMAC-BLAKE3 as
the authentication primitive:
// Sender
import (
"crypto/rand"
"fmt"
"github.com/everanium/itb"
"github.com/everanium/itb/hashes"
"github.com/everanium/itb/macs"
)
func main() {
itb.SetMaxWorkers(8) // limit to 8 CPU cores (default: all CPUs)
itb.SetNonceBits(512) // 512-bit nonce (default: 128-bit)
itb.SetBarrierFill(4) // CSPRNG fill margin (default: 1, valid: 1,2,4,8,16,32)
itb.SetBitSoup(1) // optional bit-level split ("bit-soup"; default: 0 = byte-level)
// automatically enabled for Single Ouroboros if
// itb.SetLockSoup(1) is enabled or vice versa
itb.SetLockSoup(1) // optional Insane Interlocked Mode: per-chunk PRF-keyed
// bit-permutation overlay on top of bit-soup;
// automatically enabled for Single Ouroboros if
// itb.SetBitSoup(1) is enabled or vice versa
// Four independent CSPRNG-keyed Areion-SoEM-512 paired closures
// (3 main seeds + 1 optional dedicated lockSeed). Each Pair
// returns (single, batched, [64]byte fixedKey).
fnN, batchN, keyN := hashes.Areion512Pair() // random noise hash key generated
fnD, batchD, keyD := hashes.Areion512Pair() // random data hash key generated
fnS, batchS, keyS := hashes.Areion512Pair() // random start hash key generated
fnL, batchL, keyL := hashes.Areion512Pair() // random lock hash key generated
//fnN, batchN := hashes.Areion512PairWithKey(keyN) // [64]byte key
//fnD, batchD := hashes.Areion512PairWithKey(keyD) // [64]byte key
//fnS, batchS := hashes.Areion512PairWithKey(keyS) // [64]byte key
//fnL, batchL := hashes.Areion512PairWithKey(keyL) // [64]byte key
ns, _ := itb.NewSeed512(2048, fnN); ns.BatchHash = batchN // random noise CSPRNG seeds, batch enabled
ds, _ := itb.NewSeed512(2048, fnD); ds.BatchHash = batchD // random data CSPRNG seeds, batch enabled
ss, _ := itb.NewSeed512(2048, fnS); ss.BatchHash = batchS // random start CSPRNG seeds, batch enabled
ls, _ := itb.NewSeed512(2048, fnL); ls.BatchHash = batchL // random lock CSPRNG seeds, batch enabled
// Optional: dedicated lockSeed for the bit-permutation derivation
// channel. Engages bit_soup or lock_soup before first encrypt
// (both already on above).
ns.AttachLockSeed(ls)
// HMAC-BLAKE3 — fastest of the three MACs through the AVX-512 ASM kernel.
var macKey [32]byte
rand.Read(macKey[:])
mac, _ := macs.HMACBLAKE3(macKey[:])
plaintext := []byte("any text or binary data - including 0x00 bytes")
// Authenticated encrypt — 32-byte tag is computed across the entire
// decrypted capacity and embedded inside the RGBWYOPA container,
// preserving oracle-free deniability.
encrypted, err := itb.EncryptAuthenticated512(ns, ds, ss, plaintext, mac)
if err != nil {
panic(err)
}
fmt.Printf("encrypted: %d bytes\n", len(encrypted))
// Cross-process persistence — Blob512 packs every seed's
// [64]byte hash key + Components plus the optional dedicated
// lockSeed AND the MAC key + name into one self-describing
// JSON blob alongside the captured itb.Set* globals.
bSrc := &itb.Blob512{}
blob, _ := bSrc.Export(keyN, keyD, keyS, ns, ds, ss,
itb.Blob512Opts{
KeyL: keyL, LS: ls,
MACKey: macKey[:], MACName: "hmac-blake3",
})
// Send encrypted payload + blob
}
// Receiver
import (
"fmt"
"github.com/everanium/itb"
"github.com/everanium/itb/hashes"
"github.com/everanium/itb/macs"
)
func main() {
itb.SetMaxWorkers(8) // limit to 8 CPU cores (default: all CPUs)
// Receive encrypted payload + blob
// encrypted := ...; blob := ...
// Blob512.Import restores per-slot hash keys + Components, the
// MAC key + name, AND applies the captured globals (NonceBits /
// BarrierFill / BitSoup / LockSoup) via the process-wide setters.
// Hash / BatchHash on each restored seed stay nil so the caller
// wires them from the saved Key* bytes through the matching
// factory.
bDst := &itb.Blob512{}
_ = bDst.Import(blob)
fnN, batchN := hashes.Areion512PairWithKey(bDst.KeyN)
fnD, batchD := hashes.Areion512PairWithKey(bDst.KeyD)
fnS, batchS := hashes.Areion512PairWithKey(bDst.KeyS)
fnL, batchL := hashes.Areion512PairWithKey(bDst.KeyL)
bDst.NS.Hash, bDst.NS.BatchHash = fnN, batchN
bDst.DS.Hash, bDst.DS.BatchHash = fnD, batchD
bDst.SS.Hash, bDst.SS.BatchHash = fnS, batchS
bDst.LS.Hash, bDst.LS.BatchHash = fnL, batchL
bDst.NS.AttachLockSeed(bDst.LS)
mac, _ := macs.Make(bDst.MACName, bDst.MACKey)
// Authenticated decrypt — any single-bit tamper triggers MAC failure
// (no oracle leak about which byte was tampered).
decrypted, err := itb.DecryptAuthenticated512(bDst.NS, bDst.DS, bDst.SS, encrypted, mac)
if err != nil {
panic(err)
}
fmt.Printf("decrypted: %d bytes\n", len(decrypted))
}
BLAKE2b-512 has paired (single, batched, fixedKey) constructors so the
AVX-512 ZMM-batched chain-absorb dispatch path is reachable, paired with
HMAC-BLAKE3 as the authentication primitive:
// Sender
import (
"crypto/rand"
"fmt"
"github.com/everanium/itb"
"github.com/everanium/itb/hashes"
"github.com/everanium/itb/macs"
)
func main() {
itb.SetMaxWorkers(8) // limit to 8 CPU cores (default: all CPUs)
itb.SetNonceBits(512) // 512-bit nonce (default: 128-bit)
itb.SetBarrierFill(4) // CSPRNG fill margin (default: 1, valid: 1,2,4,8,16,32)
itb.SetBitSoup(1) // optional bit-level split ("bit-soup"; default: 0 = byte-level)
// automatically enabled for Single Ouroboros if
// itb.SetLockSoup(1) is enabled or vice versa
itb.SetLockSoup(1) // optional Insane Interlocked Mode: per-chunk PRF-keyed
// bit-permutation overlay on top of bit-soup;
// automatically enabled for Single Ouroboros if
// itb.SetBitSoup(1) is enabled or vice versa
// Four independent CSPRNG-keyed BLAKE2b-512 paired closures
// (3 main seeds + 1 optional dedicated lockSeed). Each Pair
// returns (single, batched, [64]byte fixedKey).
fnN, batchN, keyN := hashes.BLAKE2b512Pair() // random noise hash key generated
fnD, batchD, keyD := hashes.BLAKE2b512Pair() // random data hash key generated
fnS, batchS, keyS := hashes.BLAKE2b512Pair() // random start hash key generated
fnL, batchL, keyL := hashes.BLAKE2b512Pair() // random lock hash key generated
//fnN, batchN := hashes.BLAKE2b512PairWithKey(keyN) // [64]byte key
//fnD, batchD := hashes.BLAKE2b512PairWithKey(keyD) // [64]byte key
//fnS, batchS := hashes.BLAKE2b512PairWithKey(keyS) // [64]byte key
//fnL, batchL := hashes.BLAKE2b512PairWithKey(keyL) // [64]byte key
ns, _ := itb.NewSeed512(2048, fnN); ns.BatchHash = batchN // random noise CSPRNG seeds, batch enabled
ds, _ := itb.NewSeed512(2048, fnD); ds.BatchHash = batchD // random data CSPRNG seeds, batch enabled
ss, _ := itb.NewSeed512(2048, fnS); ss.BatchHash = batchS // random start CSPRNG seeds, batch enabled
ls, _ := itb.NewSeed512(2048, fnL); ls.BatchHash = batchL // random lock CSPRNG seeds, batch enabled
// Optional: dedicated lockSeed for the bit-permutation derivation
// channel — same flow as the Areion-SoEM-512 + HMAC-BLAKE3 example.
ns.AttachLockSeed(ls)
// HMAC-BLAKE3 — fastest of the three MACs through the AVX-512 ASM kernel.
var macKey [32]byte
rand.Read(macKey[:])
mac, _ := macs.HMACBLAKE3(macKey[:])
plaintext := []byte("any text or binary data - including 0x00 bytes")
// Authenticated encrypt — 32-byte tag is computed across the entire
// decrypted capacity and embedded inside the RGBWYOPA container,
// preserving oracle-free deniability.
encrypted, err := itb.EncryptAuthenticated512(ns, ds, ss, plaintext, mac)
if err != nil {
panic(err)
}
fmt.Printf("encrypted: %d bytes\n", len(encrypted))
// Cross-process persistence — Blob512 packs every seed's
// [64]byte hash key + Components plus the optional dedicated
// lockSeed AND the MAC key + name into one self-describing
// JSON blob alongside the captured itb.Set* globals.
bSrc := &itb.Blob512{}
blob, _ := bSrc.Export(keyN, keyD, keyS, ns, ds, ss,
itb.Blob512Opts{
KeyL: keyL, LS: ls,
MACKey: macKey[:], MACName: "hmac-blake3",
})
// Send encrypted payload + blob
}
// Receiver
import (
"fmt"
"github.com/everanium/itb"
"github.com/everanium/itb/hashes"
"github.com/everanium/itb/macs"
)
func main() {
itb.SetMaxWorkers(8) // limit to 8 CPU cores (default: all CPUs)
// Receive encrypted payload + blob
// encrypted := ...; blob := ...
// Blob512.Import restores per-slot hash keys + Components, the
// MAC key + name, AND applies the captured globals via the
// process-wide setters. Hash / BatchHash on each restored seed
// stay nil so the caller wires them from the saved Key* bytes
// through the matching factory.
bDst := &itb.Blob512{}
_ = bDst.Import(blob)
fnN, batchN := hashes.BLAKE2b512PairWithKey(bDst.KeyN)
fnD, batchD := hashes.BLAKE2b512PairWithKey(bDst.KeyD)
fnS, batchS := hashes.BLAKE2b512PairWithKey(bDst.KeyS)
fnL, batchL := hashes.BLAKE2b512PairWithKey(bDst.KeyL)
bDst.NS.Hash, bDst.NS.BatchHash = fnN, batchN
bDst.DS.Hash, bDst.DS.BatchHash = fnD, batchD
bDst.SS.Hash, bDst.SS.BatchHash = fnS, batchS
bDst.LS.Hash, bDst.LS.BatchHash = fnL, batchL
bDst.NS.AttachLockSeed(bDst.LS)
mac, _ := macs.Make(bDst.MACName, bDst.MACKey)
// Authenticated decrypt — any single-bit tamper triggers MAC failure
// (no oracle leak about which byte was tampered).
decrypted, err := itb.DecryptAuthenticated512(bDst.NS, bDst.DS, bDst.SS, encrypted, mac)
if err != nil {
panic(err)
}
fmt.Printf("decrypted: %d bytes\n", len(decrypted))
}
SipHash-2-4 + HMAC-SHA256 — paired (single, batched) constructor for
the hash, lockSeed-engaged via SetBitSoup, MAC + hash keys captured
through Blob128:
import (
"fmt"
"github.com/everanium/itb"
"github.com/everanium/itb/hashes"
"github.com/everanium/itb/macs"
)
func main() {
itb.SetMaxWorkers(8) // limit to 8 CPU cores (default: all CPUs)
itb.SetNonceBits(512) // 512-bit nonce (default: 128-bit)
itb.SetBarrierFill(4) // CSPRNG fill margin (default: 1, valid: 1,2,4,8,16,32)
itb.SetBitSoup(1) // optional bit-level split ("bit-soup"; default: 0 = byte-level)
// automatically enabled for Single Ouroboros if
// itb.SetLockSoup(1) is enabled or vice versa
itb.SetLockSoup(1) // optional Insane Interlocked Mode: per-chunk PRF-keyed
// bit-permutation overlay on top of bit-soup;
// automatically enabled for Single Ouroboros if
// itb.SetBitSoup(1) is enabled or vice versa
fnN, batchN := hashes.SipHash24Pair()
fnD, batchD := hashes.SipHash24Pair()
fnS, batchS := hashes.SipHash24Pair()
fnL, batchL := hashes.SipHash24Pair()
ns, _ := itb.NewSeed128(1024, fnN); ns.BatchHash = batchN
ds, _ := itb.NewSeed128(1024, fnD); ds.BatchHash = batchD
ss, _ := itb.NewSeed128(1024, fnS); ss.BatchHash = batchS
ls, _ := itb.NewSeed128(1024, fnL); ls.BatchHash = batchL
ns.AttachLockSeed(ls)
// HMAC-SHA256 — universal interoperability standard (RFC 4231).
var macKey [32]byte
rand.Read(macKey[:])
mac, _ := macs.HMACSHA256(macKey[:])
plaintext := []byte("any text or binary data - including 0x00 bytes")
// Authenticated encrypt into RGBWYOPA container with embedded 32-byte tag
encrypted, _ := itb.EncryptAuthenticated128(ns, ds, ss, plaintext, mac)
// Cross-process persistence — Blob128 packs Components + the
// optional dedicated lockSeed (KeyN/KeyD/KeyS/KeyL stay nil since
// SipHash-2-4 has no internal fixed key) plus the MAC key + name.
bSrc := &itb.Blob128{}
blob, _ := bSrc.Export(nil, nil, nil, ns, ds, ss,
itb.Blob128Opts{
LS: ls,
MACKey: macKey[:], MACName: "hmac-sha256",
})
_ = blob // ship alongside the ciphertext
}
Name-keyed dispatch (used by the FFI layer; works for any code that
selects the MAC primitive at runtime). The key is []byte (size
validated against the primitive's minimum / fixed length):
mac, _ := macs.Make("hmac-sha256", key)
KMAC256 has a WithCustomization counterpart for domain
separation across distinct usages of the same key. HMAC-SHA256
and HMAC-BLAKE3 take the key as their only argument — there is
no separate WithKey variant since the key is already the only
state the factory holds.
Easy Mode — Quick start
easy.New (Single Ouroboros) and easy.New3 (Triple Ouroboros)
build a high-level *easy.Encryptor around a single hash primitive
plus a single MAC primitive chosen from the canonical list above.
The MAC argument flips the encryptor's EncryptAuth /
DecryptAuth path between the three options: "hmac-blake3"
(default — fastest under AVX-512+VL), "hmac-sha256" (dedicated
HMAC-SHA-256, the conservative pick), and "kmac256"
(KMAC256 — slowest under AVX-512+VL on hosts where the KMAC256
single-call asm is engaged). The MAC key is generated fresh from
crypto/rand alongside the seed material at construction; the
state blob carries the MAC key + name and the receiver restores
everything via Import. Two encryptors with different MAC choices
can run concurrently without cross-contamination — the per-
instance *itb.Config snapshot isolates each.
// Sender
package main
import (
"fmt"
"github.com/everanium/itb"
"github.com/everanium/itb/easy"
)
func main() {
itb.SetMaxWorkers(8) // limit to 8 CPU cores (default: all CPUs)
// Single-Ouroboros constructor — picks the BLAKE3 PRF on the
// hash side and HMAC-BLAKE3 on the MAC side. Triple Ouroboros
// (7 seeds) → easy.New3(...). The MAC choice is independent of
// the hash choice; any valid (primitive × MAC) pair works.
enc := easy.New("blake3", 1024, "hmac-blake3")
defer enc.Close()
// Per-instance configuration.
enc.SetNonceBits(256) // 256-bit nonce (default: 128-bit)
enc.SetBarrierFill(4) // CSPRNG fill margin (default: 1, valid: 1, 2, 4, 8, 16, 32)
//enc.SetLockSeed(1) // optional dedicated lockSeed for the bit-permutation
// derivation channel — separates that PRF's keying material
// from the noiseSeed-driven noise-injection channel; auto-
// couples SetLockSoup(1) + SetBitSoup(1). Adds one extra
// seed slot (3 → 4 for Single, 7 → 8 for Triple). Must be
// called BEFORE the first Encrypt — switching mid-session
// panics with easy.ErrLockSeedAfterEncrypt.
// For cross-process persistence: enc.Export() returns a single
// JSON blob carrying PRF keys, seed components, MAC key + name,
// and (when active) the dedicated lockSeed material.
blob := enc.Export()
fmt.Printf("state blob: %d bytes\n", len(blob))
fmt.Printf("primitive: %s, key_bits: %d, mode: %d, mac: %s\n",
enc.Primitive, enc.KeyBits, enc.Mode, enc.MACName)
plaintext := []byte("any text or binary data - including 0x00 bytes")
// Authenticated encrypt — 32-byte tag is computed across the
// entire decrypted capacity via the bound MAC closure (here
// HMAC-BLAKE3) and embedded inside the RGBWYOPA container,
// preserving oracle-free deniability.
encrypted, err := enc.EncryptAuth(plaintext)
if err != nil {
panic(err)
}
fmt.Printf("encrypted: %d bytes\n", len(encrypted))
// Send encrypted payload + state blob
}
// Receiver
package main
import (
"fmt"
"github.com/everanium/itb"
"github.com/everanium/itb/easy"
)
func main() {
itb.SetMaxWorkers(8) // limit to 8 CPU cores (default: all CPUs)
// Receive encrypted payload + state blob
// var encrypted, blob []byte = ..., ...
// Peek at the blob's metadata before constructing a matching
// encryptor — primitive / key_bits / mode / mac must all agree
// with the sender or Import returns easy.ErrMismatch with the
// offending field tag.
prim, keyBits, mode, mac := easy.PeekConfig(blob)
fmt.Printf("peek: primitive=%s, key_bits=%d, mode=%d, mac=%s\n",
prim, keyBits, mode, mac)
var dec *easy.Encryptor
if mode == 1 {
dec = easy.New(prim, keyBits, mac)
} else {
dec = easy.New3(prim, keyBits, mac)
}
defer dec.Close()
// Restore PRF keys, seed components, MAC key, and the per-instance
// configuration overrides from the saved blob. DecryptAuth
// surfaces MAC verification failures as itb.ErrMACFailure on the
// underlying error chain.
if err := dec.Import(blob); err != nil {
panic(err)
}
decrypted, err := dec.DecryptAuth(encrypted)
if err != nil {
panic(err)
}
fmt.Printf("decrypted: %s\n", string(decrypted))
}
Easy Mode — Mixed primitives (different PRF per seed slot)
easy.NewMixed and easy.NewMixed3 accept a per-slot primitive
spec, allowing the noise / data / start (and optional dedicated
lockSeed) seed slots to use different PRF primitives within the
same native hash width. The MAC primitive is a separate one-per-
encryptor choice (one of kmac256 / hmac-sha256 / hmac-blake3)
and rides through the same constructor. The state blob carries
per-slot primitives + per-slot PRF keys + the MAC key + name; the
receiver constructs a matching encryptor with the same spec and
calls Import to restore.
// Sender
package main
import (
"fmt"
"github.com/everanium/itb"
"github.com/everanium/itb/easy"
)
func main() {
itb.SetMaxWorkers(8) // limit to 8 CPU cores (default: all CPUs)
// Per-slot primitive selection (Single Ouroboros, 3 + 1 slots).
// Every name must share the same native hash width — mixing
// widths is rejected at construction with easy.ErrEasyMixedWidth.
// Triple Ouroboros mirror — easy.NewMixed3(easy.MixedSpec3{...})
// takes seven per-slot names (noise + 3 data + 3 start) plus
// the optional PrimitiveL lockSeed.
enc := easy.NewMixed(easy.MixedSpec{
PrimitiveN: "blake3", // noiseSeed: BLAKE3
PrimitiveD: "blake2s", // dataSeed: BLAKE2s
PrimitiveS: "areion256", // startSeed: Areion-SoEM-256
PrimitiveL: "blake2b256", // dedicated lockSeed (optional;
// empty = no lockSeed slot)
KeyBits: 1024,
MACName: "hmac-blake3",
})
defer enc.Close()
// Per-instance configuration applies as for easy.New.
enc.SetNonceBits(512)
enc.SetBarrierFill(4)
// BitSoup + LockSoup are auto-coupled on the on-direction by
// PrimitiveL above; explicit calls below are unnecessary but
// harmless if added.
//enc.SetBitSoup(1)
//enc.SetLockSoup(1)
// Per-slot introspection — Primitive returns the "mixed"
// literal, PrimitiveAt(slot) returns each slot's name,
// IsMixed() is the typed predicate.
fmt.Printf("mixed=%v primitive=%s\n", enc.IsMixed(), enc.Primitive)
for i := 0; i < 4; i++ {
fmt.Printf(" slot %d: %s\n", i, enc.PrimitiveAt(i))
}
blob := enc.Export()
fmt.Printf("state blob: %d bytes\n", len(blob))
plaintext := []byte("mixed-primitive Easy Mode payload")
// Authenticated encrypt — 32-byte tag is computed across the
// entire decrypted capacity and embedded inside the RGBWYOPA
// container, preserving oracle-free deniability.
encrypted, err := enc.EncryptAuth(plaintext)
if err != nil {
panic(err)
}
fmt.Printf("encrypted: %d bytes\n", len(encrypted))
// Send encrypted payload + state blob
}
// Receiver
package main
import (
"fmt"
"github.com/everanium/itb"
"github.com/everanium/itb/easy"
)
func main() {
itb.SetMaxWorkers(8) // limit to 8 CPU cores (default: all CPUs)
// Receive encrypted payload + state blob
// var encrypted, blob []byte = ..., ...
// Receiver constructs a matching mixed encryptor — every per-
// slot primitive name plus key_bits and mac must agree with the
// sender. Import validates each per-slot primitive against the
// receiver's bound spec; mismatches surface as
// easy.ErrMismatch{Field: "primitive"}.
dec := easy.NewMixed(easy.MixedSpec{
PrimitiveN: "blake3",
PrimitiveD: "blake2s",
PrimitiveS: "areion256",
PrimitiveL: "blake2b256",
KeyBits: 1024,
MACName: "hmac-blake3",
})
defer dec.Close()
// Restore PRF keys, seed components, MAC key, and the per-
// instance configuration overrides from the saved blob. Mixed
// blobs carry mixed:true plus a primitives array; Import on a
// single-primitive receiver (or vice versa) is rejected as a
// primitive mismatch.
if err := dec.Import(blob); err != nil {
panic(err)
}
decrypted, err := dec.DecryptAuth(encrypted)
if err != nil {
panic(err)
}
fmt.Printf("decrypted: %s\n", string(decrypted))
}
Why these three
ITB's MAC-Inside-Encrypt construction places the 32-byte tag inside
the encrypted container. The barrier dispersal
(process128 / 256 / 512) destroys the plaintext / tag boundary an
attacker could otherwise observe; under SetLockSoup(1) the
bit-permutation layer further obscures the payload region. So the
MAC primitive itself only has to be a sound keyed PRF — the
surrounding ITB construction handles placement-hiding,
replay-resistance (per-message nonce), and CCA-resistance.
Three primitives keep the choice tractable:
kmac256 — modern NIST-standard keyed XOF (SP 800-185), based
on the well-vetted Keccak permutation. But slowest.
hmac-sha256 — universal interoperability standard,
hardware-accelerated through SHA-NI on amd64 / arm64 where the
underlying CPU exposes the SHA-256 round instructions.
hmac-blake3 — fastest of the three through BLAKE3's
AVX-512 ASM kernel.
Validation
hmac-sha256 is bit-exactly cross-checked against
RFC 4231 test vectors in macs_test.go.
hmac-blake3 rests on the upstream github.com/zeebo/blake3
project's own keyed-mode KAT.
kmac256 is bit-exactly cross-checked against four KAT
vectors generated from pycryptodome 3.23.0
(Crypto.Hash.KMAC256, an audited NIST SP 800-185 reference
implementation): three are L = 256 analogues of NIST SP 800-185
Annex A samples 4 / 5 / 6 (sample 4 message
00 01 02 03, sample 5 with customization
My Tagged Application, sample 6 with the 200-byte
0x00..0xC7 message), plus a degenerate empty-message case.
Reproduce via the python snippet shown in the test file.
- All three primitives pass
TestITBAuthIntegration (3 MACs × 3
hash widths × encrypt/decrypt round trip + bit-flip tamper
rejection).