mirror of
https://github.com/ziglang/zig.git
synced 2024-11-14 16:13:24 +00:00
Add common hash/checksum functions
- SipHash64, SipHash128 - Crc32 (fast + small variants) - Adler32 - Fnv1a (32, 64 and 128 bit variants)
This commit is contained in:
parent
873641c123
commit
c34ce2cbc6
@ -438,6 +438,11 @@ set(ZIG_STD_FILES
|
||||
"fmt/errol/lookup.zig"
|
||||
"fmt/index.zig"
|
||||
"hash_map.zig"
|
||||
"hash/index.zig"
|
||||
"hash/adler.zig"
|
||||
"hash/crc.zig"
|
||||
"hash/fnv.zig"
|
||||
"hash/siphash.zig"
|
||||
"heap.zig"
|
||||
"index.zig"
|
||||
"io.zig"
|
||||
|
112
std/hash/adler.zig
Normal file
112
std/hash/adler.zig
Normal file
@ -0,0 +1,112 @@
|
||||
// Adler32 checksum.
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc1950#section-9
|
||||
// https://github.com/madler/zlib/blob/master/adler32.c
|
||||
|
||||
const std = @import("../index.zig");
|
||||
const debug = std.debug;
|
||||
|
||||
pub const Adler32 = struct {
|
||||
const base = 65521;
|
||||
const nmax = 5552;
|
||||
|
||||
adler: u32,
|
||||
|
||||
pub fn init() Adler32 {
|
||||
return Adler32 {
|
||||
.adler = 1,
|
||||
};
|
||||
}
|
||||
|
||||
// This fast variant is taken from zlib. It reduces the required modulos and unrolls longer
|
||||
// buffer inputs and should be much quicker.
|
||||
pub fn update(self: &Adler32, input: []const u8) void {
|
||||
var s1 = self.adler & 0xffff;
|
||||
var s2 = (self.adler >> 16) & 0xffff;
|
||||
|
||||
if (input.len == 1) {
|
||||
s1 +%= input[0];
|
||||
if (s1 >= base) {
|
||||
s1 -= base;
|
||||
}
|
||||
s2 +%= s1;
|
||||
if (s2 >= base) {
|
||||
s2 -= base;
|
||||
}
|
||||
}
|
||||
else if (input.len < 16) {
|
||||
for (input) |b| {
|
||||
s1 +%= b;
|
||||
s2 +%= s1;
|
||||
}
|
||||
if (s1 >= base) {
|
||||
s1 -= base;
|
||||
}
|
||||
|
||||
s2 %= base;
|
||||
}
|
||||
else {
|
||||
var i: usize = 0;
|
||||
while (i + nmax <= input.len) : (i += nmax) {
|
||||
const n = nmax / 16; // note: 16 | nmax
|
||||
|
||||
var rounds: usize = 0;
|
||||
while (rounds < n) : (rounds += 1) {
|
||||
comptime var j: usize = 0;
|
||||
inline while (j < 16) : (j += 1) {
|
||||
s1 +%= input[i + n * j];
|
||||
s2 +%= s1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i < input.len) {
|
||||
while (i + 16 <= input.len) : (i += 16) {
|
||||
comptime var j: usize = 0;
|
||||
inline while (j < 16) : (j += 1) {
|
||||
s1 +%= input[i + j];
|
||||
s2 +%= s1;
|
||||
}
|
||||
}
|
||||
while (i < input.len) : (i += 1) {
|
||||
s1 +%= input[i];
|
||||
s2 +%= s1;
|
||||
}
|
||||
|
||||
s1 %= base;
|
||||
s2 %= base;
|
||||
}
|
||||
}
|
||||
|
||||
self.adler = s1 | (s2 << 16);
|
||||
}
|
||||
|
||||
pub fn final(self: &Adler32) u32 {
|
||||
return self.adler;
|
||||
}
|
||||
|
||||
pub fn hash(input: []const u8) u32 {
|
||||
var c = Adler32.init();
|
||||
c.update(input);
|
||||
return c.final();
|
||||
}
|
||||
};
|
||||
|
||||
test "adler32 sanity" {
|
||||
debug.assert(Adler32.hash("a") == 0x620062);
|
||||
debug.assert(Adler32.hash("example") == 0xbc002ed);
|
||||
}
|
||||
|
||||
test "adler32 long" {
|
||||
const long1 = []u8 {1} ** 1024;
|
||||
debug.assert(Adler32.hash(long1[0..]) == 0x06780401);
|
||||
|
||||
const long2 = []u8 {1} ** 1025;
|
||||
debug.assert(Adler32.hash(long2[0..]) == 0x0a7a0402);
|
||||
}
|
||||
|
||||
test "adler32 very long" {
|
||||
const long = []u8 {1} ** 5553;
|
||||
debug.assert(Adler32.hash(long[0..]) == 0x707f15b2);
|
||||
}
|
||||
|
180
std/hash/crc.zig
Normal file
180
std/hash/crc.zig
Normal file
@ -0,0 +1,180 @@
|
||||
// There are two implementations of CRC32 implemented with the following key characteristics:
|
||||
//
|
||||
// - Crc32WithPoly uses 8Kb of tables but is ~10x faster than the small method.
|
||||
//
|
||||
// - Crc32SmallWithPoly uses only 64 bytes of memory but is slower. Be aware that this is
|
||||
// still moderately fast just slow relative to the slicing approach.
|
||||
|
||||
const std = @import("../index.zig");
|
||||
const debug = std.debug;
|
||||
|
||||
pub const Polynomial = struct {
|
||||
const IEEE = 0xedb88320;
|
||||
const Castagnoli = 0x82f63b78;
|
||||
const Koopman = 0xeb31d82e;
|
||||
};
|
||||
|
||||
// IEEE is by far the most common CRC and so is aliased by default.
|
||||
pub const Crc32 = Crc32WithPoly(Polynomial.IEEE);
|
||||
|
||||
// slicing-by-8 crc32 implementation.
|
||||
pub fn Crc32WithPoly(comptime poly: u32) type {
|
||||
return struct {
|
||||
const Self = this;
|
||||
const lookup_tables = comptime block: {
|
||||
@setEvalBranchQuota(20000);
|
||||
var tables: [8][256]u32 = undefined;
|
||||
|
||||
for (tables[0]) |*e, i| {
|
||||
var crc = u32(i);
|
||||
var j: usize = 0; while (j < 8) : (j += 1) {
|
||||
if (crc & 1 == 1) {
|
||||
crc = (crc >> 1) ^ poly;
|
||||
} else {
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
}
|
||||
*e = crc;
|
||||
}
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < 256) : (i += 1) {
|
||||
var crc = tables[0][i];
|
||||
var j: usize = 1; while (j < 8) : (j += 1) {
|
||||
const index = @truncate(u8, crc);
|
||||
crc = tables[0][index] ^ (crc >> 8);
|
||||
tables[j][i] = crc;
|
||||
}
|
||||
}
|
||||
|
||||
break :block tables;
|
||||
};
|
||||
|
||||
crc: u32,
|
||||
|
||||
pub fn init() Self {
|
||||
return Self {
|
||||
.crc = 0xffffffff,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn update(self: &Self, input: []const u8) void {
|
||||
var i: usize = 0;
|
||||
while (i + 8 <= input.len) : (i += 8) {
|
||||
const p = input[i..i+8];
|
||||
|
||||
// Unrolling this way gives ~50Mb/s increase
|
||||
self.crc ^= (u32(p[0]) << 0);
|
||||
self.crc ^= (u32(p[1]) << 8);
|
||||
self.crc ^= (u32(p[2]) << 16);
|
||||
self.crc ^= (u32(p[3]) << 24);
|
||||
|
||||
self.crc =
|
||||
lookup_tables[0][p[7]] ^
|
||||
lookup_tables[1][p[6]] ^
|
||||
lookup_tables[2][p[5]] ^
|
||||
lookup_tables[3][p[4]] ^
|
||||
lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
|
||||
lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
|
||||
lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
|
||||
lookup_tables[7][@truncate(u8, self.crc >> 0)];
|
||||
}
|
||||
|
||||
while (i < input.len) : (i += 1) {
|
||||
const index = @truncate(u8, self.crc) ^ input[i];
|
||||
self.crc = (self.crc >> 8) ^ lookup_tables[0][index];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn final(self: &Self) u32 {
|
||||
return ~self.crc;
|
||||
}
|
||||
|
||||
pub fn hash(input: []const u8) u32 {
|
||||
var c = Self.init();
|
||||
c.update(input);
|
||||
return c.final();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test "crc32 ieee" {
|
||||
const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE);
|
||||
|
||||
debug.assert(Crc32Ieee.hash("") == 0x00000000);
|
||||
debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43);
|
||||
debug.assert(Crc32Ieee.hash("abc") == 0x352441c2);
|
||||
}
|
||||
|
||||
test "crc32 castagnoli" {
|
||||
const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli);
|
||||
|
||||
debug.assert(Crc32Castagnoli.hash("") == 0x00000000);
|
||||
debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330);
|
||||
debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
|
||||
}
|
||||
|
||||
// half-byte lookup table implementation.
|
||||
pub fn Crc32SmallWithPoly(comptime poly: u32) type {
|
||||
return struct {
|
||||
const Self = this;
|
||||
const lookup_table = comptime block: {
|
||||
var table: [16]u32 = undefined;
|
||||
|
||||
for (table) |*e, i| {
|
||||
var crc = u32(i * 16);
|
||||
var j: usize = 0; while (j < 8) : (j += 1) {
|
||||
if (crc & 1 == 1) {
|
||||
crc = (crc >> 1) ^ poly;
|
||||
} else {
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
}
|
||||
*e = crc;
|
||||
}
|
||||
|
||||
break :block table;
|
||||
};
|
||||
|
||||
crc: u32,
|
||||
|
||||
pub fn init() Self {
|
||||
return Self {
|
||||
.crc = 0xffffffff,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn update(self: &Self, input: []const u8) void {
|
||||
for (input) |b| {
|
||||
self.crc = lookup_table[@truncate(u4, self.crc ^ (b >> 0))] ^ (self.crc >> 4);
|
||||
self.crc = lookup_table[@truncate(u4, self.crc ^ (b >> 4))] ^ (self.crc >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn final(self: &Self) u32 {
|
||||
return ~self.crc;
|
||||
}
|
||||
|
||||
pub fn hash(input: []const u8) u32 {
|
||||
var c = Self.init();
|
||||
c.update(input);
|
||||
return c.final();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test "small crc32 ieee" {
|
||||
const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE);
|
||||
|
||||
debug.assert(Crc32Ieee.hash("") == 0x00000000);
|
||||
debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43);
|
||||
debug.assert(Crc32Ieee.hash("abc") == 0x352441c2);
|
||||
}
|
||||
|
||||
test "small crc32 castagnoli" {
|
||||
const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli);
|
||||
|
||||
debug.assert(Crc32Castagnoli.hash("") == 0x00000000);
|
||||
debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330);
|
||||
debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
|
||||
}
|
60
std/hash/fnv.zig
Normal file
60
std/hash/fnv.zig
Normal file
@ -0,0 +1,60 @@
|
||||
// FNV1a - Fowler-Noll-Vo hash function
|
||||
//
|
||||
// FNV1a is a fast, non-cryptographic hash function with fairly good distribution properties.
|
||||
//
|
||||
// https://tools.ietf.org/html/draft-eastlake-fnv-14
|
||||
|
||||
const std = @import("../index.zig");
|
||||
const debug = std.debug;
|
||||
|
||||
pub const Fnv1a_32 = Fnv1a(u32, 0x01000193 , 0x811c9dc5);
|
||||
pub const Fnv1a_64 = Fnv1a(u64, 0x100000001b3, 0xcbf29ce484222325);
|
||||
pub const Fnv1a_128 = Fnv1a(u128, 0x1000000000000000000013b, 0x6c62272e07bb014262b821756295c58d);
|
||||
|
||||
fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type {
|
||||
return struct {
|
||||
const Self = this;
|
||||
|
||||
value: T,
|
||||
|
||||
pub fn init() Self {
|
||||
return Self {
|
||||
.value = offset,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn update(self: &Self, input: []const u8) void {
|
||||
for (input) |b| {
|
||||
self.value ^= b;
|
||||
self.value *%= prime;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn final(self: &Self) T {
|
||||
return self.value;
|
||||
}
|
||||
|
||||
pub fn hash(input: []const u8) T {
|
||||
var c = Self.init();
|
||||
c.update(input);
|
||||
return c.final();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test "fnv1a-32" {
|
||||
debug.assert(Fnv1a_32.hash("") == 0x811c9dc5);
|
||||
debug.assert(Fnv1a_32.hash("a") == 0xe40c292c);
|
||||
debug.assert(Fnv1a_32.hash("foobar") == 0xbf9cf968);
|
||||
}
|
||||
|
||||
test "fnv1a-64" {
|
||||
debug.assert(Fnv1a_64.hash("") == 0xcbf29ce484222325);
|
||||
debug.assert(Fnv1a_64.hash("a") == 0xaf63dc4c8601ec8c);
|
||||
debug.assert(Fnv1a_64.hash("foobar") == 0x85944171f73967e8);
|
||||
}
|
||||
|
||||
test "fnv1a-128" {
|
||||
debug.assert(Fnv1a_128.hash("") == 0x6c62272e07bb014262b821756295c58d);
|
||||
debug.assert(Fnv1a_128.hash("a") == 0xd228cb696f1a8caf78912b704e4a8964);
|
||||
}
|
22
std/hash/index.zig
Normal file
22
std/hash/index.zig
Normal file
@ -0,0 +1,22 @@
|
||||
const adler = @import("adler.zig");
|
||||
pub const Adler32 = adler.Adler32;
|
||||
|
||||
// pub for polynomials + generic crc32 construction
|
||||
pub const crc = @import("crc.zig");
|
||||
pub const Crc32 = crc.Crc32;
|
||||
|
||||
const fnv = @import("fnv.zig");
|
||||
pub const Fnv1a_32 = fnv.Fnv1a_32;
|
||||
pub const Fnv1a_64 = fnv.Fnv1a_64;
|
||||
pub const Fnv1a_128 = fnv.Fnv1a_128;
|
||||
|
||||
const siphash = @import("siphash.zig");
|
||||
pub const SipHash64 = siphash.SipHash64;
|
||||
pub const SipHash128 = siphash.SipHash128;
|
||||
|
||||
test "hash" {
|
||||
_ = @import("adler.zig");
|
||||
_ = @import("crc.zig");
|
||||
_ = @import("fnv.zig");
|
||||
_ = @import("siphash.zig");
|
||||
}
|
320
std/hash/siphash.zig
Normal file
320
std/hash/siphash.zig
Normal file
@ -0,0 +1,320 @@
|
||||
// Siphash
|
||||
//
|
||||
// SipHash is a moderately fast, non-cryptographic keyed hash function designed for resistance
|
||||
// against hash flooding DoS attacks.
|
||||
//
|
||||
// https://131002.net/siphash/
|
||||
|
||||
const std = @import("../index.zig");
|
||||
const debug = std.debug;
|
||||
const math = std.math;
|
||||
const mem = std.mem;
|
||||
|
||||
const Endian = @import("builtin").Endian;
|
||||
|
||||
pub fn SipHash64(comptime c_rounds: usize, comptime d_rounds: usize) type {
|
||||
return SipHash(u64, c_rounds, d_rounds);
|
||||
}
|
||||
|
||||
pub fn SipHash128(comptime c_rounds: usize, comptime d_rounds: usize) type {
|
||||
return SipHash(u128, c_rounds, d_rounds);
|
||||
}
|
||||
|
||||
fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type {
|
||||
debug.assert(T == u64 or T == u128);
|
||||
debug.assert(c_rounds > 0 and d_rounds > 0);
|
||||
|
||||
return struct {
|
||||
const Self = this;
|
||||
const digest_size = 64;
|
||||
const block_size = 64;
|
||||
|
||||
v0: u64,
|
||||
v1: u64,
|
||||
v2: u64,
|
||||
v3: u64,
|
||||
|
||||
// streaming cache
|
||||
buf: [8]u8,
|
||||
buf_len: usize,
|
||||
msg_len: u8,
|
||||
|
||||
pub fn init(key: []const u8) Self {
|
||||
debug.assert(key.len >= 16);
|
||||
|
||||
const k0 = mem.readInt(key[0..8], u64, Endian.Little);
|
||||
const k1 = mem.readInt(key[8..16], u64, Endian.Little);
|
||||
|
||||
var d = Self {
|
||||
.v0 = k0 ^ 0x736f6d6570736575,
|
||||
.v1 = k1 ^ 0x646f72616e646f6d,
|
||||
.v2 = k0 ^ 0x6c7967656e657261,
|
||||
.v3 = k1 ^ 0x7465646279746573,
|
||||
|
||||
.buf = undefined,
|
||||
.buf_len = 0,
|
||||
.msg_len = 0,
|
||||
};
|
||||
|
||||
if (T == u128) {
|
||||
d.v1 ^= 0xee;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
pub fn update(d: &Self, b: []const u8) void {
|
||||
var off: usize = 0;
|
||||
|
||||
// Partial from previous.
|
||||
if (d.buf_len != 0 and d.buf_len + b.len > 8) {
|
||||
off += 8 - d.buf_len;
|
||||
mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
|
||||
d.round(d.buf[0..]);
|
||||
d.buf_len = 0;
|
||||
}
|
||||
|
||||
// Full middle blocks.
|
||||
while (off + 8 <= b.len) : (off += 8) {
|
||||
d.round(b[off..off + 8]);
|
||||
}
|
||||
|
||||
// Remainder for next pass.
|
||||
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
|
||||
d.buf_len += u8(b[off..].len);
|
||||
d.msg_len +%= @truncate(u8, b.len);
|
||||
}
|
||||
|
||||
pub fn final(d: &Self) T {
|
||||
// Padding
|
||||
mem.set(u8, d.buf[d.buf_len..], 0);
|
||||
d.buf[7] = d.msg_len;
|
||||
d.round(d.buf[0..]);
|
||||
|
||||
if (T == u128) {
|
||||
d.v2 ^= 0xee;
|
||||
} else {
|
||||
d.v2 ^= 0xff;
|
||||
}
|
||||
|
||||
comptime var i: usize = 0;
|
||||
inline while (i < d_rounds) : (i += 1) {
|
||||
@inlineCall(sipRound, d);
|
||||
}
|
||||
|
||||
const b1 = d.v0 ^ d.v1 ^ d.v2 ^ d.v3;
|
||||
if (T == u64) {
|
||||
return b1;
|
||||
}
|
||||
|
||||
d.v1 ^= 0xdd;
|
||||
|
||||
comptime var j: usize = 0;
|
||||
inline while (j < d_rounds) : (j += 1) {
|
||||
@inlineCall(sipRound, d);
|
||||
}
|
||||
|
||||
const b2 = d.v0 ^ d.v1 ^ d.v2 ^ d.v3;
|
||||
return (u128(b2) << 64) | b1;
|
||||
}
|
||||
|
||||
fn round(d: &Self, b: []const u8) void {
|
||||
debug.assert(b.len == 8);
|
||||
|
||||
const m = mem.readInt(b[0..], u64, Endian.Little);
|
||||
d.v3 ^= m;
|
||||
|
||||
comptime var i: usize = 0;
|
||||
inline while (i < c_rounds) : (i += 1) {
|
||||
@inlineCall(sipRound, d);
|
||||
}
|
||||
|
||||
d.v0 ^= m;
|
||||
}
|
||||
|
||||
fn sipRound(d: &Self) void {
|
||||
d.v0 +%= d.v1;
|
||||
d.v1 = math.rotl(u64, d.v1, u64(13));
|
||||
d.v1 ^= d.v0;
|
||||
d.v0 = math.rotl(u64, d.v0, u64(32));
|
||||
d.v2 +%= d.v3;
|
||||
d.v3 = math.rotl(u64, d.v3, u64(16));
|
||||
d.v3 ^= d.v2;
|
||||
d.v0 +%= d.v3;
|
||||
d.v3 = math.rotl(u64, d.v3, u64(21));
|
||||
d.v3 ^= d.v0;
|
||||
d.v2 +%= d.v1;
|
||||
d.v1 = math.rotl(u64, d.v1, u64(17));
|
||||
d.v1 ^= d.v2;
|
||||
d.v2 = math.rotl(u64, d.v2, u64(32));
|
||||
}
|
||||
|
||||
pub fn hash(key: []const u8, input: []const u8) T {
|
||||
var c = Self.init(key);
|
||||
c.update(input);
|
||||
return c.final();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Test vectors from reference implementation.
|
||||
// https://github.com/veorq/SipHash/blob/master/vectors.h
|
||||
const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
|
||||
|
||||
test "siphash64-2-4 sanity" {
|
||||
const vectors = [][]const u8 {
|
||||
"\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
|
||||
"\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
|
||||
"\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
|
||||
"\x2d\x7e\xfb\xd7\x96\x66\x67\x85",
|
||||
"\xb7\x87\x71\x27\xe0\x94\x27\xcf",
|
||||
"\x8d\xa6\x99\xcd\x64\x55\x76\x18",
|
||||
"\xce\xe3\xfe\x58\x6e\x46\xc9\xcb",
|
||||
"\x37\xd1\x01\x8b\xf5\x00\x02\xab",
|
||||
"\x62\x24\x93\x9a\x79\xf5\xf5\x93",
|
||||
"\xb0\xe4\xa9\x0b\xdf\x82\x00\x9e",
|
||||
"\xf3\xb9\xdd\x94\xc5\xbb\x5d\x7a",
|
||||
"\xa7\xad\x6b\x22\x46\x2f\xb3\xf4",
|
||||
"\xfb\xe5\x0e\x86\xbc\x8f\x1e\x75",
|
||||
"\x90\x3d\x84\xc0\x27\x56\xea\x14",
|
||||
"\xee\xf2\x7a\x8e\x90\xca\x23\xf7",
|
||||
"\xe5\x45\xbe\x49\x61\xca\x29\xa1",
|
||||
"\xdb\x9b\xc2\x57\x7f\xcc\x2a\x3f",
|
||||
"\x94\x47\xbe\x2c\xf5\xe9\x9a\x69",
|
||||
"\x9c\xd3\x8d\x96\xf0\xb3\xc1\x4b",
|
||||
"\xbd\x61\x79\xa7\x1d\xc9\x6d\xbb",
|
||||
"\x98\xee\xa2\x1a\xf2\x5c\xd6\xbe",
|
||||
"\xc7\x67\x3b\x2e\xb0\xcb\xf2\xd0",
|
||||
"\x88\x3e\xa3\xe3\x95\x67\x53\x93",
|
||||
"\xc8\xce\x5c\xcd\x8c\x03\x0c\xa8",
|
||||
"\x94\xaf\x49\xf6\xc6\x50\xad\xb8",
|
||||
"\xea\xb8\x85\x8a\xde\x92\xe1\xbc",
|
||||
"\xf3\x15\xbb\x5b\xb8\x35\xd8\x17",
|
||||
"\xad\xcf\x6b\x07\x63\x61\x2e\x2f",
|
||||
"\xa5\xc9\x1d\xa7\xac\xaa\x4d\xde",
|
||||
"\x71\x65\x95\x87\x66\x50\xa2\xa6",
|
||||
"\x28\xef\x49\x5c\x53\xa3\x87\xad",
|
||||
"\x42\xc3\x41\xd8\xfa\x92\xd8\x32",
|
||||
"\xce\x7c\xf2\x72\x2f\x51\x27\x71",
|
||||
"\xe3\x78\x59\xf9\x46\x23\xf3\xa7",
|
||||
"\x38\x12\x05\xbb\x1a\xb0\xe0\x12",
|
||||
"\xae\x97\xa1\x0f\xd4\x34\xe0\x15",
|
||||
"\xb4\xa3\x15\x08\xbe\xff\x4d\x31",
|
||||
"\x81\x39\x62\x29\xf0\x90\x79\x02",
|
||||
"\x4d\x0c\xf4\x9e\xe5\xd4\xdc\xca",
|
||||
"\x5c\x73\x33\x6a\x76\xd8\xbf\x9a",
|
||||
"\xd0\xa7\x04\x53\x6b\xa9\x3e\x0e",
|
||||
"\x92\x59\x58\xfc\xd6\x42\x0c\xad",
|
||||
"\xa9\x15\xc2\x9b\xc8\x06\x73\x18",
|
||||
"\x95\x2b\x79\xf3\xbc\x0a\xa6\xd4",
|
||||
"\xf2\x1d\xf2\xe4\x1d\x45\x35\xf9",
|
||||
"\x87\x57\x75\x19\x04\x8f\x53\xa9",
|
||||
"\x10\xa5\x6c\xf5\xdf\xcd\x9a\xdb",
|
||||
"\xeb\x75\x09\x5c\xcd\x98\x6c\xd0",
|
||||
"\x51\xa9\xcb\x9e\xcb\xa3\x12\xe6",
|
||||
"\x96\xaf\xad\xfc\x2c\xe6\x66\xc7",
|
||||
"\x72\xfe\x52\x97\x5a\x43\x64\xee",
|
||||
"\x5a\x16\x45\xb2\x76\xd5\x92\xa1",
|
||||
"\xb2\x74\xcb\x8e\xbf\x87\x87\x0a",
|
||||
"\x6f\x9b\xb4\x20\x3d\xe7\xb3\x81",
|
||||
"\xea\xec\xb2\xa3\x0b\x22\xa8\x7f",
|
||||
"\x99\x24\xa4\x3c\xc1\x31\x57\x24",
|
||||
"\xbd\x83\x8d\x3a\xaf\xbf\x8d\xb7",
|
||||
"\x0b\x1a\x2a\x32\x65\xd5\x1a\xea",
|
||||
"\x13\x50\x79\xa3\x23\x1c\xe6\x60",
|
||||
"\x93\x2b\x28\x46\xe4\xd7\x06\x66",
|
||||
"\xe1\x91\x5f\x5c\xb1\xec\xa4\x6c",
|
||||
"\xf3\x25\x96\x5c\xa1\x6d\x62\x9f",
|
||||
"\x57\x5f\xf2\x8e\x60\x38\x1b\xe5",
|
||||
"\x72\x45\x06\xeb\x4c\x32\x8a\x95",
|
||||
};
|
||||
|
||||
const siphash = SipHash64(2, 4);
|
||||
|
||||
var buffer: [64]u8 = undefined;
|
||||
for (vectors) |vector, i| {
|
||||
buffer[i] = u8(i);
|
||||
|
||||
const expected = mem.readInt(vector, u64, Endian.Little);
|
||||
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
|
||||
}
|
||||
}
|
||||
|
||||
test "siphash128-2-4 sanity" {
|
||||
const vectors = [][]const u8 {
|
||||
"\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
|
||||
"\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
|
||||
"\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",
|
||||
"\x9c\x70\xb6\x0c\x52\x67\xa9\x4e\x5f\x33\xb6\xb0\x29\x85\xed\x51",
|
||||
"\xf8\x81\x64\xc1\x2d\x9c\x8f\xaf\x7d\x0f\x6e\x7c\x7b\xcd\x55\x79",
|
||||
"\x13\x68\x87\x59\x80\x77\x6f\x88\x54\x52\x7a\x07\x69\x0e\x96\x27",
|
||||
"\x14\xee\xca\x33\x8b\x20\x86\x13\x48\x5e\xa0\x30\x8f\xd7\xa1\x5e",
|
||||
"\xa1\xf1\xeb\xbe\xd8\xdb\xc1\x53\xc0\xb8\x4a\xa6\x1f\xf0\x82\x39",
|
||||
"\x3b\x62\xa9\xba\x62\x58\xf5\x61\x0f\x83\xe2\x64\xf3\x14\x97\xb4",
|
||||
"\x26\x44\x99\x06\x0a\xd9\xba\xab\xc4\x7f\x8b\x02\xbb\x6d\x71\xed",
|
||||
"\x00\x11\x0d\xc3\x78\x14\x69\x56\xc9\x54\x47\xd3\xf3\xd0\xfb\xba",
|
||||
"\x01\x51\xc5\x68\x38\x6b\x66\x77\xa2\xb4\xdc\x6f\x81\xe5\xdc\x18",
|
||||
"\xd6\x26\xb2\x66\x90\x5e\xf3\x58\x82\x63\x4d\xf6\x85\x32\xc1\x25",
|
||||
"\x98\x69\xe2\x47\xe9\xc0\x8b\x10\xd0\x29\x93\x4f\xc4\xb9\x52\xf7",
|
||||
"\x31\xfc\xef\xac\x66\xd7\xde\x9c\x7e\xc7\x48\x5f\xe4\x49\x49\x02",
|
||||
"\x54\x93\xe9\x99\x33\xb0\xa8\x11\x7e\x08\xec\x0f\x97\xcf\xc3\xd9",
|
||||
"\x6e\xe2\xa4\xca\x67\xb0\x54\xbb\xfd\x33\x15\xbf\x85\x23\x05\x77",
|
||||
"\x47\x3d\x06\xe8\x73\x8d\xb8\x98\x54\xc0\x66\xc4\x7a\xe4\x77\x40",
|
||||
"\xa4\x26\xe5\xe4\x23\xbf\x48\x85\x29\x4d\xa4\x81\xfe\xae\xf7\x23",
|
||||
"\x78\x01\x77\x31\xcf\x65\xfa\xb0\x74\xd5\x20\x89\x52\x51\x2e\xb1",
|
||||
"\x9e\x25\xfc\x83\x3f\x22\x90\x73\x3e\x93\x44\xa5\xe8\x38\x39\xeb",
|
||||
"\x56\x8e\x49\x5a\xbe\x52\x5a\x21\x8a\x22\x14\xcd\x3e\x07\x1d\x12",
|
||||
"\x4a\x29\xb5\x45\x52\xd1\x6b\x9a\x46\x9c\x10\x52\x8e\xff\x0a\xae",
|
||||
"\xc9\xd1\x84\xdd\xd5\xa9\xf5\xe0\xcf\x8c\xe2\x9a\x9a\xbf\x69\x1c",
|
||||
"\x2d\xb4\x79\xae\x78\xbd\x50\xd8\x88\x2a\x8a\x17\x8a\x61\x32\xad",
|
||||
"\x8e\xce\x5f\x04\x2d\x5e\x44\x7b\x50\x51\xb9\xea\xcb\x8d\x8f\x6f",
|
||||
"\x9c\x0b\x53\xb4\xb3\xc3\x07\xe8\x7e\xae\xe0\x86\x78\x14\x1f\x66",
|
||||
"\xab\xf2\x48\xaf\x69\xa6\xea\xe4\xbf\xd3\xeb\x2f\x12\x9e\xeb\x94",
|
||||
"\x06\x64\xda\x16\x68\x57\x4b\x88\xb9\x35\xf3\x02\x73\x58\xae\xf4",
|
||||
"\xaa\x4b\x9d\xc4\xbf\x33\x7d\xe9\x0c\xd4\xfd\x3c\x46\x7c\x6a\xb7",
|
||||
"\xea\x5c\x7f\x47\x1f\xaf\x6b\xde\x2b\x1a\xd7\xd4\x68\x6d\x22\x87",
|
||||
"\x29\x39\xb0\x18\x32\x23\xfa\xfc\x17\x23\xde\x4f\x52\xc4\x3d\x35",
|
||||
"\x7c\x39\x56\xca\x5e\xea\xfc\x3e\x36\x3e\x9d\x55\x65\x46\xeb\x68",
|
||||
"\x77\xc6\x07\x71\x46\xf0\x1c\x32\xb6\xb6\x9d\x5f\x4e\xa9\xff\xcf",
|
||||
"\x37\xa6\x98\x6c\xb8\x84\x7e\xdf\x09\x25\xf0\xf1\x30\x9b\x54\xde",
|
||||
"\xa7\x05\xf0\xe6\x9d\xa9\xa8\xf9\x07\x24\x1a\x2e\x92\x3c\x8c\xc8",
|
||||
"\x3d\xc4\x7d\x1f\x29\xc4\x48\x46\x1e\x9e\x76\xed\x90\x4f\x67\x11",
|
||||
"\x0d\x62\xbf\x01\xe6\xfc\x0e\x1a\x0d\x3c\x47\x51\xc5\xd3\x69\x2b",
|
||||
"\x8c\x03\x46\x8b\xca\x7c\x66\x9e\xe4\xfd\x5e\x08\x4b\xbe\xe7\xb5",
|
||||
"\x52\x8a\x5b\xb9\x3b\xaf\x2c\x9c\x44\x73\xcc\xe5\xd0\xd2\x2b\xd9",
|
||||
"\xdf\x6a\x30\x1e\x95\xc9\x5d\xad\x97\xae\x0c\xc8\xc6\x91\x3b\xd8",
|
||||
"\x80\x11\x89\x90\x2c\x85\x7f\x39\xe7\x35\x91\x28\x5e\x70\xb6\xdb",
|
||||
"\xe6\x17\x34\x6a\xc9\xc2\x31\xbb\x36\x50\xae\x34\xcc\xca\x0c\x5b",
|
||||
"\x27\xd9\x34\x37\xef\xb7\x21\xaa\x40\x18\x21\xdc\xec\x5a\xdf\x89",
|
||||
"\x89\x23\x7d\x9d\xed\x9c\x5e\x78\xd8\xb1\xc9\xb1\x66\xcc\x73\x42",
|
||||
"\x4a\x6d\x80\x91\xbf\x5e\x7d\x65\x11\x89\xfa\x94\xa2\x50\xb1\x4c",
|
||||
"\x0e\x33\xf9\x60\x55\xe7\xae\x89\x3f\xfc\x0e\x3d\xcf\x49\x29\x02",
|
||||
"\xe6\x1c\x43\x2b\x72\x0b\x19\xd1\x8e\xc8\xd8\x4b\xdc\x63\x15\x1b",
|
||||
"\xf7\xe5\xae\xf5\x49\xf7\x82\xcf\x37\x90\x55\xa6\x08\x26\x9b\x16",
|
||||
"\x43\x8d\x03\x0f\xd0\xb7\xa5\x4f\xa8\x37\xf2\xad\x20\x1a\x64\x03",
|
||||
"\xa5\x90\xd3\xee\x4f\xbf\x04\xe3\x24\x7e\x0d\x27\xf2\x86\x42\x3f",
|
||||
"\x5f\xe2\xc1\xa1\x72\xfe\x93\xc4\xb1\x5c\xd3\x7c\xae\xf9\xf5\x38",
|
||||
"\x2c\x97\x32\x5c\xbd\x06\xb3\x6e\xb2\x13\x3d\xd0\x8b\x3a\x01\x7c",
|
||||
"\x92\xc8\x14\x22\x7a\x6b\xca\x94\x9f\xf0\x65\x9f\x00\x2a\xd3\x9e",
|
||||
"\xdc\xe8\x50\x11\x0b\xd8\x32\x8c\xfb\xd5\x08\x41\xd6\x91\x1d\x87",
|
||||
"\x67\xf1\x49\x84\xc7\xda\x79\x12\x48\xe3\x2b\xb5\x92\x25\x83\xda",
|
||||
"\x19\x38\xf2\xcf\x72\xd5\x4e\xe9\x7e\x94\x16\x6f\xa9\x1d\x2a\x36",
|
||||
"\x74\x48\x1e\x96\x46\xed\x49\xfe\x0f\x62\x24\x30\x16\x04\x69\x8e",
|
||||
"\x57\xfc\xa5\xde\x98\xa9\xd6\xd8\x00\x64\x38\xd0\x58\x3d\x8a\x1d",
|
||||
"\x9f\xec\xde\x1c\xef\xdc\x1c\xbe\xd4\x76\x36\x74\xd9\x57\x53\x59",
|
||||
"\xe3\x04\x0c\x00\xeb\x28\xf1\x53\x66\xca\x73\xcb\xd8\x72\xe7\x40",
|
||||
"\x76\x97\x00\x9a\x6a\x83\x1d\xfe\xcc\xa9\x1c\x59\x93\x67\x0f\x7a",
|
||||
"\x58\x53\x54\x23\x21\xf5\x67\xa0\x05\xd5\x47\xa4\xf0\x47\x59\xbd",
|
||||
"\x51\x50\xd1\x77\x2f\x50\x83\x4a\x50\x3e\x06\x9a\x97\x3f\xbd\x7c",
|
||||
};
|
||||
|
||||
const siphash = SipHash128(2, 4);
|
||||
|
||||
var buffer: [64]u8 = undefined;
|
||||
for (vectors) |vector, i| {
|
||||
buffer[i] = u8(i);
|
||||
|
||||
const expected = mem.readInt(vector, u128, Endian.Little);
|
||||
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ pub const elf = @import("elf.zig");
|
||||
pub const empty_import = @import("empty.zig");
|
||||
pub const endian = @import("endian.zig");
|
||||
pub const fmt = @import("fmt/index.zig");
|
||||
pub const hash = @import("hash/index.zig");
|
||||
pub const heap = @import("heap.zig");
|
||||
pub const io = @import("io.zig");
|
||||
pub const macho = @import("macho.zig");
|
||||
@ -51,6 +52,7 @@ test "std" {
|
||||
_ = @import("empty.zig");
|
||||
_ = @import("endian.zig");
|
||||
_ = @import("fmt/index.zig");
|
||||
_ = @import("hash/index.zig");
|
||||
_ = @import("io.zig");
|
||||
_ = @import("macho.zig");
|
||||
_ = @import("math/index.zig");
|
||||
|
Loading…
Reference in New Issue
Block a user