Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std.crypto.hash: add a non-clobbering method to serialize the current hash value #13400

Closed
nektro opened this issue Nov 1, 2022 · 2 comments
Closed
Labels
bug Observed behavior contradicts documented or intended behavior

Comments

@nektro
Copy link
Contributor

nektro commented Nov 1, 2022

Zig Version

0.11.0-dev.6+2943df016

Steps to Reproduce and Observed Behavior

const std = @import("std");

test {
    const Sha256 = std.crypto.hash.sha2.Sha256;
    const length = Sha256.digest_length;

    var b1: [length]u8 = undefined;
    var h1 = Sha256.init(.{});
    h1.update("abab");
    h1.update("cdcd");
    h1.final(&b1);
    h1.update("efef");
    h1.final(&b1);
    var o1: [length * 2]u8 = undefined;
    _ = try std.fmt.bufPrint(&o1, "{}", .{std.fmt.fmtSliceHexLower(&b1)});

    var b2: [length]u8 = undefined;
    var h2 = Sha256.init(.{});
    h2.update("abab");
    h2.update("cdcd");
    h2.update("efef");
    h2.final(&b2);
    var o2: [length * 2]u8 = undefined;
    _ = try std.fmt.bufPrint(&o2, "{}", .{std.fmt.fmtSliceHexLower(&b2)});

    try std.testing.expectEqualStrings(&o2, &o1);
}
Test [1/1] test_0... 
====== expected this output: =========
7a8abe2debd5bc4afc9a940226200962136858ad3bd4f2777ad2974f133f3237␃

======== instead found this: =========
6934c9d035b7387a84482e1f5c0c4f7ead3b2784ba3923630fc0f5aecee733a3␃

======================================
First difference occurs on line 1:
expected:
7a8abe2debd5bc4afc9a940226200962136858ad3bd4f2777ad2974f133f3237
^ ('\x37')
found:
6934c9d035b7387a84482e1f5c0c4f7ead3b2784ba3923630fc0f5aecee733a3
^ ('\x36')
Test [1/1] test_0... FAIL (TestExpectedEqual)

Expected Behavior

.final() to not dirty the state, or an alternate function (eg .serialize() that does not clobber)

@nektro nektro added the bug Observed behavior contradicts documented or intended behavior label Nov 1, 2022
@nektro
Copy link
Contributor Author

nektro commented Nov 1, 2022

workaround in the meantime that makes the test pass

fn serialize(comptime T: type, h: T, out: *[T.digest_length]u8) void {
    var copy = h;
    copy.final(out);
}

@jedisct1
Copy link
Contributor

jedisct1 commented Nov 1, 2022

final() should be considered final :)

For example, it can (and maybe already does) zero the key or other sensitive data from the state.

And in state-based systems such as Gimli and Xoodyak, final() updates the state by design, so that h(a, b) is not the same as h(a || b).

However, hash states can be explicitly copied:

    var b1: [length]u8 = undefined;
    var h1 = Sha256.init(.{});
    h1.update("abab");
    h1.update("cdcd");

    var h1_copy = h1; // copy the state
    h1.final(&b1);

    h1_copy.update("efef");
    h1_copy.final(&b1);

This approach works with all hashes, is already used in the compiler, and allows for tree-based hashing (the same state can then be used for different updates).

@nektro nektro closed this as completed Nov 1, 2022
@nektro nektro closed this as not planned Won't fix, can't repro, duplicate, stale Nov 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

2 participants