| author | |
| committer | |
| log | 56eb5323106cccfea7a5212dd6ab2e66d35f3f64 |
| tree | b59f8fa1e629042c79f05a3cdd1c828332dc1a50 |
| parent | fc78a22b96035b023c4fb138baee0ac9dcc4c42b |
| parent | 73046cd8097b6b37ee1e003c8c1ee83c6136ae48 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/371454 files changed, 72 insertions(+), 7 deletions(-)
lib/std/crypto.zig+1| ... | ... | @@ -302,6 +302,7 @@ test { |
| 302 | 302 | _ = core.aes; |
| 303 | 303 | _ = core.keccak; |
| 304 | 304 | _ = core.Ascon; |
| 305 | _ = core.keccak; | |
| 305 | 306 | _ = core.modes; |
| 306 | 307 | |
| 307 | 308 | _ = dh.X25519; |
lib/std/crypto/benchmark.zig+2| ... | ... | @@ -31,6 +31,8 @@ const hashes = [_]Crypto{ |
| 31 | 31 | Crypto{ .ty = crypto.hash.sha3.Shake256, .name = "shake-256" }, |
| 32 | 32 | Crypto{ .ty = crypto.hash.sha3.TurboShake128(null), .name = "turboshake-128" }, |
| 33 | 33 | Crypto{ .ty = crypto.hash.sha3.TurboShake256(null), .name = "turboshake-256" }, |
| 34 | Crypto{ .ty = crypto.hash.sha3.MiniShake128(null), .name = "minishake-128" }, | |
| 35 | Crypto{ .ty = crypto.hash.sha3.MiniShake256(null), .name = "minishake-256" }, | |
| 34 | 36 | Crypto{ .ty = crypto.hash.sha3.KT128, .name = "kt128" }, |
| 35 | 37 | Crypto{ .ty = crypto.hash.blake2.Blake2s256, .name = "blake2s" }, |
| 36 | 38 | Crypto{ .ty = crypto.hash.blake2.Blake2b512, .name = "blake2b" }, |
lib/std/crypto/keccak_p.zig+16-1| ... | ... | @@ -78,7 +78,7 @@ pub fn KeccakF(comptime f: u11) type { |
| 78 | 78 | |
| 79 | 79 | /// XOR a byte into the state at a given offset. |
| 80 | 80 | pub fn addByte(self: *Self, byte: u8, offset: usize) void { |
| 81 | const z = @sizeOf(T) * @as(math.Log2Int(T), @truncate(offset % @sizeOf(T))); | |
| 81 | const z: math.Log2Int(T) = @intCast(8 * (offset % @sizeOf(T))); | |
| 82 | 82 | self.st[offset / @sizeOf(T)] ^= @as(T, byte) << z; |
| 83 | 83 | } |
| 84 | 84 | |
| ... | ... | @@ -382,6 +382,21 @@ test "Keccak-f800" { |
| 382 | 382 | try std.testing.expectEqualSlices(u32, &st.st, &expected); |
| 383 | 383 | } |
| 384 | 384 | |
| 385 | test "addByte" { | |
| 386 | inline for (.{ 200, 400, 800, 1600 }) |f| { | |
| 387 | const F = KeccakF(f); | |
| 388 | for (0..F.block_bytes) |offset| { | |
| 389 | var a: F = .{}; | |
| 390 | a.addByte(0xa5, offset); | |
| 391 | var bytes: [F.block_bytes]u8 = @splat(0); | |
| 392 | bytes[offset] = 0xa5; | |
| 393 | var b: F = .{}; | |
| 394 | b.addBytes(&bytes); | |
| 395 | try std.testing.expectEqual(b.st, a.st); | |
| 396 | } | |
| 397 | } | |
| 398 | } | |
| 399 | ||
| 385 | 400 | test "squeeze" { |
| 386 | 401 | var st: State(800, 256, 22) = .init(@splat(0x80), 0x01); |
| 387 | 402 |
lib/std/crypto/sha3.zig+53-6| ... | ... | @@ -46,6 +46,28 @@ pub fn TurboShake256(comptime delim: ?u7) type { |
| 46 | 46 | return TurboShake(256, delim); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | /// MiniSHAKE128 is a XOF (a secure hash function with a variable output length), with a 128 bit security level. | |
| 50 | /// It works like TurboSHAKE128, with a permutation half the size. | |
| 51 | /// | |
| 52 | /// It was designed for hashing many short messages inside zero-knowledge proofs. | |
| 53 | /// Note: on 64-bit CPUs, it is about as fast as TurboSHAKE128 for inputs up to 67 bytes, and much slower for longer ones. | |
| 54 | /// | |
| 55 | /// The delimiter is 0x01 by default, but can be changed for domain separation. | |
| 56 | pub fn MiniShake128(comptime delim: ?u7) type { | |
| 57 | return MiniShake(128, delim); | |
| 58 | } | |
| 59 | ||
| 60 | /// MiniSHAKE256 is a XOF (a secure hash function with a variable output length), with a 256 bit security level. | |
| 61 | /// It works like TurboSHAKE256, with a permutation half the size. | |
| 62 | /// | |
| 63 | /// It was designed for hashing many short messages inside zero-knowledge proofs. | |
| 64 | /// Note: on 64-bit CPUs, it is much slower than TurboSHAKE256, even for short inputs. | |
| 65 | /// | |
| 66 | /// The delimiter is 0x01 by default, but can be changed for domain separation. | |
| 67 | pub fn MiniShake256(comptime delim: ?u7) type { | |
| 68 | return MiniShake(256, delim); | |
| 69 | } | |
| 70 | ||
| 49 | 71 | /// A generic Keccak hash function. |
| 50 | 72 | pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime default_delim: u8, comptime rounds: u5) type { |
| 51 | 73 | comptime assert(output_bits > 0 and output_bits * 2 < f and output_bits % 8 == 0); // invalid output length |
| ... | ... | @@ -97,7 +119,7 @@ pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime default_delim |
| 97 | 119 | |
| 98 | 120 | /// The SHAKE extendable output hash function. |
| 99 | 121 | pub fn Shake(comptime security_level: u11) type { |
| 100 | return ShakeLike(security_level, 0x1f, 24); | |
| 122 | return ShakeLike(1600, security_level, 0x1f, 24); | |
| 101 | 123 | } |
| 102 | 124 | |
| 103 | 125 | /// The TurboSHAKE extendable output hash function. |
| ... | ... | @@ -108,11 +130,24 @@ pub fn TurboShake(comptime security_level: u11, comptime delim: ?u7) type { |
| 108 | 130 | comptime assert(security_level <= 256); |
| 109 | 131 | const d = delim orelse 0x1f; |
| 110 | 132 | comptime assert(d >= 0x01); // delimiter must be >= 1 |
| 111 | return ShakeLike(security_level, d, 12); | |
| 133 | return ShakeLike(1600, security_level, d, 12); | |
| 134 | } | |
| 135 | ||
| 136 | /// The MiniSHAKE extendable output hash function. | |
| 137 | /// It is TurboSHAKE with an 800-bit permutation instead of a 1600-bit one. | |
| 138 | /// The security level must be a multiple of 4, up to 256. | |
| 139 | /// | |
| 140 | /// The delimiter is 0x01 by default, but can be changed for domain separation. | |
| 141 | /// | |
| 142 | /// https://eprint.iacr.org/2026/2363 | |
| 143 | pub fn MiniShake(comptime security_level: u11, comptime delim: ?u7) type { | |
| 144 | comptime assert(security_level > 0 and security_level <= 256 and security_level % 4 == 0); | |
| 145 | const d = delim orelse 0x01; | |
| 146 | comptime assert(d >= 0x01); | |
| 147 | return ShakeLike(800, security_level, d, 12); | |
| 112 | 148 | } |
| 113 | 149 | |
| 114 | fn ShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime rounds: u5) type { | |
| 115 | const f = 1600; | |
| 150 | fn ShakeLike(comptime f: u11, comptime security_level: u11, comptime default_delim: u8, comptime rounds: u5) type { | |
| 116 | 151 | const State = KeccakState(f, security_level * 2, rounds); |
| 117 | 152 | |
| 118 | 153 | return struct { |
| ... | ... | @@ -124,7 +159,7 @@ fn ShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime |
| 124 | 159 | padded: bool = false, |
| 125 | 160 | |
| 126 | 161 | /// The recommended output length, in bytes. |
| 127 | pub const digest_length = security_level / 8 * 2; | |
| 162 | pub const digest_length = security_level * 2 / 8; | |
| 128 | 163 | /// The block length, or rate, in bytes. |
| 129 | 164 | pub const block_length = State.rate; |
| 130 | 165 | /// The delimiter can be overwritten in the options. |
| ... | ... | @@ -202,7 +237,7 @@ pub fn CShake(comptime security_level: u11, comptime fname: ?[]const u8) type { |
| 202 | 237 | |
| 203 | 238 | fn CShakeLike(comptime security_level: u11, comptime default_delim: u8, comptime rounds: u5, comptime fname: ?[]const u8) type { |
| 204 | 239 | return struct { |
| 205 | const Shaker = ShakeLike(security_level, default_delim, rounds); | |
| 240 | const Shaker = ShakeLike(1600, security_level, default_delim, rounds); | |
| 206 | 241 | shaker: Shaker, |
| 207 | 242 | |
| 208 | 243 | /// The recommended output length, in bytes. |
| ... | ... | @@ -682,6 +717,18 @@ test "TurboSHAKE-128" { |
| 682 | 717 | try htest.assertEqual("8ec9c66465ed0d4a6c35d13506718d687a25cb05c74cca1e42501abd83874a67", &out); |
| 683 | 718 | } |
| 684 | 719 | |
| 720 | test "MiniSHAKE-128" { | |
| 721 | var out: [32]u8 = undefined; | |
| 722 | MiniShake128(null).hash("", &out, .{}); | |
| 723 | try htest.assertEqual("4e21f95d5dae60ddca7bc29b5a0da731d710b91f7e1effdb7bbd1055fd74618c", &out); | |
| 724 | } | |
| 725 | ||
| 726 | test "MiniSHAKE-256" { | |
| 727 | var out: [64]u8 = undefined; | |
| 728 | MiniShake256(null).hash("", &out, .{}); | |
| 729 | try htest.assertEqual("1e56563204eef4cef068b1666eec7ef033c43b70b8133d020773e6197dc7b61101e1b28360a9e589757371d7e3db8e1dface3d5661d39ab1c969850e50f550cc", &out); | |
| 730 | } | |
| 731 | ||
| 685 | 732 | test "SHA-3 with streaming" { |
| 686 | 733 | var msg: [613]u8 = [613]u8{ 0x97, 0xd1, 0x2d, 0x1a, 0x16, 0x2d, 0x36, 0x4d, 0x20, 0x62, 0x19, 0x0b, 0x14, 0x93, 0xbb, 0xf8, 0x5b, 0xea, 0x04, 0xc2, 0x61, 0x8e, 0xd6, 0x08, 0x81, 0xa1, 0x1d, 0x73, 0x27, 0x48, 0xbf, 0xa4, 0xba, 0xb1, 0x9a, 0x48, 0x9c, 0xf9, 0x9b, 0xff, 0x34, 0x48, 0xa9, 0x75, 0xea, 0xc8, 0xa3, 0x48, 0x24, 0x9d, 0x75, 0x27, 0x48, 0xec, 0x03, 0xb0, 0xbb, 0xdf, 0x33, 0x90, 0xe3, 0x93, 0xed, 0x68, 0x24, 0x39, 0x12, 0xdf, 0xea, 0xee, 0x8c, 0x9f, 0x96, 0xde, 0x42, 0x46, 0x8c, 0x2b, 0x17, 0x83, 0x36, 0xfb, 0xf4, 0xf7, 0xff, 0x79, 0xb9, 0x45, 0x41, 0xc9, 0x56, 0x1a, 0x6b, 0x0c, 0xa4, 0x1a, 0xdd, 0x6b, 0x95, 0xe8, 0x03, 0x0f, 0x09, 0x29, 0x40, 0x1b, 0xea, 0x87, 0xfa, 0xb9, 0x18, 0xa9, 0x95, 0x07, 0x7c, 0x2f, 0x7c, 0x33, 0xfb, 0xc5, 0x11, 0x5e, 0x81, 0x0e, 0xbc, 0xae, 0xec, 0xb3, 0xe1, 0x4a, 0x26, 0x56, 0xe8, 0x5b, 0x11, 0x9d, 0x37, 0x06, 0x9b, 0x34, 0x31, 0x6e, 0xa3, 0xba, 0x41, 0xbc, 0x11, 0xd8, 0xc5, 0x15, 0xc9, 0x30, 0x2c, 0x9b, 0xb6, 0x71, 0xd8, 0x7c, 0xbc, 0x38, 0x2f, 0xd5, 0xbd, 0x30, 0x96, 0xd4, 0xa3, 0x00, 0x77, 0x9d, 0x55, 0x4a, 0x33, 0x53, 0xb6, 0xb3, 0x35, 0x1b, 0xae, 0xe5, 0xdc, 0x22, 0x23, 0x85, 0x95, 0x88, 0xf9, 0x3b, 0xbf, 0x74, 0x13, 0xaa, 0xcb, 0x0a, 0x60, 0x79, 0x13, 0x79, 0xc0, 0x4a, 0x02, 0xdb, 0x1c, 0xc9, 0xff, 0x60, 0x57, 0x9a, 0x70, 0x28, 0x58, 0x60, 0xbc, 0x57, 0x07, 0xc7, 0x47, 0x1a, 0x45, 0x71, 0x76, 0x94, 0xfb, 0x05, 0xad, 0xec, 0x12, 0x29, 0x5a, 0x44, 0x6a, 0x81, 0xd9, 0xc6, 0xf0, 0xb6, 0x9b, 0x97, 0x83, 0x69, 0xfb, 0xdc, 0x0d, 0x4a, 0x67, 0xbc, 0x72, 0xf5, 0x43, 0x5e, 0x9b, 0x13, 0xf2, 0xe4, 0x6d, 0x49, 0xdb, 0x76, 0xcb, 0x42, 0x6a, 0x3c, 0x9f, 0xa1, 0xfe, 0x5e, 0xca, 0x0a, 0xfc, 0xfa, 0x39, 0x27, 0xd1, 0x3c, 0xcb, 0x9a, 0xde, 0x4c, 0x6b, 0x09, 0x8b, 0x49, 0xfd, 0x1e, 0x3d, 0x5e, 0x67, 0x7c, 0x57, 0xad, 0x90, 0xcc, 0x46, 0x5f, 0x5c, 0xae, 0x6a, 0x9c, 0xb2, 0xcd, 0x2c, 0x89, 0x78, 0xcf, 0xf1, 0x49, 0x96, 0x55, 0x1e, 0x04, 0xef, 0x0e, 0x1c, 0xde, 0x6c, 0x96, 0x51, 0x00, 0xee, 0x9a, 0x1f, 0x8d, 0x61, 0xbc, 0xeb, 0xb1, 0xa6, 0xa5, 0x21, 0x8b, 0xa7, 0xf8, 0x25, 0x41, 0x48, 0x62, 0x5b, 0x01, 0x6c, 0x7c, 0x2a, 0xe8, 0xff, 0xf9, 0xf9, 0x1f, 0xe2, 0x79, 0x2e, 0xd1, 0xff, 0xa3, 0x2e, 0x1c, 0x3a, 0x1a, 0x5d, 0x2b, 0x7b, 0x87, 0x25, 0x22, 0xa4, 0x90, 0xea, 0x26, 0x9d, 0xdd, 0x13, 0x60, 0x4c, 0x10, 0x03, 0xf6, 0x99, 0xd3, 0x21, 0x0c, 0x69, 0xc6, 0xd8, 0xc8, 0x9e, 0x94, 0x89, 0x51, 0x21, 0xe3, 0x9a, 0xcd, 0xda, 0x54, 0x72, 0x64, 0xae, 0x94, 0x79, 0x36, 0x81, 0x44, 0x14, 0x6d, 0x3a, 0x0e, 0xa6, 0x30, 0xbf, 0x95, 0x99, 0xa6, 0xf5, 0x7f, 0x4f, 0xef, 0xc6, 0x71, 0x2f, 0x36, 0x13, 0x14, 0xa2, 0x9d, 0xc2, 0x0c, 0x0d, 0x4e, 0xc0, 0x02, 0xd3, 0x6f, 0xee, 0x98, 0x5e, 0x24, 0x31, 0x74, 0x11, 0x96, 0x6e, 0x43, 0x57, 0xe8, 0x8e, 0xa0, 0x8d, 0x3d, 0x79, 0x38, 0x20, 0xc2, 0x0f, 0xb4, 0x75, 0x99, 0x3b, 0xb1, 0xf0, 0xe8, 0xe1, 0xda, 0xf9, 0xd4, 0xe6, 0xd6, 0xf4, 0x8a, 0x32, 0x4a, 0x4a, 0x25, 0xa8, 0xd9, 0x60, 0xd6, 0x33, 0x31, 0x97, 0xb9, 0xb6, 0xed, 0x5f, 0xfc, 0x15, 0xbd, 0x13, 0xc0, 0x3a, 0x3f, 0x1f, 0x2d, 0x09, 0x1d, 0xeb, 0x69, 0x6a, 0xfe, 0xd7, 0x95, 0x3e, 0x8a, 0x4e, 0xe1, 0x6e, 0x61, 0xb2, 0x6c, 0xe3, 0x2b, 0x70, 0x60, 0x7e, 0x8c, 0xe4, 0xdd, 0x27, 0x30, 0x7e, 0x0d, 0xc7, 0xb7, 0x9a, 0x1a, 0x3c, 0xcc, 0xa7, 0x22, 0x77, 0x14, 0x05, 0x50, 0x57, 0x31, 0x1b, 0xc8, 0xbf, 0xce, 0x52, 0xaf, 0x9c, 0x8e, 0x10, 0x2e, 0xd2, 0x16, 0xb6, 0x6e, 0x43, 0x10, 0xaf, 0x8b, 0xde, 0x1d, 0x60, 0xb2, 0x7d, 0xe6, 0x2f, 0x08, 0x10, 0x12, 0x7e, 0xb4, 0x76, 0x45, 0xb6, 0xd8, 0x9b, 0x26, 0x40, 0xa1, 0x63, 0x5c, 0x7a, 0x2a, 0xb1, 0x8c, 0xd6, 0xa4, 0x6f, 0x5a, 0xae, 0x33, 0x7e, 0x6d, 0x71, 0xf5, 0xc8, 0x6d, 0x80, 0x1c, 0x35, 0xfc, 0x3f, 0xc1, 0xa6, 0xc6, 0x1a, 0x15, 0x04, 0x6d, 0x76, 0x38, 0x32, 0x95, 0xb2, 0x51, 0x1a, 0xe9, 0x3e, 0x89, 0x9f, 0x0c, 0x79 }; |
| 687 | 734 | var out: [Sha3_256.digest_length]u8 = undefined; |