authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-04-05 02:31:10+12:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-04 10:31:10-04:00
log8938429ea12ff2857ace5380932a7cd68d3b4ab1
tree405ee313889d86ff8e6e1b63cf21f33c11f346c0
parentf68c2e0a14c7d9997db0305981ce3e5998d88a36

Add Hmac function (#890)


3 files changed, 88 insertions(+), 0 deletions(-)

CMakeLists.txt+1
...@@ -425,6 +425,7 @@ set(ZIG_STD_FILES...@@ -425,6 +425,7 @@ set(ZIG_STD_FILES
425 "crypto/sha2.zig"425 "crypto/sha2.zig"
426 "crypto/sha3.zig"426 "crypto/sha3.zig"
427 "crypto/blake2.zig"427 "crypto/blake2.zig"
428 "crypto/hmac.zig"
428 "cstr.zig"429 "cstr.zig"
429 "debug/failing_allocator.zig"430 "debug/failing_allocator.zig"
430 "debug/index.zig"431 "debug/index.zig"
std/crypto/hmac.zig created+81
...@@ -0,0 +1,81 @@
1const std = @import("../index.zig");
2const crypto = std.crypto;
3const debug = std.debug;
4const mem = std.mem;
5
6pub const HmacMd5 = Hmac(crypto.Md5);
7pub const HmacSha1 = Hmac(crypto.Sha1);
8pub const HmacSha256 = Hmac(crypto.Sha256);
9
10pub fn Hmac(comptime H: type) type {
11 return struct {
12 const digest_size = H.digest_size;
13
14 pub fn hash(output: []u8, key: []const u8, message: []const u8) void {
15 debug.assert(output.len >= H.digest_size);
16 debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption
17 var scratch: [H.block_size]u8 = undefined;
18
19 // Normalize key length to block size of hash
20 if (key.len > H.block_size) {
21 H.hash(key, scratch[0..H.digest_size]);
22 mem.set(u8, scratch[H.digest_size..H.block_size], 0);
23 } else if (key.len < H.block_size) {
24 mem.copy(u8, scratch[0..key.len], key);
25 mem.set(u8, scratch[key.len..H.block_size], 0);
26 } else {
27 mem.copy(u8, scratch[0..], key);
28 }
29
30 var o_key_pad: [H.block_size]u8 = undefined;
31 for (o_key_pad) |*b, i| {
32 *b = scratch[i] ^ 0x5c;
33 }
34
35 var i_key_pad: [H.block_size]u8 = undefined;
36 for (i_key_pad) |*b, i| {
37 *b = scratch[i] ^ 0x36;
38 }
39
40 // HMAC(k, m) = H(o_key_pad | H(i_key_pad | message)) where | is concatenation
41 var hmac = H.init();
42 hmac.update(i_key_pad[0..]);
43 hmac.update(message);
44 hmac.final(scratch[0..H.digest_size]);
45
46 hmac.reset();
47 hmac.update(o_key_pad[0..]);
48 hmac.update(scratch[0..H.digest_size]);
49 hmac.final(output[0..H.digest_size]);
50 }
51 };
52}
53
54const htest = @import("test.zig");
55
56test "hmac md5" {
57 var out: [crypto.Md5.digest_size]u8 = undefined;
58 HmacMd5.hash(out[0..], "", "");
59 htest.assertEqual("74e6f7298a9c2d168935f58c001bad88", out[0..]);
60
61 HmacMd5.hash(out[0..], "key", "The quick brown fox jumps over the lazy dog");
62 htest.assertEqual("80070713463e7749b90c2dc24911e275", out[0..]);
63}
64
65test "hmac sha1" {
66 var out: [crypto.Sha1.digest_size]u8 = undefined;
67 HmacSha1.hash(out[0..], "", "");
68 htest.assertEqual("fbdb1d1b18aa6c08324b7d64b71fb76370690e1d", out[0..]);
69
70 HmacSha1.hash(out[0..], "key", "The quick brown fox jumps over the lazy dog");
71 htest.assertEqual("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9", out[0..]);
72}
73
74test "hmac sha256" {
75 var out: [crypto.Sha256.digest_size]u8 = undefined;
76 HmacSha256.hash(out[0..], "", "");
77 htest.assertEqual("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", out[0..]);
78
79 HmacSha256.hash(out[0..], "key", "The quick brown fox jumps over the lazy dog");
80 htest.assertEqual("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8", out[0..]);
81}
std/crypto/index.zig+6
...@@ -19,10 +19,16 @@ pub const Blake2s256 = blake2.Blake2s256;...@@ -19,10 +19,16 @@ pub const Blake2s256 = blake2.Blake2s256;
19pub const Blake2b384 = blake2.Blake2b384;19pub const Blake2b384 = blake2.Blake2b384;
20pub const Blake2b512 = blake2.Blake2b512;20pub const Blake2b512 = blake2.Blake2b512;
2121
22const hmac = @import("hmac.zig");
23pub const HmacMd5 = hmac.HmacMd5;
24pub const HmacSha1 = hmac.Sha1;
25pub const HmacSha256 = hmac.Sha256;
26
22test "crypto" {27test "crypto" {
23 _ = @import("md5.zig");28 _ = @import("md5.zig");
24 _ = @import("sha1.zig");29 _ = @import("sha1.zig");
25 _ = @import("sha2.zig");30 _ = @import("sha2.zig");
26 _ = @import("sha3.zig");31 _ = @import("sha3.zig");
27 _ = @import("blake2.zig");32 _ = @import("blake2.zig");
33 _ = @import("hmac.zig");
28}34}