From 6c684ef5cad513370974c2fb326bd5fd381708bd Mon Sep 17 00:00:00 2001 From: Pia Date: Fri, 6 Sep 2024 21:18:17 +0900 Subject: [PATCH 1/5] sketch --- .gitignore | 2 ++ src/hashes/lib.zig | 1 + src/hashes/sha256t.zig | 59 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 src/hashes/sha256t.zig diff --git a/.gitignore b/.gitignore index d6b66c8..a9594b6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ zig-out/ /build/ /build-*/ /docgen_tmp/ + +build.zig.zon \ No newline at end of file diff --git a/src/hashes/lib.zig b/src/hashes/lib.zig index 20f5bc4..f4d8855 100644 --- a/src/hashes/lib.zig +++ b/src/hashes/lib.zig @@ -1 +1,2 @@ pub const Ripemd160 = @import("ripemd160.zig").Ripemd160; +pub const Sha256t = @import("sha256t.zig").Sha256t; diff --git a/src/hashes/sha256t.zig b/src/hashes/sha256t.zig new file mode 100644 index 0000000..008aa3d --- /dev/null +++ b/src/hashes/sha256t.zig @@ -0,0 +1,59 @@ +const std = @import("std"); +const Sha256 = std.crypto.hash.sha2.Sha256; +const testing = std.testing; + +pub fn Tag(comptime tag_value: []const u8) type { + return struct { + pub fn engine() Sha256 { + var h = Sha256.init(.{}); + h.update(tag_value); + return h; + } + }; +} + +pub fn Hash(comptime T: type) type { + return struct { + bytes: [32]u8, + + const Self = @This(); + + pub fn init(data: []const u8) Self { + var h = T.engine(); + h.update(data); + var out: [32]u8 = undefined; + h.final(&out); + return Self{ .bytes = out }; + } + + pub fn toSlice(self: *const Self) []const u8 { + return &self.bytes; + } + + pub fn toString(self: *const Self) ![64]u8 { + var buf: [64]u8 = undefined; + _ = try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexLower(&self.bytes)}); + return buf; + } + }; +} + +pub fn Sha256t(comptime tag: []const u8) type { + const TagType = Tag(tag); + return Hash(TagType); +} + +test "TestHash" { + var h = Sha256.init(.{}); + var out: [32]u8 = undefined; + + h.final(out[0..]); + const expected = [_]u8{ + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, + }; + + try testing.expectEqualSlices(u8, &expected, &out); +} From 1d502c57f7c841b9f8aa1738db8e49ba6ca6e6f6 Mon Sep 17 00:00:00 2001 From: Pia Date: Sun, 22 Sep 2024 14:20:43 +0900 Subject: [PATCH 2/5] feat: midstate, hashengine --- src/hashes/sha256.zig | 91 +++++++++++++++++++++++++++++++++++ src/hashes/sha256t.zig | 107 ++++++++++++++++++++++------------------- 2 files changed, 148 insertions(+), 50 deletions(-) create mode 100644 src/hashes/sha256.zig diff --git a/src/hashes/sha256.zig b/src/hashes/sha256.zig new file mode 100644 index 0000000..71382e6 --- /dev/null +++ b/src/hashes/sha256.zig @@ -0,0 +1,91 @@ +const std = @import("std"); +const mem = std.mem; + +/// Unfinalized output of the SHA256 hash function. +/// +/// The `Midstate` type is obscure and specialized and should not be used unless you are sure of +/// what you are doing. +/// +/// It represents "partially hashed data" but does not itself have properties of cryptographic +/// hashes. For example, when (ab)used as hashes, midstates are vulnerable to trivial +/// length-extension attacks. They are typically used to optimize the computation of full hashes. +/// For example, when implementing BIP-340 tagged hashes, which always begin by hashing the same +/// fixed 64-byte prefix, it makes sense to hash the prefix once, store the midstate as a constant, +/// and hash any future data starting from the constant rather than from a fresh hash engine. +/// +/// For BIP-340 support we provide the [`sha256t`] module, and the [`sha256t_tag`] macro which will +/// create the midstate for you in const context. +const Midstate = struct { + /// Raw bytes of the midstate i.e., the already-hashed contents of the hash engine. + data: [32]u8, + /// Number of bytes hashed to achieve this midstate. + // INVARIANT must always be a multiple of 64. + length: u64, + + pub fn asBytes(self: Midstate) [8]u32 { + var blocks: [8]u32 = undefined; + var idx: usize = 0; + var idxBuff: usize = 0; + while (idx < 8) : (idx += 1) { + blocks[idx] = @as(u32, self.data[idxBuff]) << 24 | @as(u24, self.data[idxBuff + 1]) << 16 | @as(u16, self.data[idxBuff + 2]) << 8 | self.data[idxBuff + 3]; + idxBuff += 4; + } + return blocks; + } +}; + +const BLOCK_SIZE: usize = 64; + +/// Engine to compute SHA256 hash function. +const HashEngine = struct { + buffer: [BLOCK_SIZE]u8, + h: [8]u32, + length: u64, + + /// Creates a new SHA256 hash engine. + pub fn new() HashEngine { + return HashEngine{ + .buffer = std.mem.zeroes([BLOCK_SIZE]u8), + .h = [8]u32{ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, + }, + .length = 0, + }; + } + + /// Creates a new [`HashEngine`] from a [`Midstate`]. + /// + /// Please see docs on [`Midstate`] before using this function. + pub fn fromMidstate(midstate: Midstate) HashEngine { + const midstate_bytes = midstate.asBytes(); + + return HashEngine{ + .buffer = std.mem.zeroes([BLOCK_SIZE]u32), + .h = midstate_bytes, + .length = midstate.length, + }; + } +}; + +test "Convert [32]u8 to [8]u32" { + const input: [32]u8 = [32]u8{ + 0x0f, 0xd0, 0x69, 0x0c, 0xfe, 0xfe, 0xae, 0xb7, + 0x99, 0x6e, 0xac, 0x7f, 0x5c, 0x30, 0xd8, 0x64, + 0x8c, 0x4a, 0x05, 0x73, 0xac, 0xa1, 0xa2, 0x2f, + 0x6f, 0x43, 0xb8, 0x01, 0x85, 0xce, 0x27, 0xcd, + }; + + var midstate = Midstate{ + .data = input, + .length = 32, + }; + + const expected: [8]u32 = [8]u32{ + 0x0fd0690c, 0xfefeaeb7, 0x996eac7f, 0x5c30d864, + 0x8c4a0573, 0xaca1a22f, 0x6f43b801, 0x85ce27cd, + }; + + const result = midstate.asChunkedBytes(); + try std.testing.expectEqualSlices(u32, &expected, &result); +} diff --git a/src/hashes/sha256t.zig b/src/hashes/sha256t.zig index 008aa3d..e861caf 100644 --- a/src/hashes/sha256t.zig +++ b/src/hashes/sha256t.zig @@ -1,59 +1,66 @@ const std = @import("std"); -const Sha256 = std.crypto.hash.sha2.Sha256; +const Hash = std.crypto.hash.sha2.Sha256; const testing = std.testing; -pub fn Tag(comptime tag_value: []const u8) type { - return struct { - pub fn engine() Sha256 { - var h = Sha256.init(.{}); - h.update(tag_value); - return h; - } - }; -} +const Tag = struct { + engine: fn () Hash, +}; -pub fn Hash(comptime T: type) type { - return struct { - bytes: [32]u8, - - const Self = @This(); - - pub fn init(data: []const u8) Self { - var h = T.engine(); - h.update(data); - var out: [32]u8 = undefined; - h.final(&out); - return Self{ .bytes = out }; - } - - pub fn toSlice(self: *const Self) []const u8 { - return &self.bytes; - } - - pub fn toString(self: *const Self) ![64]u8 { - var buf: [64]u8 = undefined; - _ = try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexLower(&self.bytes)}); - return buf; - } - }; -} +pub const Sha256t = struct { + const Self = @This(); -pub fn Sha256t(comptime tag: []const u8) type { - const TagType = Tag(tag); - return Hash(TagType); -} + sha256_engine: Hash, + + pub fn init() Self { + return Sha256t{ + .sha256_engine = Hash.init(.{}), + }; + } +}; + +const TestHashTag = struct { + fn engine() Hash { + const TEST_MIDSTATE = [32]u8{ + 156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, 147, + 108, 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201, + }; + + var sha256_engine = Hash.init(.{}); + sha256_engine.update(&TEST_MIDSTATE); + return sha256_engine; + } +}; + +// Define the TestHash struct +const TestHash = struct { + data: [32]u8, + + // Hash some bytes and create a new TestHash + pub fn hash(data: []const u8) TestHash { + var sha256_engine = TestHashTag.engine(); + sha256_engine.update(data); + + // Debugging: Print engine state after update + std.debug.print("Engine state after update: {x}\n", .{sha256_engine.s}); + + var out: [32]u8 = undefined; + sha256_engine.final(&out); + + // Debugging: Print final hash output + std.debug.print("Final hash output: {x}\n", .{out}); -test "TestHash" { - var h = Sha256.init(.{}); - var out: [32]u8 = undefined; + return TestHash{ .data = out }; + } +}; - h.final(out[0..]); - const expected = [_]u8{ - 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, - 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, - 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, - 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, - }; +// Test function using expectEqualSlices to compare TestHash output to the expected value +test "manually created sha256t hash type" { + var hash = TestHash.hash(&[_]u8{0}); + try std.testing.expectEqualSlices(u8, &[32]u8{ + 0xed, 0x13, 0x82, 0x03, 0x78, 0x00, 0xc9, 0xdd, 0x93, 0x8d, 0xd8, 0x85, 0x4f, 0x1a, 0x88, 0x63, + 0xbc, 0xde, 0xb6, 0x70, 0x50, 0x69, 0xb4, 0xb5, 0x6a, 0x66, 0xec, 0x22, 0x51, 0x9d, 0x58, 0x29, + }, &hash.data); - try testing.expectEqualSlices(u8, &expected, &out); + // You can also print success message if needed + std.debug.print("Test passed: Hash matches expected value.\n", .{}); } From 4fda1aee1a0f3432d4894838254a61ff0de5eb59 Mon Sep 17 00:00:00 2001 From: Pia Date: Sun, 22 Sep 2024 15:48:18 +0900 Subject: [PATCH 3/5] chore: readInt --- src/hashes/sha256.zig | 57 ++++++++++++++++++++++++++++++++++++++++-- src/hashes/sha256t.zig | 29 ++++++++++++++++++--- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/hashes/sha256.zig b/src/hashes/sha256.zig index 71382e6..056be6d 100644 --- a/src/hashes/sha256.zig +++ b/src/hashes/sha256.zig @@ -1,5 +1,6 @@ const std = @import("std"); const mem = std.mem; +const Hash = std.crypto.hash.sha2.Sha256; /// Unfinalized output of the SHA256 hash function. /// @@ -27,13 +28,50 @@ const Midstate = struct { var idx: usize = 0; var idxBuff: usize = 0; while (idx < 8) : (idx += 1) { - blocks[idx] = @as(u32, self.data[idxBuff]) << 24 | @as(u24, self.data[idxBuff + 1]) << 16 | @as(u16, self.data[idxBuff + 2]) << 8 | self.data[idxBuff + 3]; + blocks[idx] = std.mem.readInt(u32, @ptrCast(&self.data[idxBuff]), .big); idxBuff += 4; } return blocks; } + + // Creates midstate for tagged hashes. + // + // Computes non-finalized hash of `sha256(tag) || sha256(tag)` for use in [`sha256t`]. It's + // provided for use with [`sha256t`]. + // pub fn hash_tag(tag: []const u8) Midstate { + // var h = Hash.init(.{}); + // h.update(tag); + // const hash = h.finalResult(); + + // var buf: [64]u8 = undefined; + // for (&buf, 0..) |*buf_elem, idx| { + // buf_elem.* = hash[idx % 32]; + // } + + // var h2 = Hash.init(.{}); + // h2.update(&buf); + + // return Midstate{ .data = toBytes(h2.s), .length = 64 }; + // } }; +// pub fn toBytes(blocks: [8]u32) [32]u8 { +// var data: [32]u8 = undefined; +// var idx: usize = 0; +// var idxBuff: usize = 0; +// while (idx < 8) : (idx += 1) { +// const word = blocks[idx]; + +// std.mem.readInt(u16, &[_]u8{ 0x12, 0x34 }); +// data[idxBuff] = @truncate(u8, word >> 24); +// data[idxBuff + 1] = @truncate(u8, word >> 16); +// data[idxBuff + 2] = @truncate(u8, word >> 8); +// data[idxBuff + 3] = @truncate(u8, word); +// idxBuff += 4; +// } +// return data; +// } + const BLOCK_SIZE: usize = 64; /// Engine to compute SHA256 hash function. @@ -86,6 +124,21 @@ test "Convert [32]u8 to [8]u32" { 0x8c4a0573, 0xaca1a22f, 0x6f43b801, 0x85ce27cd, }; - const result = midstate.asChunkedBytes(); + const result = midstate.asBytes(); try std.testing.expectEqualSlices(u32, &expected, &result); } + +// test "const midstate" { +// const expectedMidstate = Midstate{ +// .data = [32]u8{ +// 156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, +// 147, 108, 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201, +// }, +// .length = 64, +// }; + +// const midstate = Midstate.hash_tag("TapLeaf"); +// try std.testing.expectEqualSlices(u8, &expectedMidstate.data, &midstate.data); + +// try std.testing.expectEqual(expectedMidstate.length, midstate.length); +// } diff --git a/src/hashes/sha256t.zig b/src/hashes/sha256t.zig index e861caf..1043246 100644 --- a/src/hashes/sha256t.zig +++ b/src/hashes/sha256t.zig @@ -1,6 +1,31 @@ const std = @import("std"); const Hash = std.crypto.hash.sha2.Sha256; const testing = std.testing; +const Midstate = @import("./sha256.zig"); +const HashEngine = @import("./sha256.zig"); + +fn sha256t_tag(comptime tag: []const u8) [8]u32 { + var h = Hash.init(.{}); + h.update(tag); + const digest1 = h.finalResult(); + + var h2 = Hash.init(.{}); + h2.update(&digest1); + const digest2 = h2.finalResult(); + + var midstate: [8]u32 = undefined; + + var i: usize = 0; + while (i < 8) : (i += 1) { + const idx = i * 4; + midstate[i] = (@as(u32, digest2[idx]) << 24) | + (@as(u32, digest2[idx + 1]) << 16) | + (@as(u32, digest2[idx + 2]) << 8) | + (@as(u32, digest2[idx + 3])); + } + + return midstate; +} const Tag = struct { engine: fn () Hash, @@ -38,7 +63,7 @@ const TestHash = struct { // Hash some bytes and create a new TestHash pub fn hash(data: []const u8) TestHash { var sha256_engine = TestHashTag.engine(); - sha256_engine.update(data); + sha256_engine.input(data); // Debugging: Print engine state after update std.debug.print("Engine state after update: {x}\n", .{sha256_engine.s}); @@ -53,7 +78,6 @@ const TestHash = struct { } }; -// Test function using expectEqualSlices to compare TestHash output to the expected value test "manually created sha256t hash type" { var hash = TestHash.hash(&[_]u8{0}); try std.testing.expectEqualSlices(u8, &[32]u8{ @@ -61,6 +85,5 @@ test "manually created sha256t hash type" { 0xbc, 0xde, 0xb6, 0x70, 0x50, 0x69, 0xb4, 0xb5, 0x6a, 0x66, 0xec, 0x22, 0x51, 0x9d, 0x58, 0x29, }, &hash.data); - // You can also print success message if needed std.debug.print("Test passed: Hash matches expected value.\n", .{}); } From 5298fd2bb8296f80c94c5da763def781cba53557 Mon Sep 17 00:00:00 2001 From: Pia Date: Sun, 22 Sep 2024 16:16:14 +0900 Subject: [PATCH 4/5] fix: const midstate --- src/hashes/sha256.zig | 89 ++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/src/hashes/sha256.zig b/src/hashes/sha256.zig index 056be6d..eae36fc 100644 --- a/src/hashes/sha256.zig +++ b/src/hashes/sha256.zig @@ -34,43 +34,35 @@ const Midstate = struct { return blocks; } - // Creates midstate for tagged hashes. - // - // Computes non-finalized hash of `sha256(tag) || sha256(tag)` for use in [`sha256t`]. It's - // provided for use with [`sha256t`]. - // pub fn hash_tag(tag: []const u8) Midstate { - // var h = Hash.init(.{}); - // h.update(tag); - // const hash = h.finalResult(); - - // var buf: [64]u8 = undefined; - // for (&buf, 0..) |*buf_elem, idx| { - // buf_elem.* = hash[idx % 32]; - // } - - // var h2 = Hash.init(.{}); - // h2.update(&buf); - - // return Midstate{ .data = toBytes(h2.s), .length = 64 }; - // } -}; + /// Creates midstate for tagged hashes. + /// + /// Computes non-finalized hash of `sha256(tag) || sha256(tag)` for use in [`sha256t`]. It's + /// provided for use with [`sha256t`]. + pub fn hash_tag(tag: []const u8) Midstate { + var h = Hash.init(.{}); + h.update(tag); + const hash = h.finalResult(); + + var buf: [64]u8 = undefined; + for (&buf, 0..) |*buf_elem, idx| { + buf_elem.* = hash[idx % 32]; + } -// pub fn toBytes(blocks: [8]u32) [32]u8 { -// var data: [32]u8 = undefined; -// var idx: usize = 0; -// var idxBuff: usize = 0; -// while (idx < 8) : (idx += 1) { -// const word = blocks[idx]; - -// std.mem.readInt(u16, &[_]u8{ 0x12, 0x34 }); -// data[idxBuff] = @truncate(u8, word >> 24); -// data[idxBuff + 1] = @truncate(u8, word >> 16); -// data[idxBuff + 2] = @truncate(u8, word >> 8); -// data[idxBuff + 3] = @truncate(u8, word); -// idxBuff += 4; -// } -// return data; -// } + var h2 = Hash.init(.{}); + h2.update(&buf); + + var blocks: [32]u8 = undefined; + for (h2.s, 0..) |word, idx| { + const idx4 = idx * 4; + blocks[idx4] = @truncate(word >> 24); + blocks[idx4 + 1] = @truncate(word >> 16); + blocks[idx4 + 2] = @truncate(word >> 8); + blocks[idx4 + 3] = @truncate(word); + } + + return Midstate{ .data = blocks, .length = h2.total_len }; + } +}; const BLOCK_SIZE: usize = 64; @@ -128,17 +120,18 @@ test "Convert [32]u8 to [8]u32" { try std.testing.expectEqualSlices(u32, &expected, &result); } -// test "const midstate" { -// const expectedMidstate = Midstate{ -// .data = [32]u8{ -// 156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, -// 147, 108, 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201, -// }, -// .length = 64, -// }; +test "const midstate" { + const expectedMidstate = Midstate{ + .data = [32]u8{ + 156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, + 147, 108, 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201, + }, + .length = 64, + }; -// const midstate = Midstate.hash_tag("TapLeaf"); -// try std.testing.expectEqualSlices(u8, &expectedMidstate.data, &midstate.data); + const midstate = Midstate.hash_tag("TapLeaf"); -// try std.testing.expectEqual(expectedMidstate.length, midstate.length); -// } + try std.testing.expectEqualSlices(u8, &expectedMidstate.data, &midstate.data); + + try std.testing.expectEqual(expectedMidstate.length, midstate.length); +} From 6e03b937f0725b4c2058ca5cb40c538758ad5088 Mon Sep 17 00:00:00 2001 From: Pia Date: Sun, 22 Sep 2024 16:59:53 +0900 Subject: [PATCH 5/5] wip --- src/hashes/sha256.zig | 56 ++++++++++++++++++++++++++++++++++ src/hashes/sha256t.zig | 68 +++++++++++++----------------------------- 2 files changed, 76 insertions(+), 48 deletions(-) diff --git a/src/hashes/sha256.zig b/src/hashes/sha256.zig index eae36fc..e587c11 100644 --- a/src/hashes/sha256.zig +++ b/src/hashes/sha256.zig @@ -96,6 +96,25 @@ const HashEngine = struct { .length = midstate.length, }; } + + // TODO: need `input` compatible in rust implementation + // pub fn update(self: *HashEngine, data: []const u8) void { + // var sha = Hash.init(.{}); + // sha.update(data); + // self.h = sha.s; + // } + + pub fn getMidstate(self: *HashEngine) Midstate { + var midstate_bytes: [32]u8 = undefined; + for (self.h, 0..) |word, idx| { + const idx4 = idx * 4; + midstate_bytes[idx4] = @truncate(word >> 24); + midstate_bytes[idx4 + 1] = @truncate(word >> 16); + midstate_bytes[idx4 + 2] = @truncate(word >> 8); + midstate_bytes[idx4 + 3] = @truncate(word); + } + return Midstate{ .data = midstate_bytes, .length = self.length }; + } }; test "Convert [32]u8 to [8]u32" { @@ -135,3 +154,40 @@ test "const midstate" { try std.testing.expectEqual(expectedMidstate.length, midstate.length); } + +// TODO make it work +// test "midstate" { +// // Test vector obtained by doing an asset issuance on Elements +// var engine = HashEngine.new(); +// // sha256dhash of outpoint +// // 73828cbc65fd68ab78dc86992b76ae50ae2bf8ceedbe8de0483172f0886219f7:0 +// const input1: [32]u8 = [32]u8{ +// 0x9d, 0xd0, 0x1b, 0x56, 0xb1, 0x56, 0x45, 0x14, +// 0x3e, 0xad, 0x15, 0x8d, 0xec, 0x19, 0xf8, 0xce, +// 0xa9, 0x0b, 0xd0, 0xa9, 0xb2, 0xf8, 0x1d, 0x21, +// 0xff, 0xa3, 0xa4, 0xc6, 0x44, 0x81, 0xd4, 0x1c, +// }; +// engine.update(&input1); +// // 32 bytes of zeroes representing "new asset" +// const input2: [32]u8 = std.mem.zeroes([32]u8); +// engine.update(&input2); + +// // RPC output +// const WANT = Midstate{ +// .data = [32]u8{ +// 0x0b, 0xcf, 0xe0, 0xe5, 0x4e, 0x6c, 0xc7, 0xd3, +// 0x4f, 0x4f, 0x7c, 0x1d, 0xf0, 0xb0, 0xf5, 0x03, +// 0xf2, 0xf7, 0x12, 0x91, 0x2a, 0x06, 0x05, 0xb4, +// 0x14, 0xed, 0x33, 0x7f, 0x7f, 0x03, 0x2e, 0x03, +// }, +// .length = 64, +// }; + +// // get midstate +// const computed_midstate = engine.getMidstate(); + +// try std.testing.expectEqualSlices(u8, &WANT.data, &computed_midstate.data); +// try std.testing.expectEqual(WANT.length, computed_midstate.length); + +// std.debug.print("Test passed: Midstate matches expected value.\n", .{}); +// } diff --git a/src/hashes/sha256t.zig b/src/hashes/sha256t.zig index 1043246..a30c09f 100644 --- a/src/hashes/sha256t.zig +++ b/src/hashes/sha256t.zig @@ -1,58 +1,30 @@ const std = @import("std"); const Hash = std.crypto.hash.sha2.Sha256; const testing = std.testing; -const Midstate = @import("./sha256.zig"); -const HashEngine = @import("./sha256.zig"); +const Midstate = @import("./sha256.zig").Midstate; +const HashEngine = @import("./sha256.zig").HashEngine; -fn sha256t_tag(comptime tag: []const u8) [8]u32 { - var h = Hash.init(.{}); - h.update(tag); - const digest1 = h.finalResult(); - - var h2 = Hash.init(.{}); - h2.update(&digest1); - const digest2 = h2.finalResult(); - - var midstate: [8]u32 = undefined; - - var i: usize = 0; - while (i < 8) : (i += 1) { - const idx = i * 4; - midstate[i] = (@as(u32, digest2[idx]) << 24) | - (@as(u32, digest2[idx + 1]) << 16) | - (@as(u32, digest2[idx + 2]) << 8) | - (@as(u32, digest2[idx + 3])); - } - - return midstate; +fn sha256t_tag(comptime tag: []const u8) HashEngine { + const midstate = Midstate.hash_tag(tag); + return HashEngine.fromMidstate(midstate); } const Tag = struct { - engine: fn () Hash, -}; - -pub const Sha256t = struct { - const Self = @This(); - - sha256_engine: Hash, - - pub fn init() Self { - return Sha256t{ - .sha256_engine = Hash.init(.{}), - }; - } + engine: fn () HashEngine, }; const TestHashTag = struct { - fn engine() Hash { + fn engine() HashEngine { const TEST_MIDSTATE = [32]u8{ 156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, 147, 108, 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201, }; + const midstate = Midstate{ + .data = TEST_MIDSTATE, + .length = 64, + }; - var sha256_engine = Hash.init(.{}); - sha256_engine.update(&TEST_MIDSTATE); - return sha256_engine; + return HashEngine.fromMidstate(midstate); } }; @@ -78,12 +50,12 @@ const TestHash = struct { } }; -test "manually created sha256t hash type" { - var hash = TestHash.hash(&[_]u8{0}); - try std.testing.expectEqualSlices(u8, &[32]u8{ - 0xed, 0x13, 0x82, 0x03, 0x78, 0x00, 0xc9, 0xdd, 0x93, 0x8d, 0xd8, 0x85, 0x4f, 0x1a, 0x88, 0x63, - 0xbc, 0xde, 0xb6, 0x70, 0x50, 0x69, 0xb4, 0xb5, 0x6a, 0x66, 0xec, 0x22, 0x51, 0x9d, 0x58, 0x29, - }, &hash.data); +// test "manually created sha256t hash type" { +// var hash = TestHash.hash(&[_]u8{0}); +// try std.testing.expectEqualSlices(u8, &[32]u8{ +// 0xed, 0x13, 0x82, 0x03, 0x78, 0x00, 0xc9, 0xdd, 0x93, 0x8d, 0xd8, 0x85, 0x4f, 0x1a, 0x88, 0x63, +// 0xbc, 0xde, 0xb6, 0x70, 0x50, 0x69, 0xb4, 0xb5, 0x6a, 0x66, 0xec, 0x22, 0x51, 0x9d, 0x58, 0x29, +// }, &hash.data); - std.debug.print("Test passed: Hash matches expected value.\n", .{}); -} +// std.debug.print("Test passed: Hash matches expected value.\n", .{}); +// }