ziglang/zig

HMAC + SHA3 incorrect output

guidovranken opened this issue · 4 comments

Zig Version

zig-linux-x86_64-0.11.0-dev.1000+94780f7cd

Steps to Reproduce and Observed Behavior

const std = @import("std");
const hash = std.crypto.hash;
const hmac = std.crypto.auth.hmac;

pub fn main() !void {
    var key: [8]u8 = [8]u8{0xe9, 0xbb, 0x6c, 0xff, 0x69, 0xf8, 0xb7, 0xd4};
    var input: [28]u8 = [28]u8{
    0x86, 0x94, 0xd3, 0xdb, 0x4a, 0x08, 0xc8, 0x4f, 0xda, 0x92, 0xc1, 0x67, 0x69, 0x13, 0x6b, 0x8a,
    0x14, 0x76, 0x62, 0x26, 0x05, 0x9e, 0x54, 0x96, 0x5e, 0x72, 0xe1, 0x4a};
    var out: [32]u8 = undefined;

    var h = hmac.Hmac(hash.sha3.Sha3_256).init(&key);
    h.update(&input);
    h.final(&out);
    var i: u32 = 0;
    while (i < 32): (i+=1) {
        std.debug.print("0x{x} ", .{out[i]});
    }
    std.debug.print("\n", .{});
}

This prints:

0x84 0xfc 0xe4 0xc 0x51 0xff 0xb8 0x55 0x39 0xf7 0x5d 0x58 0x55 0xb2 0x71 0xa5 0xf3 0x27 0x6 0xab 0xb3 0x25 0x20 0xfa 0xac 0x7b 0x27 0xe8 0xc2 0xd8 0xc7 0xa5

Expected Behavior

It should print:

0xf3 0x20 0x7b 0x53 0x74 0xf3 0x1f 0xfe 0xc5 0x22 0xb9 0x33 0xad 0xdd 0x22 0x31 0xc2 0xd4 0x67 0x8c 0xbf 0x5f 0x93 0xd1 0x18 0x22 0x6f 0x05 0x19 0xe1 0xb9 0x8d

HMAC works correctly with all the other algorithms I've tested (BLAKE2B128,BLAKE2B160,BLAKE2B256,BLAKE2B384,BLAKE2B512,BLAKE2S128,BLAKE2S160,BLAKE2S256,MD5,SHA1,SHA224,SHA256,SHA384,SHA512)

SHA3 algorithms also work correctly when used as a digest function.

But the combination of HMAC + (any of SHA3-224, SHA3-256, SHA3-384, SHA-512, KECCAK-256, KECCAK-512) all produce the wrong result.

Wrong result means that the output is different than that of all other cryptographic libraries.

I didn't write that code, but in sha3, we always return 200 as the block size.

This is the state size, which is not the same as the block size for sponge constructions.

I'm currently AFK, but fixing this should be trivial; I'll do it as soon as I get back home.

Untested, but changing the block_length definition to:

pub const block_length = 200 - 2 * digest_length;

should fix it.

That being said, talking about "block size" doesn't really make sense in the context of sponge constructions.

Neither does using them with HMAC, to be honest :)