From a9f9becc4144850694875723a910c463f7eefea3 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 9 Sep 2024 15:38:55 +0200 Subject: [PATCH] add support for algorithms SHA256 and SHA512 --- src/main.zig | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/main.zig b/src/main.zig index 14bdca0..f7f4aad 100644 --- a/src/main.zig +++ b/src/main.zig @@ -104,6 +104,19 @@ const Authenticator = struct { std.crypto.auth.hmac.HmacSha1.create(hmac[0..], &intervalAsU8Array, secret); return try self.generateTotp(allocator, &hmac); } + + if (std.mem.eql(u8, self.url.algorithm, "SHA256")) { + var hmac: [std.crypto.auth.hmac.sha2.HmacSha256.mac_length]u8 = undefined; + std.crypto.auth.hmac.sha2.HmacSha256.create(hmac[0..], &intervalAsU8Array, secret); + return try self.generateTotp(allocator, &hmac); + } + + if (std.mem.eql(u8, self.url.algorithm, "SHA512")) { + var hmac: [std.crypto.auth.hmac.sha2.HmacSha512.mac_length]u8 = undefined; + std.crypto.auth.hmac.sha2.HmacSha512.create(hmac[0..], &intervalAsU8Array, secret); + return try self.generateTotp(allocator, &hmac); + } + unreachable; } @@ -396,6 +409,10 @@ test "authenticator generate code with 10 digits and zero padding" { test "testcases from https://www.rfc-editor.org/rfc/rfc6238#appendix-A" { const secretForSha1 = "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ"; // plain: "12345678901234567890" hex: "3132333435363738393031323334353637383930" + const secretForSha256 = "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZA"; // hex: "3132333435363738393031323334353637383930313233343536373839303132" + + const secretForSha512 = "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNA"; // hex: "313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930" + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha1, .url = "", .period = 30, .digits = 8, .algorithm = "SHA1" }, _closure_return_59, "94287082"); try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha1, .url = "", .period = 30, .digits = 8, .algorithm = "SHA1" }, _closure_return_1111111109, "07081804"); @@ -407,6 +424,30 @@ test "testcases from https://www.rfc-editor.org/rfc/rfc6238#appendix-A" { try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha1, .url = "", .period = 30, .digits = 8, .algorithm = "SHA1" }, _closure_return_2000000000, "69279037"); try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha1, .url = "", .period = 30, .digits = 8, .algorithm = "SHA1" }, _closure_return_20000000000, "65353130"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha256, .url = "", .period = 30, .digits = 8, .algorithm = "SHA256" }, _closure_return_59, "46119246"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha256, .url = "", .period = 30, .digits = 8, .algorithm = "SHA256" }, _closure_return_1111111109, "68084774"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha256, .url = "", .period = 30, .digits = 8, .algorithm = "SHA256" }, _closure_return_1111111111, "67062674"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha256, .url = "", .period = 30, .digits = 8, .algorithm = "SHA256" }, _closure_return_1234567890, "91819424"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha256, .url = "", .period = 30, .digits = 8, .algorithm = "SHA256" }, _closure_return_2000000000, "90698825"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha256, .url = "", .period = 30, .digits = 8, .algorithm = "SHA256" }, _closure_return_20000000000, "77737706"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha512, .url = "", .period = 30, .digits = 8, .algorithm = "SHA512" }, _closure_return_59, "90693936"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha512, .url = "", .period = 30, .digits = 8, .algorithm = "SHA512" }, _closure_return_1111111109, "25091201"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha512, .url = "", .period = 30, .digits = 8, .algorithm = "SHA512" }, _closure_return_1111111111, "99943326"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha512, .url = "", .period = 30, .digits = 8, .algorithm = "SHA512" }, _closure_return_1234567890, "93441116"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha512, .url = "", .period = 30, .digits = 8, .algorithm = "SHA512" }, _closure_return_2000000000, "38618901"); + + try testTOTP(OtpAuthUrl{ .name = "", .secretEncoded = secretForSha512, .url = "", .period = 30, .digits = 8, .algorithm = "SHA512" }, _closure_return_20000000000, "47863826"); } fn testTOTP(otpAuthUrl: OtpAuthUrl, timeFunc: *const fn () i64, expected: []const u8) !void {