Commit 4b593a6c24

Frank Denis <124872+jedisct1@users.noreply.github.com>
2025-11-07 08:20:04
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.
1 parent 2e8f8af
Changed files (2)
lib/std/crypto/blake3.zig
@@ -12,8 +12,8 @@ const Vec16 = @Vector(16, u32);
 const chunk_length = 1024;
 const max_depth = 54;
 
-pub const simd_degree = std.simd.suggestVectorLength(u32) orelse 1;
-pub const max_simd_degree = simd_degree;
+const simd_degree = std.simd.suggestVectorLength(u32) orelse 1;
+const max_simd_degree = simd_degree;
 const max_simd_degree_or_2 = if (max_simd_degree > 2) max_simd_degree else 2;
 
 /// Threshold for switching to parallel processing.
@@ -502,9 +502,7 @@ fn hashManySimd(
     var out_ptr = out.ptr;
     var cnt = counter;
 
-    const simd_deg = comptime simd_degree;
-
-    if (comptime simd_deg >= 16) {
+    if (simd_degree >= 16) {
         while (remaining >= 16) {
             const sixteen_inputs = [16][*]const u8{
                 inp[0],  inp[1],  inp[2],  inp[3],
@@ -525,7 +523,7 @@ fn hashManySimd(
         }
     }
 
-    if (comptime simd_deg >= 8) {
+    if (simd_degree >= 8) {
         while (remaining >= 8) {
             const eight_inputs = [8][*]const u8{
                 inp[0], inp[1], inp[2], inp[3],
@@ -544,7 +542,7 @@ fn hashManySimd(
         }
     }
 
-    if (comptime simd_deg >= 4) {
+    if (simd_degree >= 4) {
         while (remaining >= 4) {
             const four_inputs = [4][*]const u8{
                 inp[0],
@@ -571,7 +569,7 @@ fn hashManySimd(
 }
 
 fn 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 {
-    if (comptime max_simd_degree >= 4) {
+    if (max_simd_degree >= 4) {
         hashManySimd(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out);
     } else {
         hashManyPortable(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out);
@@ -909,7 +907,7 @@ pub const Blake3 = struct {
     pub const digest_length = 32;
     pub const key_length = 32;
 
-    pub const Options = struct { key: ?[digest_length]u8 = null };
+    pub const Options = struct { key: ?[key_length]u8 = null };
     pub const KdfOptions = struct {};
 
     key: [8]u32,
lib/std/crypto/kangarootwelve.zig
@@ -840,7 +840,21 @@ fn KTHash(
         /// The block length, or rate, in bytes.
         pub const block_length = Variant.rate;
 
-        /// Options for KangarooTwelve can include a customization string for domain separation.
+        /// Configuration options for KangarooTwelve hashing.
+        ///
+        /// Options include an optional customization string that provides domain separation,
+        /// ensuring that identical inputs with different customization strings
+        /// produce completely distinct hash outputs.
+        ///
+        /// This prevents hash collisions when the same data is hashed in different contexts.
+        ///
+        /// Customization strings can be of any length.
+        ///
+        /// Common options for customization::
+        ///
+        /// - Key derivation or MAC: 16-byte secret for KT128, 32-byte secret for KT256
+        /// - Context Separation: domain-specific strings (e.g., "email", "password", "session")
+        /// - Composite Keys: concatenation of secret key + context string
         pub const Options = struct {
             customization: ?[]const u8 = null,
         };
@@ -864,7 +878,20 @@ fn KTHash(
         pending_count: usize, // Number of complete chunks in pending_chunks
 
         /// Initialize a KangarooTwelve hashing context.
-        /// The customization string is optional and used for domain separation.
+        ///
+        /// Options include an optional customization string that provides domain separation,
+        /// ensuring that identical inputs with different customization strings
+        /// produce completely distinct hash outputs.
+        ///
+        /// This prevents hash collisions when the same data is hashed in different contexts.
+        ///
+        /// Customization strings can be of any length.
+        ///
+        /// Common options for customization::
+        ///
+        /// - Key derivation or MAC: 16-byte secret for KT128, 32-byte secret for KT256
+        /// - Context Separation: domain-specific strings (e.g., "email", "password", "session")
+        /// - Composite Keys: concatenation of secret key + context string
         pub fn init(options: Options) Self {
             const custom = options.customization orelse &[_]u8{};
             return .{
@@ -971,7 +998,13 @@ fn KTHash(
         }
 
         /// Finalize the hash and produce output.
-        /// After calling this, the context should not be reused.
+        ///
+        /// Unlike traditional hash functions, the output can be of any length.
+        ///
+        /// When using as a regular hash function, use the recommended `digest_length` value (32 bytes for KT128, 64 bytes for KT256).
+        ///
+        /// After calling this method, the context should not be reused. However, the structure can be cloned before finalizing
+        /// to compute multiple hashes with the same prefix.
         pub fn final(self: *Self, out: []u8) void {
             const cv_size = Variant.cv_size;
 
@@ -1063,12 +1096,11 @@ fn KTHash(
         }
 
         /// Hash a message using sequential processing with SIMD acceleration.
-        /// Best performance for inputs under 10MB. Never allocates memory.
         ///
         /// Parameters:
         ///   - message: Input data to hash (any length)
-        ///   - out: Output buffer (any length, arbitrary output sizes supported)
-        ///   - options: Optional settings including customization string for domain separation
+        ///   - out: Output buffer (any length, arbitrary output sizes supported, `digest_length` recommended for standard use)
+        ///   - options: Optional settings to include a secret key or a context separation string
         pub fn hash(message: []const u8, out: []u8, options: Options) !void {
             const custom = options.customization orelse &[_]u8{};