| author | |
| committer | |
| log | a2315cfbfcfe33a2b9010994a1da6674854151e9 |
| tree | d509b0494776da54c78aa299d4679cf4f17180e0 |
| parent | 3268276b58d8b65cb295b738d7c14174005bd84e |
| parent | 51fdbf7f8c282c7b91a688c9069b363e90bedf6e |
| signature |
Add Md5 and Sha1 functions6 files changed, 583 insertions(+), 0 deletions(-)
CMakeLists.txt+3| ... | @@ -364,6 +364,9 @@ set(ZIG_STD_FILES | ... | @@ -364,6 +364,9 @@ set(ZIG_STD_FILES |
| 364 | "c/index.zig" | 364 | "c/index.zig" |
| 365 | "c/linux.zig" | 365 | "c/linux.zig" |
| 366 | "c/windows.zig" | 366 | "c/windows.zig" |
| 367 | "crypto/index.zig" | ||
| 368 | "crypto/md5.zig" | ||
| 369 | "crypto/sha1.zig" | ||
| 367 | "cstr.zig" | 370 | "cstr.zig" |
| 368 | "debug/failing_allocator.zig" | 371 | "debug/failing_allocator.zig" |
| 369 | "debug/index.zig" | 372 | "debug/index.zig" |
std/crypto/index.zig created+7| ... | @@ -0,0 +1,7 @@ | ||
| 1 | pub const Sha1 = @import("md5.zig").Sha1; | ||
| 2 | pub const Md5 = @import("sha1.zig").Md5; | ||
| 3 | |||
| 4 | test "crypto" { | ||
| 5 | _ = @import("md5.zig"); | ||
| 6 | _ = @import("sha1.zig"); | ||
| 7 | } | ||
std/crypto/md5.zig created+252| ... | @@ -0,0 +1,252 @@ | ||
| 1 | const mem = @import("../mem.zig"); | ||
| 2 | const math = @import("../math/index.zig"); | ||
| 3 | const endian = @import("../endian.zig"); | ||
| 4 | const debug = @import("../debug/index.zig"); | ||
| 5 | |||
| 6 | const RoundParam = struct { | ||
| 7 | a: u32, b: u32, c: u32, d: u32, | ||
| 8 | k: u32, s: u32, t: u32 | ||
| 9 | }; | ||
| 10 | |||
| 11 | fn 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(); | ||
| 21 | pub 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 | |||
| 228 | test "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 | |||
| 238 | test "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 @@ | ||
| 1 | const mem = @import("../mem.zig"); | ||
| 2 | const math = @import("../math/index.zig"); | ||
| 3 | const endian = @import("../endian.zig"); | ||
| 4 | const debug = @import("../debug/index.zig"); | ||
| 5 | |||
| 6 | pub const u160 = @IntType(false, 160); | ||
| 7 | |||
| 8 | const RoundParam = struct { | ||
| 9 | a: u32, b: u32, c: u32, d: u32, e: u32, i: u32, | ||
| 10 | }; | ||
| 11 | |||
| 12 | fn 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 | |||
| 16 | pub 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 | |||
| 260 | test "sha1 single" { | ||
| 261 | debug.assert(0xda39a3ee5e6b4b0d3255bfef95601890afd80709 == Sha1.hash("")); | ||
| 262 | debug.assert(0xa9993e364706816aba3e25717850c26c9cd0d89d == Sha1.hash("abc")); | ||
| 263 | debug.assert(0xa49b2446a02c645bf419f995b67091253a04a259 == Sha1.hash("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")); | ||
| 264 | } | ||
| 265 | |||
| 266 | test "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; | ... | @@ -10,6 +10,7 @@ pub const LinkedList = @import("linked_list.zig").LinkedList; |
| 10 | pub const base64 = @import("base64.zig"); | 10 | pub const base64 = @import("base64.zig"); |
| 11 | pub const build = @import("build.zig"); | 11 | pub const build = @import("build.zig"); |
| 12 | pub const c = @import("c/index.zig"); | 12 | pub const c = @import("c/index.zig"); |
| 13 | pub const crypto = @import("crypto/index.zig"); | ||
| 13 | pub const cstr = @import("cstr.zig"); | 14 | pub const cstr = @import("cstr.zig"); |
| 14 | pub const debug = @import("debug/index.zig"); | 15 | pub const debug = @import("debug/index.zig"); |
| 15 | pub const dwarf = @import("dwarf.zig"); | 16 | pub const dwarf = @import("dwarf.zig"); |
| ... | @@ -39,6 +40,7 @@ test "std" { | ... | @@ -39,6 +40,7 @@ test "std" { |
| 39 | _ = @import("base64.zig"); | 40 | _ = @import("base64.zig"); |
| 40 | _ = @import("build.zig"); | 41 | _ = @import("build.zig"); |
| 41 | _ = @import("c/index.zig"); | 42 | _ = @import("c/index.zig"); |
| 43 | _ = @import("crypto/index.zig"); | ||
| 42 | _ = @import("cstr.zig"); | 44 | _ = @import("cstr.zig"); |
| 43 | _ = @import("debug/index.zig"); | 45 | _ = @import("debug/index.zig"); |
| 44 | _ = @import("dwarf.zig"); | 46 | _ = @import("dwarf.zig"); |
std/math/index.zig+39| ... | @@ -267,6 +267,45 @@ test "math.shr" { | ... | @@ -267,6 +267,45 @@ test "math.shr" { |
| 267 | assert(shr(u8, 0b11111111, isize(-2)) == 0b11111100); | 267 | assert(shr(u8, 0b11111111, isize(-2)) == 0b11111100); |
| 268 | } | 268 | } |
| 269 | 269 | ||
| 270 | /// Rotates right. Only unsigned values can be rotated. | ||
| 271 | /// Negative shift values results in shift modulo the bit count. | ||
| 272 | pub 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 | |||
| 281 | test "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. | ||
| 291 | pub 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 | |||
| 300 | test "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 | |||
| 270 | pub fn Log2Int(comptime T: type) -> type { | 309 | pub fn Log2Int(comptime T: type) -> type { |
| 271 | return @IntType(false, log2(T.bit_count)); | 310 | return @IntType(false, log2(T.bit_count)); |
| 272 | } | 311 | } |