authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-06 09:44:25-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-04-06 09:44:25-04:00
log7186e92c86982950d0aa7c0c2deef9ef96bc1264
treeb2c878a576c73d289189b31951ca76c8f40f80ea
parent873641c1232d0442c5924ac5ccb36710bf84d0ce
parentc34ce2cbc6ca6f623e2e6e1d444c2b51e43dc493
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #900 from zig-lang/hash-and-checksums

Add common hash/checksum functions

7 files changed, 701 insertions(+), 0 deletions(-)

CMakeLists.txt+5
......@@ -438,6 +438,11 @@ set(ZIG_STD_FILES
438438 "fmt/errol/lookup.zig"
439439 "fmt/index.zig"
440440 "hash_map.zig"
441 "hash/index.zig"
442 "hash/adler.zig"
443 "hash/crc.zig"
444 "hash/fnv.zig"
445 "hash/siphash.zig"
441446 "heap.zig"
442447 "index.zig"
443448 "io.zig"
std/hash/adler.zig created+112
......@@ -0,0 +1,112 @@
1// Adler32 checksum.
2//
3// https://tools.ietf.org/html/rfc1950#section-9
4// https://github.com/madler/zlib/blob/master/adler32.c
5
6const std = @import("../index.zig");
7const debug = std.debug;
8
9pub const Adler32 = struct {
10 const base = 65521;
11 const nmax = 5552;
12
13 adler: u32,
14
15 pub fn init() Adler32 {
16 return Adler32 {
17 .adler = 1,
18 };
19 }
20
21 // This fast variant is taken from zlib. It reduces the required modulos and unrolls longer
22 // buffer inputs and should be much quicker.
23 pub fn update(self: &Adler32, input: []const u8) void {
24 var s1 = self.adler & 0xffff;
25 var s2 = (self.adler >> 16) & 0xffff;
26
27 if (input.len == 1) {
28 s1 +%= input[0];
29 if (s1 >= base) {
30 s1 -= base;
31 }
32 s2 +%= s1;
33 if (s2 >= base) {
34 s2 -= base;
35 }
36 }
37 else if (input.len < 16) {
38 for (input) |b| {
39 s1 +%= b;
40 s2 +%= s1;
41 }
42 if (s1 >= base) {
43 s1 -= base;
44 }
45
46 s2 %= base;
47 }
48 else {
49 var i: usize = 0;
50 while (i + nmax <= input.len) : (i += nmax) {
51 const n = nmax / 16; // note: 16 | nmax
52
53 var rounds: usize = 0;
54 while (rounds < n) : (rounds += 1) {
55 comptime var j: usize = 0;
56 inline while (j < 16) : (j += 1) {
57 s1 +%= input[i + n * j];
58 s2 +%= s1;
59 }
60 }
61 }
62
63 if (i < input.len) {
64 while (i + 16 <= input.len) : (i += 16) {
65 comptime var j: usize = 0;
66 inline while (j < 16) : (j += 1) {
67 s1 +%= input[i + j];
68 s2 +%= s1;
69 }
70 }
71 while (i < input.len) : (i += 1) {
72 s1 +%= input[i];
73 s2 +%= s1;
74 }
75
76 s1 %= base;
77 s2 %= base;
78 }
79 }
80
81 self.adler = s1 | (s2 << 16);
82 }
83
84 pub fn final(self: &Adler32) u32 {
85 return self.adler;
86 }
87
88 pub fn hash(input: []const u8) u32 {
89 var c = Adler32.init();
90 c.update(input);
91 return c.final();
92 }
93};
94
95test "adler32 sanity" {
96 debug.assert(Adler32.hash("a") == 0x620062);
97 debug.assert(Adler32.hash("example") == 0xbc002ed);
98}
99
100test "adler32 long" {
101 const long1 = []u8 {1} ** 1024;
102 debug.assert(Adler32.hash(long1[0..]) == 0x06780401);
103
104 const long2 = []u8 {1} ** 1025;
105 debug.assert(Adler32.hash(long2[0..]) == 0x0a7a0402);
106}
107
108test "adler32 very long" {
109 const long = []u8 {1} ** 5553;
110 debug.assert(Adler32.hash(long[0..]) == 0x707f15b2);
111}
112
std/hash/crc.zig created+180
......@@ -0,0 +1,180 @@
1// There are two implementations of CRC32 implemented with the following key characteristics:
2//
3// - Crc32WithPoly uses 8Kb of tables but is ~10x faster than the small method.
4//
5// - Crc32SmallWithPoly uses only 64 bytes of memory but is slower. Be aware that this is
6// still moderately fast just slow relative to the slicing approach.
7
8const std = @import("../index.zig");
9const debug = std.debug;
10
11pub const Polynomial = struct {
12 const IEEE = 0xedb88320;
13 const Castagnoli = 0x82f63b78;
14 const Koopman = 0xeb31d82e;
15};
16
17// IEEE is by far the most common CRC and so is aliased by default.
18pub const Crc32 = Crc32WithPoly(Polynomial.IEEE);
19
20// slicing-by-8 crc32 implementation.
21pub fn Crc32WithPoly(comptime poly: u32) type {
22 return struct {
23 const Self = this;
24 const lookup_tables = comptime block: {
25 @setEvalBranchQuota(20000);
26 var tables: [8][256]u32 = undefined;
27
28 for (tables[0]) |*e, i| {
29 var crc = u32(i);
30 var j: usize = 0; while (j < 8) : (j += 1) {
31 if (crc & 1 == 1) {
32 crc = (crc >> 1) ^ poly;
33 } else {
34 crc = (crc >> 1);
35 }
36 }
37 *e = crc;
38 }
39
40 var i: usize = 0;
41 while (i < 256) : (i += 1) {
42 var crc = tables[0][i];
43 var j: usize = 1; while (j < 8) : (j += 1) {
44 const index = @truncate(u8, crc);
45 crc = tables[0][index] ^ (crc >> 8);
46 tables[j][i] = crc;
47 }
48 }
49
50 break :block tables;
51 };
52
53 crc: u32,
54
55 pub fn init() Self {
56 return Self {
57 .crc = 0xffffffff,
58 };
59 }
60
61 pub fn update(self: &Self, input: []const u8) void {
62 var i: usize = 0;
63 while (i + 8 <= input.len) : (i += 8) {
64 const p = input[i..i+8];
65
66 // Unrolling this way gives ~50Mb/s increase
67 self.crc ^= (u32(p[0]) << 0);
68 self.crc ^= (u32(p[1]) << 8);
69 self.crc ^= (u32(p[2]) << 16);
70 self.crc ^= (u32(p[3]) << 24);
71
72 self.crc =
73 lookup_tables[0][p[7]] ^
74 lookup_tables[1][p[6]] ^
75 lookup_tables[2][p[5]] ^
76 lookup_tables[3][p[4]] ^
77 lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
78 lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
79 lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
80 lookup_tables[7][@truncate(u8, self.crc >> 0)];
81 }
82
83 while (i < input.len) : (i += 1) {
84 const index = @truncate(u8, self.crc) ^ input[i];
85 self.crc = (self.crc >> 8) ^ lookup_tables[0][index];
86 }
87 }
88
89 pub fn final(self: &Self) u32 {
90 return ~self.crc;
91 }
92
93 pub fn hash(input: []const u8) u32 {
94 var c = Self.init();
95 c.update(input);
96 return c.final();
97 }
98 };
99}
100
101test "crc32 ieee" {
102 const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE);
103
104 debug.assert(Crc32Ieee.hash("") == 0x00000000);
105 debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43);
106 debug.assert(Crc32Ieee.hash("abc") == 0x352441c2);
107}
108
109test "crc32 castagnoli" {
110 const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli);
111
112 debug.assert(Crc32Castagnoli.hash("") == 0x00000000);
113 debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330);
114 debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
115}
116
117// half-byte lookup table implementation.
118pub fn Crc32SmallWithPoly(comptime poly: u32) type {
119 return struct {
120 const Self = this;
121 const lookup_table = comptime block: {
122 var table: [16]u32 = undefined;
123
124 for (table) |*e, i| {
125 var crc = u32(i * 16);
126 var j: usize = 0; while (j < 8) : (j += 1) {
127 if (crc & 1 == 1) {
128 crc = (crc >> 1) ^ poly;
129 } else {
130 crc = (crc >> 1);
131 }
132 }
133 *e = crc;
134 }
135
136 break :block table;
137 };
138
139 crc: u32,
140
141 pub fn init() Self {
142 return Self {
143 .crc = 0xffffffff,
144 };
145 }
146
147 pub fn update(self: &Self, input: []const u8) void {
148 for (input) |b| {
149 self.crc = lookup_table[@truncate(u4, self.crc ^ (b >> 0))] ^ (self.crc >> 4);
150 self.crc = lookup_table[@truncate(u4, self.crc ^ (b >> 4))] ^ (self.crc >> 4);
151 }
152 }
153
154 pub fn final(self: &Self) u32 {
155 return ~self.crc;
156 }
157
158 pub fn hash(input: []const u8) u32 {
159 var c = Self.init();
160 c.update(input);
161 return c.final();
162 }
163 };
164}
165
166test "small crc32 ieee" {
167 const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE);
168
169 debug.assert(Crc32Ieee.hash("") == 0x00000000);
170 debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43);
171 debug.assert(Crc32Ieee.hash("abc") == 0x352441c2);
172}
173
174test "small crc32 castagnoli" {
175 const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli);
176
177 debug.assert(Crc32Castagnoli.hash("") == 0x00000000);
178 debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330);
179 debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
180}
std/hash/fnv.zig created+60
......@@ -0,0 +1,60 @@
1// FNV1a - Fowler-Noll-Vo hash function
2//
3// FNV1a is a fast, non-cryptographic hash function with fairly good distribution properties.
4//
5// https://tools.ietf.org/html/draft-eastlake-fnv-14
6
7const std = @import("../index.zig");
8const debug = std.debug;
9
10pub const Fnv1a_32 = Fnv1a(u32, 0x01000193 , 0x811c9dc5);
11pub const Fnv1a_64 = Fnv1a(u64, 0x100000001b3, 0xcbf29ce484222325);
12pub const Fnv1a_128 = Fnv1a(u128, 0x1000000000000000000013b, 0x6c62272e07bb014262b821756295c58d);
13
14fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type {
15 return struct {
16 const Self = this;
17
18 value: T,
19
20 pub fn init() Self {
21 return Self {
22 .value = offset,
23 };
24 }
25
26 pub fn update(self: &Self, input: []const u8) void {
27 for (input) |b| {
28 self.value ^= b;
29 self.value *%= prime;
30 }
31 }
32
33 pub fn final(self: &Self) T {
34 return self.value;
35 }
36
37 pub fn hash(input: []const u8) T {
38 var c = Self.init();
39 c.update(input);
40 return c.final();
41 }
42 };
43}
44
45test "fnv1a-32" {
46 debug.assert(Fnv1a_32.hash("") == 0x811c9dc5);
47 debug.assert(Fnv1a_32.hash("a") == 0xe40c292c);
48 debug.assert(Fnv1a_32.hash("foobar") == 0xbf9cf968);
49}
50
51test "fnv1a-64" {
52 debug.assert(Fnv1a_64.hash("") == 0xcbf29ce484222325);
53 debug.assert(Fnv1a_64.hash("a") == 0xaf63dc4c8601ec8c);
54 debug.assert(Fnv1a_64.hash("foobar") == 0x85944171f73967e8);
55}
56
57test "fnv1a-128" {
58 debug.assert(Fnv1a_128.hash("") == 0x6c62272e07bb014262b821756295c58d);
59 debug.assert(Fnv1a_128.hash("a") == 0xd228cb696f1a8caf78912b704e4a8964);
60}
std/hash/index.zig created+22
......@@ -0,0 +1,22 @@
1const adler = @import("adler.zig");
2pub const Adler32 = adler.Adler32;
3
4// pub for polynomials + generic crc32 construction
5pub const crc = @import("crc.zig");
6pub const Crc32 = crc.Crc32;
7
8const fnv = @import("fnv.zig");
9pub const Fnv1a_32 = fnv.Fnv1a_32;
10pub const Fnv1a_64 = fnv.Fnv1a_64;
11pub const Fnv1a_128 = fnv.Fnv1a_128;
12
13const siphash = @import("siphash.zig");
14pub const SipHash64 = siphash.SipHash64;
15pub const SipHash128 = siphash.SipHash128;
16
17test "hash" {
18 _ = @import("adler.zig");
19 _ = @import("crc.zig");
20 _ = @import("fnv.zig");
21 _ = @import("siphash.zig");
22}
std/hash/siphash.zig created+320
......@@ -0,0 +1,320 @@
1// Siphash
2//
3// SipHash is a moderately fast, non-cryptographic keyed hash function designed for resistance
4// against hash flooding DoS attacks.
5//
6// https://131002.net/siphash/
7
8const std = @import("../index.zig");
9const debug = std.debug;
10const math = std.math;
11const mem = std.mem;
12
13const Endian = @import("builtin").Endian;
14
15pub fn SipHash64(comptime c_rounds: usize, comptime d_rounds: usize) type {
16 return SipHash(u64, c_rounds, d_rounds);
17}
18
19pub fn SipHash128(comptime c_rounds: usize, comptime d_rounds: usize) type {
20 return SipHash(u128, c_rounds, d_rounds);
21}
22
23fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type {
24 debug.assert(T == u64 or T == u128);
25 debug.assert(c_rounds > 0 and d_rounds > 0);
26
27 return struct {
28 const Self = this;
29 const digest_size = 64;
30 const block_size = 64;
31
32 v0: u64,
33 v1: u64,
34 v2: u64,
35 v3: u64,
36
37 // streaming cache
38 buf: [8]u8,
39 buf_len: usize,
40 msg_len: u8,
41
42 pub fn init(key: []const u8) Self {
43 debug.assert(key.len >= 16);
44
45 const k0 = mem.readInt(key[0..8], u64, Endian.Little);
46 const k1 = mem.readInt(key[8..16], u64, Endian.Little);
47
48 var d = Self {
49 .v0 = k0 ^ 0x736f6d6570736575,
50 .v1 = k1 ^ 0x646f72616e646f6d,
51 .v2 = k0 ^ 0x6c7967656e657261,
52 .v3 = k1 ^ 0x7465646279746573,
53
54 .buf = undefined,
55 .buf_len = 0,
56 .msg_len = 0,
57 };
58
59 if (T == u128) {
60 d.v1 ^= 0xee;
61 }
62
63 return d;
64 }
65
66 pub fn update(d: &Self, b: []const u8) void {
67 var off: usize = 0;
68
69 // Partial from previous.
70 if (d.buf_len != 0 and d.buf_len + b.len > 8) {
71 off += 8 - d.buf_len;
72 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
73 d.round(d.buf[0..]);
74 d.buf_len = 0;
75 }
76
77 // Full middle blocks.
78 while (off + 8 <= b.len) : (off += 8) {
79 d.round(b[off..off + 8]);
80 }
81
82 // Remainder for next pass.
83 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
84 d.buf_len += u8(b[off..].len);
85 d.msg_len +%= @truncate(u8, b.len);
86 }
87
88 pub fn final(d: &Self) T {
89 // Padding
90 mem.set(u8, d.buf[d.buf_len..], 0);
91 d.buf[7] = d.msg_len;
92 d.round(d.buf[0..]);
93
94 if (T == u128) {
95 d.v2 ^= 0xee;
96 } else {
97 d.v2 ^= 0xff;
98 }
99
100 comptime var i: usize = 0;
101 inline while (i < d_rounds) : (i += 1) {
102 @inlineCall(sipRound, d);
103 }
104
105 const b1 = d.v0 ^ d.v1 ^ d.v2 ^ d.v3;
106 if (T == u64) {
107 return b1;
108 }
109
110 d.v1 ^= 0xdd;
111
112 comptime var j: usize = 0;
113 inline while (j < d_rounds) : (j += 1) {
114 @inlineCall(sipRound, d);
115 }
116
117 const b2 = d.v0 ^ d.v1 ^ d.v2 ^ d.v3;
118 return (u128(b2) << 64) | b1;
119 }
120
121 fn round(d: &Self, b: []const u8) void {
122 debug.assert(b.len == 8);
123
124 const m = mem.readInt(b[0..], u64, Endian.Little);
125 d.v3 ^= m;
126
127 comptime var i: usize = 0;
128 inline while (i < c_rounds) : (i += 1) {
129 @inlineCall(sipRound, d);
130 }
131
132 d.v0 ^= m;
133 }
134
135 fn sipRound(d: &Self) void {
136 d.v0 +%= d.v1;
137 d.v1 = math.rotl(u64, d.v1, u64(13));
138 d.v1 ^= d.v0;
139 d.v0 = math.rotl(u64, d.v0, u64(32));
140 d.v2 +%= d.v3;
141 d.v3 = math.rotl(u64, d.v3, u64(16));
142 d.v3 ^= d.v2;
143 d.v0 +%= d.v3;
144 d.v3 = math.rotl(u64, d.v3, u64(21));
145 d.v3 ^= d.v0;
146 d.v2 +%= d.v1;
147 d.v1 = math.rotl(u64, d.v1, u64(17));
148 d.v1 ^= d.v2;
149 d.v2 = math.rotl(u64, d.v2, u64(32));
150 }
151
152 pub fn hash(key: []const u8, input: []const u8) T {
153 var c = Self.init(key);
154 c.update(input);
155 return c.final();
156 }
157 };
158}
159
160// Test vectors from reference implementation.
161// https://github.com/veorq/SipHash/blob/master/vectors.h
162const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
163
164test "siphash64-2-4 sanity" {
165 const vectors = [][]const u8 {
166 "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
167 "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
168 "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
169 "\x2d\x7e\xfb\xd7\x96\x66\x67\x85",
170 "\xb7\x87\x71\x27\xe0\x94\x27\xcf",
171 "\x8d\xa6\x99\xcd\x64\x55\x76\x18",
172 "\xce\xe3\xfe\x58\x6e\x46\xc9\xcb",
173 "\x37\xd1\x01\x8b\xf5\x00\x02\xab",
174 "\x62\x24\x93\x9a\x79\xf5\xf5\x93",
175 "\xb0\xe4\xa9\x0b\xdf\x82\x00\x9e",
176 "\xf3\xb9\xdd\x94\xc5\xbb\x5d\x7a",
177 "\xa7\xad\x6b\x22\x46\x2f\xb3\xf4",
178 "\xfb\xe5\x0e\x86\xbc\x8f\x1e\x75",
179 "\x90\x3d\x84\xc0\x27\x56\xea\x14",
180 "\xee\xf2\x7a\x8e\x90\xca\x23\xf7",
181 "\xe5\x45\xbe\x49\x61\xca\x29\xa1",
182 "\xdb\x9b\xc2\x57\x7f\xcc\x2a\x3f",
183 "\x94\x47\xbe\x2c\xf5\xe9\x9a\x69",
184 "\x9c\xd3\x8d\x96\xf0\xb3\xc1\x4b",
185 "\xbd\x61\x79\xa7\x1d\xc9\x6d\xbb",
186 "\x98\xee\xa2\x1a\xf2\x5c\xd6\xbe",
187 "\xc7\x67\x3b\x2e\xb0\xcb\xf2\xd0",
188 "\x88\x3e\xa3\xe3\x95\x67\x53\x93",
189 "\xc8\xce\x5c\xcd\x8c\x03\x0c\xa8",
190 "\x94\xaf\x49\xf6\xc6\x50\xad\xb8",
191 "\xea\xb8\x85\x8a\xde\x92\xe1\xbc",
192 "\xf3\x15\xbb\x5b\xb8\x35\xd8\x17",
193 "\xad\xcf\x6b\x07\x63\x61\x2e\x2f",
194 "\xa5\xc9\x1d\xa7\xac\xaa\x4d\xde",
195 "\x71\x65\x95\x87\x66\x50\xa2\xa6",
196 "\x28\xef\x49\x5c\x53\xa3\x87\xad",
197 "\x42\xc3\x41\xd8\xfa\x92\xd8\x32",
198 "\xce\x7c\xf2\x72\x2f\x51\x27\x71",
199 "\xe3\x78\x59\xf9\x46\x23\xf3\xa7",
200 "\x38\x12\x05\xbb\x1a\xb0\xe0\x12",
201 "\xae\x97\xa1\x0f\xd4\x34\xe0\x15",
202 "\xb4\xa3\x15\x08\xbe\xff\x4d\x31",
203 "\x81\x39\x62\x29\xf0\x90\x79\x02",
204 "\x4d\x0c\xf4\x9e\xe5\xd4\xdc\xca",
205 "\x5c\x73\x33\x6a\x76\xd8\xbf\x9a",
206 "\xd0\xa7\x04\x53\x6b\xa9\x3e\x0e",
207 "\x92\x59\x58\xfc\xd6\x42\x0c\xad",
208 "\xa9\x15\xc2\x9b\xc8\x06\x73\x18",
209 "\x95\x2b\x79\xf3\xbc\x0a\xa6\xd4",
210 "\xf2\x1d\xf2\xe4\x1d\x45\x35\xf9",
211 "\x87\x57\x75\x19\x04\x8f\x53\xa9",
212 "\x10\xa5\x6c\xf5\xdf\xcd\x9a\xdb",
213 "\xeb\x75\x09\x5c\xcd\x98\x6c\xd0",
214 "\x51\xa9\xcb\x9e\xcb\xa3\x12\xe6",
215 "\x96\xaf\xad\xfc\x2c\xe6\x66\xc7",
216 "\x72\xfe\x52\x97\x5a\x43\x64\xee",
217 "\x5a\x16\x45\xb2\x76\xd5\x92\xa1",
218 "\xb2\x74\xcb\x8e\xbf\x87\x87\x0a",
219 "\x6f\x9b\xb4\x20\x3d\xe7\xb3\x81",
220 "\xea\xec\xb2\xa3\x0b\x22\xa8\x7f",
221 "\x99\x24\xa4\x3c\xc1\x31\x57\x24",
222 "\xbd\x83\x8d\x3a\xaf\xbf\x8d\xb7",
223 "\x0b\x1a\x2a\x32\x65\xd5\x1a\xea",
224 "\x13\x50\x79\xa3\x23\x1c\xe6\x60",
225 "\x93\x2b\x28\x46\xe4\xd7\x06\x66",
226 "\xe1\x91\x5f\x5c\xb1\xec\xa4\x6c",
227 "\xf3\x25\x96\x5c\xa1\x6d\x62\x9f",
228 "\x57\x5f\xf2\x8e\x60\x38\x1b\xe5",
229 "\x72\x45\x06\xeb\x4c\x32\x8a\x95",
230 };
231
232 const siphash = SipHash64(2, 4);
233
234 var buffer: [64]u8 = undefined;
235 for (vectors) |vector, i| {
236 buffer[i] = u8(i);
237
238 const expected = mem.readInt(vector, u64, Endian.Little);
239 debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
240 }
241}
242
243test "siphash128-2-4 sanity" {
244 const vectors = [][]const u8 {
245 "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
246 "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
247 "\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",
248 "\x9c\x70\xb6\x0c\x52\x67\xa9\x4e\x5f\x33\xb6\xb0\x29\x85\xed\x51",
249 "\xf8\x81\x64\xc1\x2d\x9c\x8f\xaf\x7d\x0f\x6e\x7c\x7b\xcd\x55\x79",
250 "\x13\x68\x87\x59\x80\x77\x6f\x88\x54\x52\x7a\x07\x69\x0e\x96\x27",
251 "\x14\xee\xca\x33\x8b\x20\x86\x13\x48\x5e\xa0\x30\x8f\xd7\xa1\x5e",
252 "\xa1\xf1\xeb\xbe\xd8\xdb\xc1\x53\xc0\xb8\x4a\xa6\x1f\xf0\x82\x39",
253 "\x3b\x62\xa9\xba\x62\x58\xf5\x61\x0f\x83\xe2\x64\xf3\x14\x97\xb4",
254 "\x26\x44\x99\x06\x0a\xd9\xba\xab\xc4\x7f\x8b\x02\xbb\x6d\x71\xed",
255 "\x00\x11\x0d\xc3\x78\x14\x69\x56\xc9\x54\x47\xd3\xf3\xd0\xfb\xba",
256 "\x01\x51\xc5\x68\x38\x6b\x66\x77\xa2\xb4\xdc\x6f\x81\xe5\xdc\x18",
257 "\xd6\x26\xb2\x66\x90\x5e\xf3\x58\x82\x63\x4d\xf6\x85\x32\xc1\x25",
258 "\x98\x69\xe2\x47\xe9\xc0\x8b\x10\xd0\x29\x93\x4f\xc4\xb9\x52\xf7",
259 "\x31\xfc\xef\xac\x66\xd7\xde\x9c\x7e\xc7\x48\x5f\xe4\x49\x49\x02",
260 "\x54\x93\xe9\x99\x33\xb0\xa8\x11\x7e\x08\xec\x0f\x97\xcf\xc3\xd9",
261 "\x6e\xe2\xa4\xca\x67\xb0\x54\xbb\xfd\x33\x15\xbf\x85\x23\x05\x77",
262 "\x47\x3d\x06\xe8\x73\x8d\xb8\x98\x54\xc0\x66\xc4\x7a\xe4\x77\x40",
263 "\xa4\x26\xe5\xe4\x23\xbf\x48\x85\x29\x4d\xa4\x81\xfe\xae\xf7\x23",
264 "\x78\x01\x77\x31\xcf\x65\xfa\xb0\x74\xd5\x20\x89\x52\x51\x2e\xb1",
265 "\x9e\x25\xfc\x83\x3f\x22\x90\x73\x3e\x93\x44\xa5\xe8\x38\x39\xeb",
266 "\x56\x8e\x49\x5a\xbe\x52\x5a\x21\x8a\x22\x14\xcd\x3e\x07\x1d\x12",
267 "\x4a\x29\xb5\x45\x52\xd1\x6b\x9a\x46\x9c\x10\x52\x8e\xff\x0a\xae",
268 "\xc9\xd1\x84\xdd\xd5\xa9\xf5\xe0\xcf\x8c\xe2\x9a\x9a\xbf\x69\x1c",
269 "\x2d\xb4\x79\xae\x78\xbd\x50\xd8\x88\x2a\x8a\x17\x8a\x61\x32\xad",
270 "\x8e\xce\x5f\x04\x2d\x5e\x44\x7b\x50\x51\xb9\xea\xcb\x8d\x8f\x6f",
271 "\x9c\x0b\x53\xb4\xb3\xc3\x07\xe8\x7e\xae\xe0\x86\x78\x14\x1f\x66",
272 "\xab\xf2\x48\xaf\x69\xa6\xea\xe4\xbf\xd3\xeb\x2f\x12\x9e\xeb\x94",
273 "\x06\x64\xda\x16\x68\x57\x4b\x88\xb9\x35\xf3\x02\x73\x58\xae\xf4",
274 "\xaa\x4b\x9d\xc4\xbf\x33\x7d\xe9\x0c\xd4\xfd\x3c\x46\x7c\x6a\xb7",
275 "\xea\x5c\x7f\x47\x1f\xaf\x6b\xde\x2b\x1a\xd7\xd4\x68\x6d\x22\x87",
276 "\x29\x39\xb0\x18\x32\x23\xfa\xfc\x17\x23\xde\x4f\x52\xc4\x3d\x35",
277 "\x7c\x39\x56\xca\x5e\xea\xfc\x3e\x36\x3e\x9d\x55\x65\x46\xeb\x68",
278 "\x77\xc6\x07\x71\x46\xf0\x1c\x32\xb6\xb6\x9d\x5f\x4e\xa9\xff\xcf",
279 "\x37\xa6\x98\x6c\xb8\x84\x7e\xdf\x09\x25\xf0\xf1\x30\x9b\x54\xde",
280 "\xa7\x05\xf0\xe6\x9d\xa9\xa8\xf9\x07\x24\x1a\x2e\x92\x3c\x8c\xc8",
281 "\x3d\xc4\x7d\x1f\x29\xc4\x48\x46\x1e\x9e\x76\xed\x90\x4f\x67\x11",
282 "\x0d\x62\xbf\x01\xe6\xfc\x0e\x1a\x0d\x3c\x47\x51\xc5\xd3\x69\x2b",
283 "\x8c\x03\x46\x8b\xca\x7c\x66\x9e\xe4\xfd\x5e\x08\x4b\xbe\xe7\xb5",
284 "\x52\x8a\x5b\xb9\x3b\xaf\x2c\x9c\x44\x73\xcc\xe5\xd0\xd2\x2b\xd9",
285 "\xdf\x6a\x30\x1e\x95\xc9\x5d\xad\x97\xae\x0c\xc8\xc6\x91\x3b\xd8",
286 "\x80\x11\x89\x90\x2c\x85\x7f\x39\xe7\x35\x91\x28\x5e\x70\xb6\xdb",
287 "\xe6\x17\x34\x6a\xc9\xc2\x31\xbb\x36\x50\xae\x34\xcc\xca\x0c\x5b",
288 "\x27\xd9\x34\x37\xef\xb7\x21\xaa\x40\x18\x21\xdc\xec\x5a\xdf\x89",
289 "\x89\x23\x7d\x9d\xed\x9c\x5e\x78\xd8\xb1\xc9\xb1\x66\xcc\x73\x42",
290 "\x4a\x6d\x80\x91\xbf\x5e\x7d\x65\x11\x89\xfa\x94\xa2\x50\xb1\x4c",
291 "\x0e\x33\xf9\x60\x55\xe7\xae\x89\x3f\xfc\x0e\x3d\xcf\x49\x29\x02",
292 "\xe6\x1c\x43\x2b\x72\x0b\x19\xd1\x8e\xc8\xd8\x4b\xdc\x63\x15\x1b",
293 "\xf7\xe5\xae\xf5\x49\xf7\x82\xcf\x37\x90\x55\xa6\x08\x26\x9b\x16",
294 "\x43\x8d\x03\x0f\xd0\xb7\xa5\x4f\xa8\x37\xf2\xad\x20\x1a\x64\x03",
295 "\xa5\x90\xd3\xee\x4f\xbf\x04\xe3\x24\x7e\x0d\x27\xf2\x86\x42\x3f",
296 "\x5f\xe2\xc1\xa1\x72\xfe\x93\xc4\xb1\x5c\xd3\x7c\xae\xf9\xf5\x38",
297 "\x2c\x97\x32\x5c\xbd\x06\xb3\x6e\xb2\x13\x3d\xd0\x8b\x3a\x01\x7c",
298 "\x92\xc8\x14\x22\x7a\x6b\xca\x94\x9f\xf0\x65\x9f\x00\x2a\xd3\x9e",
299 "\xdc\xe8\x50\x11\x0b\xd8\x32\x8c\xfb\xd5\x08\x41\xd6\x91\x1d\x87",
300 "\x67\xf1\x49\x84\xc7\xda\x79\x12\x48\xe3\x2b\xb5\x92\x25\x83\xda",
301 "\x19\x38\xf2\xcf\x72\xd5\x4e\xe9\x7e\x94\x16\x6f\xa9\x1d\x2a\x36",
302 "\x74\x48\x1e\x96\x46\xed\x49\xfe\x0f\x62\x24\x30\x16\x04\x69\x8e",
303 "\x57\xfc\xa5\xde\x98\xa9\xd6\xd8\x00\x64\x38\xd0\x58\x3d\x8a\x1d",
304 "\x9f\xec\xde\x1c\xef\xdc\x1c\xbe\xd4\x76\x36\x74\xd9\x57\x53\x59",
305 "\xe3\x04\x0c\x00\xeb\x28\xf1\x53\x66\xca\x73\xcb\xd8\x72\xe7\x40",
306 "\x76\x97\x00\x9a\x6a\x83\x1d\xfe\xcc\xa9\x1c\x59\x93\x67\x0f\x7a",
307 "\x58\x53\x54\x23\x21\xf5\x67\xa0\x05\xd5\x47\xa4\xf0\x47\x59\xbd",
308 "\x51\x50\xd1\x77\x2f\x50\x83\x4a\x50\x3e\x06\x9a\x97\x3f\xbd\x7c",
309 };
310
311 const siphash = SipHash128(2, 4);
312
313 var buffer: [64]u8 = undefined;
314 for (vectors) |vector, i| {
315 buffer[i] = u8(i);
316
317 const expected = mem.readInt(vector, u128, Endian.Little);
318 debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
319 }
320}
std/index.zig+2
......@@ -19,6 +19,7 @@ pub const elf = @import("elf.zig");
1919pub const empty_import = @import("empty.zig");
2020pub const endian = @import("endian.zig");
2121pub const fmt = @import("fmt/index.zig");
22pub const hash = @import("hash/index.zig");
2223pub const heap = @import("heap.zig");
2324pub const io = @import("io.zig");
2425pub const macho = @import("macho.zig");
......@@ -51,6 +52,7 @@ test "std" {
5152 _ = @import("empty.zig");
5253 _ = @import("endian.zig");
5354 _ = @import("fmt/index.zig");
55 _ = @import("hash/index.zig");
5456 _ = @import("io.zig");
5557 _ = @import("macho.zig");
5658 _ = @import("math/index.zig");