A high-performance polynomial-based message authentication code (MAC) implementation in Zig, based on polynomial evaluation modulo prime 2^116 - 3.
- Cryptographic MAC: Provides message authentication using polynomial evaluation
- Simple API: Easy-to-use interface for authentication and verification
- Incremental processing: Support for streaming large messages
- Zero dependencies: Pure Zig implementation using only the standard library
Poly1163 uses polynomial evaluation over a large prime field (2^116 - 3) to compute authentication tags:
-
Key derivation: 256-bit key split into:
r: 112-bit polynomial evaluation key (clamped for security)s: 128-bit final masking key (blind)
-
Message processing: Messages are processed in 14-byte blocks, with each block:
- Converted to a 112-bit integer (little-endian)
- Added with a high bit set for domain separation
- Accumulated using polynomial evaluation:
acc = (acc + block) * r mod p
-
Finalization: The accumulator is masked with
sto produce the final 128-bit tag
Add to your build.zig.zon:
.dependencies = .{
.poly1163 = .{
.path = "path/to/zig-poly1163",
},
},const std = @import("std");
const poly1163 = @import("poly1163");
// Generate or load a 256-bit secret key
var key: [32]u8 = undefined;
std.crypto.random.bytes(&key);
// Authenticate a message
const message = "Hello, World!";
const tag = poly1163.authenticate(key, message);
// Tag is a 16-byte authentication code
std.debug.print("Tag: {x}\n", .{std.fmt.fmtSliceHexLower(&tag)});For large messages or streaming data:
var poly = poly1163.Poly1163.init(key);
// Process data in chunks
poly.update(chunk1);
poly.update(chunk2);
poly.update(chunk3);
// Get the final tag
const tag = poly.final();// Verify a received tag
var poly = poly1163.Poly1163.init(key);
poly.update(message);
if (poly.verify(received_tag)) {
// Message is authentic
} else {
// Authentication failed - message may be tampered
}Poly1163: Main struct for incremental MAC computationKEY_SIZE = 32: Size of the secret key in bytesTAG_SIZE = 16: Size of the authentication tag in bytes
Initialize a new Poly1163 instance with a secret key.
Process message data incrementally. Can be called multiple times.
Finalize and return the authentication tag.
Verify an authentication tag against the expected value.
One-shot function to authenticate a complete message.
- Key management: Keys must be kept secret and generated using a cryptographically secure random number generator
- Tag truncation: Never truncate tags; always use the full 16 bytes
- Nonce/sequence numbers: For protection against replay attacks, include a nonce or sequence number in the authenticated message
- Not encryption: Poly1163 provides authentication only, not confidentiality. Combine with encryption for full protection
zig buildzig build testzig build runzig build benchmarkzig build test-compatzig build test-vectors- Prime modulus: 2^116 - 3 (chosen for efficient reduction)
- Block size: 14 bytes (112 bits)
- Key clamping: Specific bits cleared in
rto ensure uniform distribution and prevent weak keys - Padding: Each block includes a high bit (bit 112) to prevent extension attacks
- Arithmetic: Uses efficient modular reduction with SIMD vector operations for performance