authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-13 00:00:33-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-01-13 00:00:33-05:00
loga2315cfbfcfe33a2b9010994a1da6674854151e9
treed509b0494776da54c78aa299d4679cf4f17180e0
parent3268276b58d8b65cb295b738d7c14174005bd84e
parent51fdbf7f8c282c7b91a688c9069b363e90bedf6e
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #686 from zig-lang/md5-sha1

Add Md5 and Sha1 functions

6 files changed, 583 insertions(+), 0 deletions(-)

CMakeLists.txt+3
......@@ -364,6 +364,9 @@ set(ZIG_STD_FILES
364364 "c/index.zig"
365365 "c/linux.zig"
366366 "c/windows.zig"
367 "crypto/index.zig"
368 "crypto/md5.zig"
369 "crypto/sha1.zig"
367370 "cstr.zig"
368371 "debug/failing_allocator.zig"
369372 "debug/index.zig"
std/crypto/index.zig created+7
......@@ -0,0 +1,7 @@
1pub const Sha1 = @import("md5.zig").Sha1;
2pub const Md5 = @import("sha1.zig").Md5;
3
4test "crypto" {
5 _ = @import("md5.zig");
6 _ = @import("sha1.zig");
7}
std/crypto/md5.zig created+252
......@@ -0,0 +1,252 @@
1const mem = @import("../mem.zig");
2const math = @import("../math/index.zig");
3const endian = @import("../endian.zig");
4const debug = @import("../debug/index.zig");
5
6const RoundParam = struct {
7 a: u32, b: u32, c: u32, d: u32,
8 k: u32, s: u32, t: u32
9};
10
11fn Rp(a: u32, b: u32, c: u32, d: u32, k: u32, s: u5, t: u32) -> RoundParam {
12 return RoundParam { .a = a, .b = b, .c = c, .d = d, .k = k, .s = s, .t = t };
13}
14
15/// const hash1 = Md5.hash("my input");
16///
17/// const hasher = Md5.init();
18/// hasher.update("my ");
19/// hasher.update("input");
20/// const hash2 = hasher.final();
21pub const Md5 = struct {
22 const Self = this;
23
24 s: [4]u32,
25 // Streaming Cache
26 buf: [64]u8,
27 buf_len: u8,
28 total_len: u64,
29
30 pub fn init() -> Self {
31 var d: Self = undefined;
32 d.reset();
33 return d;
34 }
35
36 pub fn reset(d: &Self) {
37 d.s[0] = 0x67452301;
38 d.s[1] = 0xEFCDAB89;
39 d.s[2] = 0x98BADCFE;
40 d.s[3] = 0x10325476;
41 d.buf_len = 0;
42 d.total_len = 0;
43 }
44
45 pub fn hash(b: []const u8) -> u128 {
46 var d = Md5.init();
47 d.update(b);
48 return d.final();
49 }
50
51 pub fn update(d: &Self, b: []const u8) {
52 var off: usize = 0;
53
54 // Partial buffer exists from previous update. Copy into buffer then hash.
55 if (d.buf_len != 0 and d.buf_len + b.len > 64) {
56 off += 64 - d.buf_len;
57 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
58
59 d.round(d.buf[0..]);
60 d.buf_len = 0;
61 }
62
63 // Full middle blocks.
64 while (off + 64 < b.len) : (off += 64) {
65 d.round(b[off..off + 64]);
66 }
67
68 // Copy any remainder for next pass.
69 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
70 d.buf_len += u8(b[off..].len);
71
72 d.total_len += b.len;
73 }
74
75 pub fn final(d: &Self) -> u128 {
76 // The buffer here will never be completely full.
77 mem.set(u8, d.buf[d.buf_len..], 0);
78
79 // Append padding bits.
80 d.buf[d.buf_len] = 0x80;
81 d.buf_len += 1;
82
83 // > 448 mod 512 so need to add an extra round to wrap around.
84 if (64 - d.buf_len < 8) {
85 d.round(d.buf[0..]);
86 mem.set(u8, d.buf[0..], 0);
87 }
88
89 // Append message length.
90 var i: usize = 1;
91 var len = d.total_len >> 5;
92 d.buf[56] = u8(d.total_len & 0x1f) << 3;
93 while (i < 8) : (i += 1) {
94 d.buf[56 + i] = u8(len & 0xff);
95 len >>= 8;
96 }
97
98 d.round(d.buf[0..]);
99
100 const r =
101 (u128(d.s[3]) << 96) |
102 (u128(d.s[2]) << 64) |
103 (u128(d.s[1]) << 32) |
104 (u128(d.s[0]) << 0);
105
106 return endian.swapIfLe(u128, r);
107 }
108
109 fn round(d: &Self, b: []const u8) {
110 debug.assert(b.len == 64);
111
112 var s: [16]u32 = undefined;
113
114 // ERROR: cannot unroll this at comptime
115 var i: usize = 0;
116 while (i < 16) : (i += 1) {
117 // NOTE: Performing or's separately improves perf by ~10%
118 s[i] = 0;
119 s[i] |= u32(b[i*4+0]);
120 s[i] |= u32(b[i*4+1]) << 8;
121 s[i] |= u32(b[i*4+2]) << 16;
122 s[i] |= u32(b[i*4+3]) << 24;
123 }
124
125 var v: [4]u32 = []u32 {
126 d.s[0], d.s[1], d.s[2], d.s[3],
127 };
128
129 const round0 = comptime []RoundParam {
130 Rp(0, 1, 2, 3, 0, 7, 0xD76AA478),
131 Rp(3, 0, 1, 2, 1, 12, 0xE8C7B756),
132 Rp(2, 3, 0, 1, 2, 17, 0x242070DB),
133 Rp(1, 2, 3, 0, 3, 22, 0xC1BDCEEE),
134 Rp(0, 1, 2, 3, 4, 7, 0xF57C0FAF),
135 Rp(3, 0, 1, 2, 5, 12, 0x4787C62A),
136 Rp(2, 3, 0, 1, 6, 17, 0xA8304613),
137 Rp(1, 2, 3, 0, 7, 22, 0xFD469501),
138 Rp(0, 1, 2, 3, 8, 7, 0x698098D8),
139 Rp(3, 0, 1, 2, 9, 12, 0x8B44F7AF),
140 Rp(2, 3, 0, 1, 10, 17, 0xFFFF5BB1),
141 Rp(1, 2, 3, 0, 11, 22, 0x895CD7BE),
142 Rp(0, 1, 2, 3, 12, 7, 0x6B901122),
143 Rp(3, 0, 1, 2, 13, 12, 0xFD987193),
144 Rp(2, 3, 0, 1, 14, 17, 0xA679438E),
145 Rp(1, 2, 3, 0, 15, 22, 0x49B40821),
146 };
147 inline for (round0) |r| {
148 v[r.a] = v[r.a] +% (v[r.d] ^ (v[r.b] & (v[r.c] ^ v[r.d]))) +% r.t +% s[r.k];
149 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
150 }
151
152 const round1 = comptime []RoundParam {
153 Rp(0, 1, 2, 3, 1, 5, 0xF61E2562),
154 Rp(3, 0, 1, 2, 6, 9, 0xC040B340),
155 Rp(2, 3, 0, 1, 11, 14, 0x265E5A51),
156 Rp(1, 2, 3, 0, 0, 20, 0xE9B6C7AA),
157 Rp(0, 1, 2, 3, 5, 5, 0xD62F105D),
158 Rp(3, 0, 1, 2, 10, 9, 0x02441453),
159 Rp(2, 3, 0, 1, 15, 14, 0xD8A1E681),
160 Rp(1, 2, 3, 0, 4, 20, 0xE7D3FBC8),
161 Rp(0, 1, 2, 3, 9, 5, 0x21E1CDE6),
162 Rp(3, 0, 1, 2, 14, 9, 0xC33707D6),
163 Rp(2, 3, 0, 1, 3, 14, 0xF4D50D87),
164 Rp(1, 2, 3, 0, 8, 20, 0x455A14ED),
165 Rp(0, 1, 2, 3, 13, 5, 0xA9E3E905),
166 Rp(3, 0, 1, 2, 2, 9, 0xFCEFA3F8),
167 Rp(2, 3, 0, 1, 7, 14, 0x676F02D9),
168 Rp(1, 2, 3, 0, 12, 20, 0x8D2A4C8A),
169 };
170 inline for (round1) |r| {
171 v[r.a] = v[r.a] +% (v[r.c] ^ (v[r.d] & (v[r.b] ^ v[r.c]))) +% r.t +% s[r.k];
172 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
173 }
174
175 const round2 = comptime []RoundParam {
176 Rp(0, 1, 2, 3, 5, 4, 0xFFFA3942),
177 Rp(3, 0, 1, 2, 8, 11, 0x8771F681),
178 Rp(2, 3, 0, 1, 11, 16, 0x6D9D6122),
179 Rp(1, 2, 3, 0, 14, 23, 0xFDE5380C),
180 Rp(0, 1, 2, 3, 1, 4, 0xA4BEEA44),
181 Rp(3, 0, 1, 2, 4, 11, 0x4BDECFA9),
182 Rp(2, 3, 0, 1, 7, 16, 0xF6BB4B60),
183 Rp(1, 2, 3, 0, 10, 23, 0xBEBFBC70),
184 Rp(0, 1, 2, 3, 13, 4, 0x289B7EC6),
185 Rp(3, 0, 1, 2, 0, 11, 0xEAA127FA),
186 Rp(2, 3, 0, 1, 3, 16, 0xD4EF3085),
187 Rp(1, 2, 3, 0, 6, 23, 0x04881D05),
188 Rp(0, 1, 2, 3, 9, 4, 0xD9D4D039),
189 Rp(3, 0, 1, 2, 12, 11, 0xE6DB99E5),
190 Rp(2, 3, 0, 1, 15, 16, 0x1FA27CF8),
191 Rp(1, 2, 3, 0, 2, 23, 0xC4AC5665),
192 };
193 inline for (round2) |r| {
194 v[r.a] = v[r.a] +% (v[r.b] ^ v[r.c] ^ v[r.d]) +% r.t +% s[r.k];
195 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
196 }
197
198 const round3 = comptime []RoundParam {
199 Rp(0, 1, 2, 3, 0, 6, 0xF4292244),
200 Rp(3, 0, 1, 2, 7, 10, 0x432AFF97),
201 Rp(2, 3, 0, 1, 14, 15, 0xAB9423A7),
202 Rp(1, 2, 3, 0, 5, 21, 0xFC93A039),
203 Rp(0, 1, 2, 3, 12, 6, 0x655B59C3),
204 Rp(3, 0, 1, 2, 3, 10, 0x8F0CCC92),
205 Rp(2, 3, 0, 1, 10, 15, 0xFFEFF47D),
206 Rp(1, 2, 3, 0, 1, 21, 0x85845DD1),
207 Rp(0, 1, 2, 3, 8, 6, 0x6FA87E4F),
208 Rp(3, 0, 1, 2, 15, 10, 0xFE2CE6E0),
209 Rp(2, 3, 0, 1, 6, 15, 0xA3014314),
210 Rp(1, 2, 3, 0, 13, 21, 0x4E0811A1),
211 Rp(0, 1, 2, 3, 4, 6, 0xF7537E82),
212 Rp(3, 0, 1, 2, 11, 10, 0xBD3AF235),
213 Rp(2, 3, 0, 1, 2, 15, 0x2AD7D2BB),
214 Rp(1, 2, 3, 0, 9, 21, 0xEB86D391),
215 };
216 inline for (round3) |r| {
217 v[r.a] = v[r.a] +% (v[r.c] ^ (v[r.b] | ~v[r.d])) +% r.t +% s[r.k];
218 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
219 }
220
221 d.s[0] +%= v[0];
222 d.s[1] +%= v[1];
223 d.s[2] +%= v[2];
224 d.s[3] +%= v[3];
225 }
226};
227
228test "md5 single" {
229 debug.assert(0xd41d8cd98f00b204e9800998ecf8427e == Md5.hash(""));
230 debug.assert(0x0cc175b9c0f1b6a831c399e269772661 == Md5.hash("a"));
231 debug.assert(0x900150983cd24fb0d6963f7d28e17f72 == Md5.hash("abc"));
232 debug.assert(0xf96b697d7cb7938d525a2f31aaf161d0 == Md5.hash("message digest"));
233 debug.assert(0xc3fcd3d76192e4007dfb496cca67e13b == Md5.hash("abcdefghijklmnopqrstuvwxyz"));
234 debug.assert(0xd174ab98d277d9f5a5611c2c9f419d9f == Md5.hash("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"));
235 debug.assert(0x57edf4a22be3c955ac49da2e2107b67a == Md5.hash("12345678901234567890123456789012345678901234567890123456789012345678901234567890"));
236}
237
238test "md5 streaming" {
239 var h = Md5.init();
240
241 debug.assert(0xd41d8cd98f00b204e9800998ecf8427e == h.final());
242
243 h.reset();
244 h.update("abc");
245 debug.assert(0x900150983cd24fb0d6963f7d28e17f72 == h.final());
246
247 h.reset();
248 h.update("a");
249 h.update("b");
250 h.update("c");
251 debug.assert(0x900150983cd24fb0d6963f7d28e17f72 == h.final());
252}
std/crypto/sha1.zig created+280
......@@ -0,0 +1,280 @@
1const mem = @import("../mem.zig");
2const math = @import("../math/index.zig");
3const endian = @import("../endian.zig");
4const debug = @import("../debug/index.zig");
5
6pub const u160 = @IntType(false, 160);
7
8const RoundParam = struct {
9 a: u32, b: u32, c: u32, d: u32, e: u32, i: u32,
10};
11
12fn Rp(a: u32, b: u32, c: u32, d: u32, e: u32, i: u32) -> RoundParam {
13 return RoundParam { .a = a, .b = b, .c = c, .d = d, .e = e, .i = i };
14}
15
16pub const Sha1 = struct {
17 const Self = this;
18
19 s: [5]u32,
20 // Streaming Cache
21 buf: [64]u8,
22 buf_len: u8,
23 total_len: u64,
24
25 pub fn init() -> Self {
26 var d: Self = undefined;
27 d.reset();
28 return d;
29 }
30
31 pub fn reset(d: &Self) {
32 d.s[0] = 0x67452301;
33 d.s[1] = 0xEFCDAB89;
34 d.s[2] = 0x98BADCFE;
35 d.s[3] = 0x10325476;
36 d.s[4] = 0xC3D2E1F0;
37 d.buf_len = 0;
38 d.total_len = 0;
39 }
40
41 pub fn hash(b: []const u8) -> u160 {
42 var d = Sha1.init();
43 d.update(b);
44 return d.final();
45 }
46
47 pub fn update(d: &Self, b: []const u8) {
48 var off: usize = 0;
49
50 // Partial buffer exists from previous update. Copy into buffer then hash.
51 if (d.buf_len != 0 and d.buf_len + b.len > 64) {
52 off += 64 - d.buf_len;
53 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
54
55 d.round(d.buf[0..]);
56 d.buf_len = 0;
57 }
58
59 // Full middle blocks.
60 while (off + 64 < b.len) : (off += 64) {
61 d.round(b[off..off + 64]);
62 }
63
64 // Copy any remainder for next pass.
65 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
66 d.buf_len += u8(b[off..].len);
67
68 d.total_len += b.len;
69 }
70
71 pub fn final(d: &Self) -> u160 {
72 // The buffer here will never be completely full.
73 mem.set(u8, d.buf[d.buf_len..], 0);
74
75 // Append padding bits.
76 d.buf[d.buf_len] = 0x80;
77 d.buf_len += 1;
78
79 // > 448 mod 512 so need to add an extra round to wrap around.
80 if (64 - d.buf_len < 8) {
81 d.round(d.buf[0..]);
82 mem.set(u8, d.buf[0..], 0);
83 }
84
85 // Append message length.
86 var i: usize = 1;
87 var len = d.total_len >> 5;
88 d.buf[63] = u8(d.total_len & 0x1f) << 3;
89 while (i < 8) : (i += 1) {
90 d.buf[63 - i] = u8(len & 0xff);
91 len >>= 8;
92 }
93
94 d.round(d.buf[0..]);
95
96 const r =
97 (u160(d.s[0]) << 128) |
98 (u160(d.s[1]) << 96) |
99 (u160(d.s[2]) << 64) |
100 (u160(d.s[3]) << 32) |
101 (u160(d.s[4]) << 0);
102
103 return endian.swapIfBe(u160, r);
104 }
105
106 fn round(d: &Self, b: []const u8) {
107 debug.assert(b.len == 64);
108
109 var s: [16]u32 = undefined;
110
111 var v: [5]u32 = []u32 {
112 d.s[0], d.s[1], d.s[2], d.s[3], d.s[4],
113 };
114
115 const round0a = comptime []RoundParam {
116 Rp(0, 1, 2, 3, 4, 0),
117 Rp(4, 0, 1, 2, 3, 1),
118 Rp(3, 4, 0, 1, 2, 2),
119 Rp(2, 3, 4, 0, 1, 3),
120 Rp(1, 2, 3, 4, 0, 4),
121 Rp(0, 1, 2, 3, 4, 5),
122 Rp(4, 0, 1, 2, 3, 6),
123 Rp(3, 4, 0, 1, 2, 7),
124 Rp(2, 3, 4, 0, 1, 8),
125 Rp(1, 2, 3, 4, 0, 9),
126 Rp(0, 1, 2, 3, 4, 10),
127 Rp(4, 0, 1, 2, 3, 11),
128 Rp(3, 4, 0, 1, 2, 12),
129 Rp(2, 3, 4, 0, 1, 13),
130 Rp(1, 2, 3, 4, 0, 14),
131 Rp(0, 1, 2, 3, 4, 15),
132 };
133 inline for (round0a) |r| {
134 s[r.i] = (u32(b[r.i * 4 + 0]) << 24) |
135 (u32(b[r.i * 4 + 1]) << 16) |
136 (u32(b[r.i * 4 + 2]) << 8) |
137 (u32(b[r.i * 4 + 3]) << 0);
138
139 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf]
140 +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d]));
141 v[r.b] = math.rotl(u32, v[r.b], u32(30));
142 }
143
144 const round0b = comptime []RoundParam {
145 Rp(4, 0, 1, 2, 3, 16),
146 Rp(3, 4, 0, 1, 2, 17),
147 Rp(2, 3, 4, 0, 1, 18),
148 Rp(1, 2, 3, 4, 0, 19),
149 };
150 inline for (round0b) |r| {
151 const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf];
152 s[r.i & 0xf] = math.rotl(u32, t, u32(1));
153
154 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf]
155 +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d]));
156 v[r.b] = math.rotl(u32, v[r.b], u32(30));
157 }
158
159 const round1 = comptime []RoundParam {
160 Rp(0, 1, 2, 3, 4, 20),
161 Rp(4, 0, 1, 2, 3, 21),
162 Rp(3, 4, 0, 1, 2, 22),
163 Rp(2, 3, 4, 0, 1, 23),
164 Rp(1, 2, 3, 4, 0, 24),
165 Rp(0, 1, 2, 3, 4, 25),
166 Rp(4, 0, 1, 2, 3, 26),
167 Rp(3, 4, 0, 1, 2, 27),
168 Rp(2, 3, 4, 0, 1, 28),
169 Rp(1, 2, 3, 4, 0, 29),
170 Rp(0, 1, 2, 3, 4, 30),
171 Rp(4, 0, 1, 2, 3, 31),
172 Rp(3, 4, 0, 1, 2, 32),
173 Rp(2, 3, 4, 0, 1, 33),
174 Rp(1, 2, 3, 4, 0, 34),
175 Rp(0, 1, 2, 3, 4, 35),
176 Rp(4, 0, 1, 2, 3, 36),
177 Rp(3, 4, 0, 1, 2, 37),
178 Rp(2, 3, 4, 0, 1, 38),
179 Rp(1, 2, 3, 4, 0, 39),
180 };
181 inline for (round1) |r| {
182 const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf];
183 s[r.i & 0xf] = math.rotl(u32, t, u32(1));
184
185 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x6ED9EBA1 +% s[r.i & 0xf]
186 +% (v[r.b] ^ v[r.c] ^ v[r.d]);
187 v[r.b] = math.rotl(u32, v[r.b], u32(30));
188 }
189
190 const round2 = comptime []RoundParam {
191 Rp(0, 1, 2, 3, 4, 40),
192 Rp(4, 0, 1, 2, 3, 41),
193 Rp(3, 4, 0, 1, 2, 42),
194 Rp(2, 3, 4, 0, 1, 43),
195 Rp(1, 2, 3, 4, 0, 44),
196 Rp(0, 1, 2, 3, 4, 45),
197 Rp(4, 0, 1, 2, 3, 46),
198 Rp(3, 4, 0, 1, 2, 47),
199 Rp(2, 3, 4, 0, 1, 48),
200 Rp(1, 2, 3, 4, 0, 49),
201 Rp(0, 1, 2, 3, 4, 50),
202 Rp(4, 0, 1, 2, 3, 51),
203 Rp(3, 4, 0, 1, 2, 52),
204 Rp(2, 3, 4, 0, 1, 53),
205 Rp(1, 2, 3, 4, 0, 54),
206 Rp(0, 1, 2, 3, 4, 55),
207 Rp(4, 0, 1, 2, 3, 56),
208 Rp(3, 4, 0, 1, 2, 57),
209 Rp(2, 3, 4, 0, 1, 58),
210 Rp(1, 2, 3, 4, 0, 59),
211 };
212 inline for (round2) |r| {
213 const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf];
214 s[r.i & 0xf] = math.rotl(u32, t, u32(1));
215
216 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x8F1BBCDC +% s[r.i & 0xf]
217 +% ((v[r.b] & v[r.c]) ^ (v[r.b] & v[r.d]) ^ (v[r.c] & v[r.d]));
218 v[r.b] = math.rotl(u32, v[r.b], u32(30));
219 }
220
221 const round3 = comptime []RoundParam {
222 Rp(0, 1, 2, 3, 4, 60),
223 Rp(4, 0, 1, 2, 3, 61),
224 Rp(3, 4, 0, 1, 2, 62),
225 Rp(2, 3, 4, 0, 1, 63),
226 Rp(1, 2, 3, 4, 0, 64),
227 Rp(0, 1, 2, 3, 4, 65),
228 Rp(4, 0, 1, 2, 3, 66),
229 Rp(3, 4, 0, 1, 2, 67),
230 Rp(2, 3, 4, 0, 1, 68),
231 Rp(1, 2, 3, 4, 0, 69),
232 Rp(0, 1, 2, 3, 4, 70),
233 Rp(4, 0, 1, 2, 3, 71),
234 Rp(3, 4, 0, 1, 2, 72),
235 Rp(2, 3, 4, 0, 1, 73),
236 Rp(1, 2, 3, 4, 0, 74),
237 Rp(0, 1, 2, 3, 4, 75),
238 Rp(4, 0, 1, 2, 3, 76),
239 Rp(3, 4, 0, 1, 2, 77),
240 Rp(2, 3, 4, 0, 1, 78),
241 Rp(1, 2, 3, 4, 0, 79),
242 };
243 inline for (round3) |r| {
244 const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf];
245 s[r.i & 0xf] = math.rotl(u32, t, u32(1));
246
247 v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0xCA62C1D6 +% s[r.i & 0xf]
248 +% (v[r.b] ^ v[r.c] ^ v[r.d]);
249 v[r.b] = math.rotl(u32, v[r.b], u32(30));
250 }
251
252 d.s[0] +%= v[0];
253 d.s[1] +%= v[1];
254 d.s[2] +%= v[2];
255 d.s[3] +%= v[3];
256 d.s[4] +%= v[4];
257 }
258};
259
260test "sha1 single" {
261 debug.assert(0xda39a3ee5e6b4b0d3255bfef95601890afd80709 == Sha1.hash(""));
262 debug.assert(0xa9993e364706816aba3e25717850c26c9cd0d89d == Sha1.hash("abc"));
263 debug.assert(0xa49b2446a02c645bf419f995b67091253a04a259 == Sha1.hash("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"));
264}
265
266test "sha1 streaming" {
267 var h = Sha1.init();
268
269 debug.assert(0xda39a3ee5e6b4b0d3255bfef95601890afd80709 == h.final());
270
271 h.reset();
272 h.update("abc");
273 debug.assert(0xa9993e364706816aba3e25717850c26c9cd0d89d == h.final());
274
275 h.reset();
276 h.update("a");
277 h.update("b");
278 h.update("c");
279 debug.assert(0xa9993e364706816aba3e25717850c26c9cd0d89d == h.final());
280}
std/index.zig+2
......@@ -10,6 +10,7 @@ pub const LinkedList = @import("linked_list.zig").LinkedList;
1010pub const base64 = @import("base64.zig");
1111pub const build = @import("build.zig");
1212pub const c = @import("c/index.zig");
13pub const crypto = @import("crypto/index.zig");
1314pub const cstr = @import("cstr.zig");
1415pub const debug = @import("debug/index.zig");
1516pub const dwarf = @import("dwarf.zig");
......@@ -39,6 +40,7 @@ test "std" {
3940 _ = @import("base64.zig");
4041 _ = @import("build.zig");
4142 _ = @import("c/index.zig");
43 _ = @import("crypto/index.zig");
4244 _ = @import("cstr.zig");
4345 _ = @import("debug/index.zig");
4446 _ = @import("dwarf.zig");
std/math/index.zig+39
......@@ -267,6 +267,45 @@ test "math.shr" {
267267 assert(shr(u8, 0b11111111, isize(-2)) == 0b11111100);
268268}
269269
270/// Rotates right. Only unsigned values can be rotated.
271/// Negative shift values results in shift modulo the bit count.
272pub fn rotr(comptime T: type, x: T, r: var) -> T {
273 if (T.is_signed) {
274 @compileError("cannot rotate signed integer");
275 } else {
276 const ar = @mod(r, T.bit_count);
277 return shr(T, x, ar) | shl(T, x, T.bit_count - ar);
278 }
279}
280
281test "math.rotr" {
282 assert(rotr(u8, 0b00000001, usize(0)) == 0b00000001);
283 assert(rotr(u8, 0b00000001, usize(9)) == 0b10000000);
284 assert(rotr(u8, 0b00000001, usize(8)) == 0b00000001);
285 assert(rotr(u8, 0b00000001, usize(4)) == 0b00010000);
286 assert(rotr(u8, 0b00000001, isize(-1)) == 0b00000010);
287}
288
289/// Rotates left. Only unsigned values can be rotated.
290/// Negative shift values results in shift modulo the bit count.
291pub fn rotl(comptime T: type, x: T, r: var) -> T {
292 if (T.is_signed) {
293 @compileError("cannot rotate signed integer");
294 } else {
295 const ar = @mod(r, T.bit_count);
296 return shl(T, x, ar) | shr(T, x, T.bit_count - ar);
297 }
298}
299
300test "math.rotl" {
301 assert(rotl(u8, 0b00000001, usize(0)) == 0b00000001);
302 assert(rotl(u8, 0b00000001, usize(9)) == 0b00000010);
303 assert(rotl(u8, 0b00000001, usize(8)) == 0b00000001);
304 assert(rotl(u8, 0b00000001, usize(4)) == 0b00010000);
305 assert(rotl(u8, 0b00000001, isize(-1)) == 0b10000000);
306}
307
308
270309pub fn Log2Int(comptime T: type) -> type {
271310 return @IntType(false, log2(T.bit_count));
272311}