authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2025-11-07 08:20:04+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-11-07 08:20:04+01:00
log4b593a6c24797484e68a668818736b0f6a8d81a2
treed140c424346e4dd46688c00023d9a3b39ee99a1f
parent2e8f8afc832112ad03125a403f66d7d9058eeac8
signaturebadge-check Signed by PGP key B5690EEEBB952194

std.crypto: improve KT documentation, use key_length for B3 key length (#25807)

It was not obvious that the KT128/KT256 customization string can be used to set a key, or what it was designed to be used for at all. Also properly use key_length and not digest_length for the BLAKE3 key length (no practical changes as they are both 32, but that was confusing). Remove unneeded simd_degree copies by the way, and that doesn't need to be in the public interface.

2 files changed, 45 insertions(+), 15 deletions(-)

lib/std/crypto/blake3.zig+7-9
...@@ -12,8 +12,8 @@ const Vec16 = @Vector(16, u32);...@@ -12,8 +12,8 @@ const Vec16 = @Vector(16, u32);
12const chunk_length = 1024;12const chunk_length = 1024;
13const max_depth = 54;13const max_depth = 54;
1414
15pub const simd_degree = std.simd.suggestVectorLength(u32) orelse 1;15const simd_degree = std.simd.suggestVectorLength(u32) orelse 1;
16pub const max_simd_degree = simd_degree;16const max_simd_degree = simd_degree;
17const max_simd_degree_or_2 = if (max_simd_degree > 2) max_simd_degree else 2;17const max_simd_degree_or_2 = if (max_simd_degree > 2) max_simd_degree else 2;
1818
19/// Threshold for switching to parallel processing.19/// Threshold for switching to parallel processing.
...@@ -502,9 +502,7 @@ fn hashManySimd(...@@ -502,9 +502,7 @@ fn hashManySimd(
502 var out_ptr = out.ptr;502 var out_ptr = out.ptr;
503 var cnt = counter;503 var cnt = counter;
504504
505 const simd_deg = comptime simd_degree;505 if (simd_degree >= 16) {
506
507 if (comptime simd_deg >= 16) {
508 while (remaining >= 16) {506 while (remaining >= 16) {
509 const sixteen_inputs = [16][*]const u8{507 const sixteen_inputs = [16][*]const u8{
510 inp[0], inp[1], inp[2], inp[3],508 inp[0], inp[1], inp[2], inp[3],
...@@ -525,7 +523,7 @@ fn hashManySimd(...@@ -525,7 +523,7 @@ fn hashManySimd(
525 }523 }
526 }524 }
527525
528 if (comptime simd_deg >= 8) {526 if (simd_degree >= 8) {
529 while (remaining >= 8) {527 while (remaining >= 8) {
530 const eight_inputs = [8][*]const u8{528 const eight_inputs = [8][*]const u8{
531 inp[0], inp[1], inp[2], inp[3],529 inp[0], inp[1], inp[2], inp[3],
...@@ -544,7 +542,7 @@ fn hashManySimd(...@@ -544,7 +542,7 @@ fn hashManySimd(
544 }542 }
545 }543 }
546544
547 if (comptime simd_deg >= 4) {545 if (simd_degree >= 4) {
548 while (remaining >= 4) {546 while (remaining >= 4) {
549 const four_inputs = [4][*]const u8{547 const four_inputs = [4][*]const u8{
550 inp[0],548 inp[0],
...@@ -571,7 +569,7 @@ fn hashManySimd(...@@ -571,7 +569,7 @@ fn hashManySimd(
571}569}
572570
573fn hashMany(inputs: [][*]const u8, num_inputs: usize, blocks: usize, key: [8]u32, counter: u64, increment_counter: bool, flags: Flags, flags_start: Flags, flags_end: Flags, out: []u8) void {571fn hashMany(inputs: [][*]const u8, num_inputs: usize, blocks: usize, key: [8]u32, counter: u64, increment_counter: bool, flags: Flags, flags_start: Flags, flags_end: Flags, out: []u8) void {
574 if (comptime max_simd_degree >= 4) {572 if (max_simd_degree >= 4) {
575 hashManySimd(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out);573 hashManySimd(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out);
576 } else {574 } else {
577 hashManyPortable(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out);575 hashManyPortable(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out);
...@@ -909,7 +907,7 @@ pub const Blake3 = struct {...@@ -909,7 +907,7 @@ pub const Blake3 = struct {
909 pub const digest_length = 32;907 pub const digest_length = 32;
910 pub const key_length = 32;908 pub const key_length = 32;
911909
912 pub const Options = struct { key: ?[digest_length]u8 = null };910 pub const Options = struct { key: ?[key_length]u8 = null };
913 pub const KdfOptions = struct {};911 pub const KdfOptions = struct {};
914912
915 key: [8]u32,913 key: [8]u32,
lib/std/crypto/kangarootwelve.zig+38-6
...@@ -840,7 +840,21 @@ fn KTHash(...@@ -840,7 +840,21 @@ fn KTHash(
840 /// The block length, or rate, in bytes.840 /// The block length, or rate, in bytes.
841 pub const block_length = Variant.rate;841 pub const block_length = Variant.rate;
842842
843 /// Options for KangarooTwelve can include a customization string for domain separation.843 /// Configuration options for KangarooTwelve hashing.
844 ///
845 /// Options include an optional customization string that provides domain separation,
846 /// ensuring that identical inputs with different customization strings
847 /// produce completely distinct hash outputs.
848 ///
849 /// This prevents hash collisions when the same data is hashed in different contexts.
850 ///
851 /// Customization strings can be of any length.
852 ///
853 /// Common options for customization::
854 ///
855 /// - Key derivation or MAC: 16-byte secret for KT128, 32-byte secret for KT256
856 /// - Context Separation: domain-specific strings (e.g., "email", "password", "session")
857 /// - Composite Keys: concatenation of secret key + context string
844 pub const Options = struct {858 pub const Options = struct {
845 customization: ?[]const u8 = null,859 customization: ?[]const u8 = null,
846 };860 };
...@@ -864,7 +878,20 @@ fn KTHash(...@@ -864,7 +878,20 @@ fn KTHash(
864 pending_count: usize, // Number of complete chunks in pending_chunks878 pending_count: usize, // Number of complete chunks in pending_chunks
865879
866 /// Initialize a KangarooTwelve hashing context.880 /// Initialize a KangarooTwelve hashing context.
867 /// The customization string is optional and used for domain separation.881 ///
882 /// Options include an optional customization string that provides domain separation,
883 /// ensuring that identical inputs with different customization strings
884 /// produce completely distinct hash outputs.
885 ///
886 /// This prevents hash collisions when the same data is hashed in different contexts.
887 ///
888 /// Customization strings can be of any length.
889 ///
890 /// Common options for customization::
891 ///
892 /// - Key derivation or MAC: 16-byte secret for KT128, 32-byte secret for KT256
893 /// - Context Separation: domain-specific strings (e.g., "email", "password", "session")
894 /// - Composite Keys: concatenation of secret key + context string
868 pub fn init(options: Options) Self {895 pub fn init(options: Options) Self {
869 const custom = options.customization orelse &[_]u8{};896 const custom = options.customization orelse &[_]u8{};
870 return .{897 return .{
...@@ -971,7 +998,13 @@ fn KTHash(...@@ -971,7 +998,13 @@ fn KTHash(
971 }998 }
972999
973 /// Finalize the hash and produce output.1000 /// Finalize the hash and produce output.
974 /// After calling this, the context should not be reused.1001 ///
1002 /// Unlike traditional hash functions, the output can be of any length.
1003 ///
1004 /// When using as a regular hash function, use the recommended `digest_length` value (32 bytes for KT128, 64 bytes for KT256).
1005 ///
1006 /// After calling this method, the context should not be reused. However, the structure can be cloned before finalizing
1007 /// to compute multiple hashes with the same prefix.
975 pub fn final(self: *Self, out: []u8) void {1008 pub fn final(self: *Self, out: []u8) void {
976 const cv_size = Variant.cv_size;1009 const cv_size = Variant.cv_size;
9771010
...@@ -1063,12 +1096,11 @@ fn KTHash(...@@ -1063,12 +1096,11 @@ fn KTHash(
1063 }1096 }
10641097
1065 /// Hash a message using sequential processing with SIMD acceleration.1098 /// Hash a message using sequential processing with SIMD acceleration.
1066 /// Best performance for inputs under 10MB. Never allocates memory.
1067 ///1099 ///
1068 /// Parameters:1100 /// Parameters:
1069 /// - message: Input data to hash (any length)1101 /// - message: Input data to hash (any length)
1070 /// - out: Output buffer (any length, arbitrary output sizes supported)1102 /// - out: Output buffer (any length, arbitrary output sizes supported, `digest_length` recommended for standard use)
1071 /// - options: Optional settings including customization string for domain separation1103 /// - options: Optional settings to include a secret key or a context separation string
1072 pub fn hash(message: []const u8, out: []u8, options: Options) !void {1104 pub fn hash(message: []const u8, out: []u8, options: Options) !void {
1073 const custom = options.customization orelse &[_]u8{};1105 const custom = options.customization orelse &[_]u8{};
10741106