structstd.hash[src]

Types

TypeCrc32IsoHdlc[src]

Source Code

Source code
pub const Crc32IsoHdlc = Crc(u32, .{
    .polynomial = 0x04c11db7,
    .initial = 0xffffffff,
    .reflect_input = true,
    .reflect_output = true,
    .xor_output = 0xffffffff,
})

TypeFnv1a_32[src]

Source Code

Source code
pub const Fnv1a_32 = Fnv1a(u32, 0x01000193, 0x811c9dc5)

TypeFnv1a_64[src]

Source Code

Source code
pub const Fnv1a_64 = Fnv1a(u64, 0x100000001b3, 0xcbf29ce484222325)

TypeFnv1a_128[src]

Source Code

Source code
pub const Fnv1a_128 = Fnv1a(u128, 0x1000000000000000000013b, 0x6c62272e07bb014262b821756295c58d)

Type FunctionSipHash64[src]

SipHash function with 64-bit output.

Recommended parameters are:

  • (c_rounds=4, d_rounds=8) for conservative security; regular hash functions such as BLAKE2 or BLAKE3 are usually a better alternative.
  • (c_rounds=2, d_rounds=4) standard parameters.
  • (c_rounds=1, d_rounds=3) reduced-round function. Faster, no known implications on its practical security level.
  • (c_rounds=1, d_rounds=2) fastest option, but the output may be distinguishable from random data with related keys or non-uniform input - not suitable as a PRF.

SipHash is not a traditional hash function. If the input includes untrusted content, a secret key is absolutely necessary. And due to its small output size, collisions in SipHash64 can be found with an exhaustive search.

Parameters

c_rounds: usize
d_rounds: usize

Types

TypeWriter[src]

Source Code

Source code
pub const Writer = std.io.Writer(*Self, Error, write)

Fields

state: State
buf: [8]u8
buf_len: usize

Values

Constantkey_length[src]

Source Code

Source code
pub const key_length = 16

Constantmac_length[src]

Source Code

Source code
pub const mac_length = @sizeOf(T)

Constantblock_length[src]

Source Code

Source code
pub const block_length = 8

Error Sets

Error SetError[src]

Source Code

Source code
pub const Error = error{}

Functions

Functioninit[src]

pub fn init(key: *const [key_length]u8) Self

Initialize a state for a SipHash function

Parameters

key: *const [key_length]u8

Source Code

Source code
pub fn init(key: *const [key_length]u8) Self {
    return Self{
        .state = State.init(key),
        .buf = undefined,
        .buf_len = 0,
    };
}

Functionupdate[src]

pub fn update(self: *Self, b: []const u8) void

Add data to the state

Parameters

self: *Self
b: []const u8

Source Code

Source code
pub fn update(self: *Self, b: []const u8) void {
    var off: usize = 0;

    if (self.buf_len != 0 and self.buf_len + b.len >= 8) {
        off += 8 - self.buf_len;
        @memcpy(self.buf[self.buf_len..][0..off], b[0..off]);
        self.state.update(self.buf[0..]);
        self.buf_len = 0;
    }

    const remain_len = b.len - off;
    const aligned_len = remain_len - (remain_len % 8);
    self.state.update(b[off .. off + aligned_len]);

    const b_slice = b[off + aligned_len ..];
    @memcpy(self.buf[self.buf_len..][0..b_slice.len], b_slice);
    self.buf_len += @as(u8, @intCast(b_slice.len));
}

Functionpeek[src]

pub fn peek(self: Self) [mac_length]u8

Parameters

self: Self

Source Code

Source code
pub fn peek(self: Self) [mac_length]u8 {
    var copy = self;
    return copy.finalResult();
}

Functionfinal[src]

pub fn final(self: *Self, out: *[mac_length]u8) void

Return an authentication tag for the current state Assumes out is less than or equal to mac_length.

Parameters

self: *Self
out: *[mac_length]u8

Source Code

Source code
pub fn final(self: *Self, out: *[mac_length]u8) void {
    mem.writeInt(T, out, self.state.final(self.buf[0..self.buf_len]), .little);
}

FunctionfinalResult[src]

pub fn finalResult(self: *Self) [mac_length]u8

Parameters

self: *Self

Source Code

Source code
pub fn finalResult(self: *Self) [mac_length]u8 {
    var result: [mac_length]u8 = undefined;
    self.final(&result);
    return result;
}

Functioncreate[src]

pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [key_length]u8) void

Return an authentication tag for a message and a key

Parameters

out: *[mac_length]u8
msg: []const u8
key: *const [key_length]u8

Source Code

Source code
pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [key_length]u8) void {
    var ctx = Self.init(key);
    ctx.update(msg);
    ctx.final(out);
}

FunctionfinalInt[src]

pub fn finalInt(self: *Self) T

Return an authentication tag for the current state, as an integer

Parameters

self: *Self

Source Code

Source code
pub fn finalInt(self: *Self) T {
    return self.state.final(self.buf[0..self.buf_len]);
}

FunctiontoInt[src]

pub fn toInt(msg: []const u8, key: *const [key_length]u8) T

Return an authentication tag for a message and a key, as an integer

Parameters

msg: []const u8
key: *const [key_length]u8

Source Code

Source code
pub fn toInt(msg: []const u8, key: *const [key_length]u8) T {
    return State.hash(msg, key);
}

Functionwriter[src]

pub fn writer(self: *Self) Writer

Parameters

self: *Self

Source Code

Source code
pub fn writer(self: *Self) Writer {
    return .{ .context = self };
}

Source Code

Source code
pub fn SipHash64(comptime c_rounds: usize, comptime d_rounds: usize) type {
    return SipHash(u64, c_rounds, d_rounds);
}

Type FunctionSipHash128[src]

SipHash function with 128-bit output.

Recommended parameters are:

  • (c_rounds=4, d_rounds=8) for conservative security; regular hash functions such as BLAKE2 or BLAKE3 are usually a better alternative.
  • (c_rounds=2, d_rounds=4) standard parameters.
  • (c_rounds=1, d_rounds=4) reduced-round function. Recommended to hash very short, similar strings, when a 128-bit PRF output is still required.
  • (c_rounds=1, d_rounds=3) reduced-round function. Faster, no known implications on its practical security level.
  • (c_rounds=1, d_rounds=2) fastest option, but the output may be distinguishable from random data with related keys or non-uniform input - not suitable as a PRF.

SipHash is not a traditional hash function. If the input includes untrusted content, a secret key is absolutely necessary.

Parameters

c_rounds: usize
d_rounds: usize

Types

TypeWriter[src]

Source Code

Source code
pub const Writer = std.io.Writer(*Self, Error, write)

Fields

state: State
buf: [8]u8
buf_len: usize

Values

Constantkey_length[src]

Source Code

Source code
pub const key_length = 16

Constantmac_length[src]

Source Code

Source code
pub const mac_length = @sizeOf(T)

Constantblock_length[src]

Source Code

Source code
pub const block_length = 8

Error Sets

Error SetError[src]

Source Code

Source code
pub const Error = error{}

Functions

Functioninit[src]

pub fn init(key: *const [key_length]u8) Self

Initialize a state for a SipHash function

Parameters

key: *const [key_length]u8

Source Code

Source code
pub fn init(key: *const [key_length]u8) Self {
    return Self{
        .state = State.init(key),
        .buf = undefined,
        .buf_len = 0,
    };
}

Functionupdate[src]

pub fn update(self: *Self, b: []const u8) void

Add data to the state

Parameters

self: *Self
b: []const u8

Source Code

Source code
pub fn update(self: *Self, b: []const u8) void {
    var off: usize = 0;

    if (self.buf_len != 0 and self.buf_len + b.len >= 8) {
        off += 8 - self.buf_len;
        @memcpy(self.buf[self.buf_len..][0..off], b[0..off]);
        self.state.update(self.buf[0..]);
        self.buf_len = 0;
    }

    const remain_len = b.len - off;
    const aligned_len = remain_len - (remain_len % 8);
    self.state.update(b[off .. off + aligned_len]);

    const b_slice = b[off + aligned_len ..];
    @memcpy(self.buf[self.buf_len..][0..b_slice.len], b_slice);
    self.buf_len += @as(u8, @intCast(b_slice.len));
}

Functionpeek[src]

pub fn peek(self: Self) [mac_length]u8

Parameters

self: Self

Source Code

Source code
pub fn peek(self: Self) [mac_length]u8 {
    var copy = self;
    return copy.finalResult();
}

Functionfinal[src]

pub fn final(self: *Self, out: *[mac_length]u8) void

Return an authentication tag for the current state Assumes out is less than or equal to mac_length.

Parameters

self: *Self
out: *[mac_length]u8

Source Code

Source code
pub fn final(self: *Self, out: *[mac_length]u8) void {
    mem.writeInt(T, out, self.state.final(self.buf[0..self.buf_len]), .little);
}

FunctionfinalResult[src]

pub fn finalResult(self: *Self) [mac_length]u8

Parameters

self: *Self

Source Code

Source code
pub fn finalResult(self: *Self) [mac_length]u8 {
    var result: [mac_length]u8 = undefined;
    self.final(&result);
    return result;
}

Functioncreate[src]

pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [key_length]u8) void

Return an authentication tag for a message and a key

Parameters

out: *[mac_length]u8
msg: []const u8
key: *const [key_length]u8

Source Code

Source code
pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [key_length]u8) void {
    var ctx = Self.init(key);
    ctx.update(msg);
    ctx.final(out);
}

FunctionfinalInt[src]

pub fn finalInt(self: *Self) T

Return an authentication tag for the current state, as an integer

Parameters

self: *Self

Source Code

Source code
pub fn finalInt(self: *Self) T {
    return self.state.final(self.buf[0..self.buf_len]);
}

FunctiontoInt[src]

pub fn toInt(msg: []const u8, key: *const [key_length]u8) T

Return an authentication tag for a message and a key, as an integer

Parameters

msg: []const u8
key: *const [key_length]u8

Source Code

Source code
pub fn toInt(msg: []const u8, key: *const [key_length]u8) T {
    return State.hash(msg, key);
}

Functionwriter[src]

pub fn writer(self: *Self) Writer

Parameters

self: *Self

Source Code

Source code
pub fn writer(self: *Self) Writer {
    return .{ .context = self };
}

Source Code

Source code
pub fn SipHash128(comptime c_rounds: usize, comptime d_rounds: usize) type {
    return SipHash(u128, c_rounds, d_rounds);
}

Functions

FunctionautoHash[src]

pub fn autoHash(hasher: anytype, key: anytype) void

Provides generic hashing for any eligible type. Only hashes key itself, pointers are not followed. Slices as well as unions and structs containing slices are rejected to avoid ambiguity on the user's intention.

Source Code

Source code
pub fn autoHash(hasher: anytype, key: anytype) void {
    const Key = @TypeOf(key);
    if (comptime typeContainsSlice(Key)) {
        @compileError("std.hash.autoHash does not allow slices as well as unions and structs containing slices here (" ++ @typeName(Key) ++
            ") because the intent is unclear. Consider using std.hash.autoHashStrat or providing your own hash function instead.");
    }

    hash(hasher, key, .Shallow);
}

Functionhash[src]

pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void

Provides generic hashing for any eligible type. Strategy is provided to determine if pointers should be followed or not.

Parameters

Source Code

Source code
pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
    const Key = @TypeOf(key);
    const Hasher = switch (@typeInfo(@TypeOf(hasher))) {
        .pointer => |ptr| ptr.child,
        else => @TypeOf(hasher),
    };

    if (strat == .Shallow and std.meta.hasUniqueRepresentation(Key)) {
        @call(.always_inline, Hasher.update, .{ hasher, mem.asBytes(&key) });
        return;
    }

    switch (@typeInfo(Key)) {
        .noreturn,
        .@"opaque",
        .undefined,
        .null,
        .comptime_float,
        .comptime_int,
        .type,
        .enum_literal,
        .frame,
        .float,
        => @compileError("unable to hash type " ++ @typeName(Key)),

        .void => return,

        // Help the optimizer see that hashing an int is easy by inlining!
        // TODO Check if the situation is better after #561 is resolved.
        .int => |int| switch (int.signedness) {
            .signed => hash(hasher, @as(@Type(.{ .int = .{
                .bits = int.bits,
                .signedness = .unsigned,
            } }), @bitCast(key)), strat),
            .unsigned => {
                if (std.meta.hasUniqueRepresentation(Key)) {
                    @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key) });
                } else {
                    // Take only the part containing the key value, the remaining
                    // bytes are undefined and must not be hashed!
                    const byte_size = comptime std.math.divCeil(comptime_int, @bitSizeOf(Key), 8) catch unreachable;
                    @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key)[0..byte_size] });
                }
            },
        },

        .bool => hash(hasher, @intFromBool(key), strat),
        .@"enum" => hash(hasher, @intFromEnum(key), strat),
        .error_set => hash(hasher, @intFromError(key), strat),
        .@"anyframe", .@"fn" => hash(hasher, @intFromPtr(key), strat),

        .pointer => @call(.always_inline, hashPointer, .{ hasher, key, strat }),

        .optional => if (key) |k| hash(hasher, k, strat),

        .array => hashArray(hasher, key, strat),

        .vector => |info| {
            if (std.meta.hasUniqueRepresentation(Key)) {
                hasher.update(mem.asBytes(&key));
            } else {
                comptime var i = 0;
                inline while (i < info.len) : (i += 1) {
                    hash(hasher, key[i], strat);
                }
            }
        },

        .@"struct" => |info| {
            inline for (info.fields) |field| {
                // We reuse the hash of the previous field as the seed for the
                // next one so that they're dependant.
                hash(hasher, @field(key, field.name), strat);
            }
        },

        .@"union" => |info| {
            if (info.tag_type) |tag_type| {
                const tag = std.meta.activeTag(key);
                hash(hasher, tag, strat);
                inline for (info.fields) |field| {
                    if (@field(tag_type, field.name) == tag) {
                        if (field.type != void) {
                            hash(hasher, @field(key, field.name), strat);
                        }
                        // TODO use a labelled break when it does not crash the compiler. cf #2908
                        // break :blk;
                        return;
                    }
                }
                unreachable;
            } else @compileError("cannot hash untagged union type: " ++ @typeName(Key) ++ ", provide your own hash function");
        },

        .error_union => blk: {
            const payload = key catch |err| {
                hash(hasher, err, strat);
                break :blk;
            };
            hash(hasher, payload, strat);
        },
    }
}

Functionint[src]

pub fn int(input: anytype) @TypeOf(input)

Integer-to-integer hashing for bit widths <= 256.

Example Usage

test int {
    const expectEqual = @import("std").testing.expectEqual;
    try expectEqual(0x1, int(@as(u1, 1)));
    try expectEqual(0x3, int(@as(u2, 1)));
    try expectEqual(0x4, int(@as(u3, 1)));
    try expectEqual(0xD6, int(@as(u8, 1)));
    try expectEqual(0x2880, int(@as(u16, 1)));
    try expectEqual(0x2880, int(@as(i16, 1)));
    try expectEqual(0x838380, int(@as(u24, 1)));
    try expectEqual(0x42741D6, int(@as(u32, 1)));
    try expectEqual(0x42741D6, int(@as(i32, 1)));
    try expectEqual(0x71894DE00D9981F, int(@as(u64, 1)));
    try expectEqual(0x71894DE00D9981F, int(@as(i64, 1)));
}

Source Code

Source code
pub fn int(input: anytype) @TypeOf(input) {
    // This function is only intended for integer types
    const info = @typeInfo(@TypeOf(input)).int;
    const bits = info.bits;
    // Convert input to unsigned integer (easier to deal with)
    const Uint = @Type(.{ .int = .{ .bits = bits, .signedness = .unsigned } });
    const u_input: Uint = @bitCast(input);
    if (bits > 256) @compileError("bit widths > 256 are unsupported, use std.hash.autoHash functionality.");
    // For bit widths that don't have a dedicated function, use a heuristic
    // construction with a multiplier suited to diffusion -
    // a mod 2^bits where a^2 - 46 * a + 1 = 0 mod 2^(bits + 4),
    // on Mathematica: bits = 256; BaseForm[Solve[1 - 46 a + a^2 == 0, a, Modulus -> 2^(bits + 4)][[-1]][[1]][[2]], 16]
    const mult: Uint = @truncate(0xfac2e27ed2036860a062b5f264d80a512b00aa459b448bf1eca24d41c96f59e5b);
    // The bit width of the input integer determines how to hash it
    const output = switch (bits) {
        0...2 => u_input *% mult,
        16 => uint16(u_input),
        32 => uint32(u_input),
        64 => uint64(u_input),
        else => blk: {
            var x: Uint = u_input;
            inline for (0..4) |_| {
                x ^= x >> (bits / 2);
                x *%= mult;
            }
            break :blk x;
        },
    };
    return @bitCast(output);
}

Functionuint32[src]

pub fn uint32(input: u32) u32

DEPRECATED: use std.hash.int() Source: https://github.com/skeeto/hash-prospector

Parameters

input: u32

Source Code

Source code
pub fn uint32(input: u32) u32 {
    var x: u32 = input;
    x = (x ^ (x >> 17)) *% 0xed5ad4bb;
    x = (x ^ (x >> 11)) *% 0xac4c1b51;
    x = (x ^ (x >> 15)) *% 0x31848bab;
    x = x ^ (x >> 14);
    return x;
}

Source Code

Source code
const adler = @import("hash/adler.zig");
pub const Adler32 = adler.Adler32;

const auto_hash = @import("hash/auto_hash.zig");
pub const autoHash = auto_hash.autoHash;
pub const autoHashStrat = auto_hash.hash;
pub const Strategy = auto_hash.HashStrategy;

// pub for polynomials + generic crc32 construction
pub const crc = @import("hash/crc.zig");
pub const Crc32 = crc.Crc32;

const fnv = @import("hash/fnv.zig");
pub const Fnv1a_32 = fnv.Fnv1a_32;
pub const Fnv1a_64 = fnv.Fnv1a_64;
pub const Fnv1a_128 = fnv.Fnv1a_128;

const siphash = @import("crypto/siphash.zig");
pub const SipHash64 = siphash.SipHash64;
pub const SipHash128 = siphash.SipHash128;

pub const murmur = @import("hash/murmur.zig");
pub const Murmur2_32 = murmur.Murmur2_32;

pub const Murmur2_64 = murmur.Murmur2_64;
pub const Murmur3_32 = murmur.Murmur3_32;

pub const cityhash = @import("hash/cityhash.zig");
pub const CityHash32 = cityhash.CityHash32;
pub const CityHash64 = cityhash.CityHash64;

const wyhash = @import("hash/wyhash.zig");
pub const Wyhash = wyhash.Wyhash;

pub const RapidHash = @import("hash/RapidHash.zig");

const xxhash = @import("hash/xxhash.zig");
pub const XxHash3 = xxhash.XxHash3;
pub const XxHash64 = xxhash.XxHash64;
pub const XxHash32 = xxhash.XxHash32;

/// Integer-to-integer hashing for bit widths <= 256.
pub fn int(input: anytype) @TypeOf(input) {
    // This function is only intended for integer types
    const info = @typeInfo(@TypeOf(input)).int;
    const bits = info.bits;
    // Convert input to unsigned integer (easier to deal with)
    const Uint = @Type(.{ .int = .{ .bits = bits, .signedness = .unsigned } });
    const u_input: Uint = @bitCast(input);
    if (bits > 256) @compileError("bit widths > 256 are unsupported, use std.hash.autoHash functionality.");
    // For bit widths that don't have a dedicated function, use a heuristic
    // construction with a multiplier suited to diffusion -
    // a mod 2^bits where a^2 - 46 * a + 1 = 0 mod 2^(bits + 4),
    // on Mathematica: bits = 256; BaseForm[Solve[1 - 46 a + a^2 == 0, a, Modulus -> 2^(bits + 4)][[-1]][[1]][[2]], 16]
    const mult: Uint = @truncate(0xfac2e27ed2036860a062b5f264d80a512b00aa459b448bf1eca24d41c96f59e5b);
    // The bit width of the input integer determines how to hash it
    const output = switch (bits) {
        0...2 => u_input *% mult,
        16 => uint16(u_input),
        32 => uint32(u_input),
        64 => uint64(u_input),
        else => blk: {
            var x: Uint = u_input;
            inline for (0..4) |_| {
                x ^= x >> (bits / 2);
                x *%= mult;
            }
            break :blk x;
        },
    };
    return @bitCast(output);
}

/// Source: https://github.com/skeeto/hash-prospector
fn uint16(input: u16) u16 {
    var x: u16 = input;
    x = (x ^ (x >> 7)) *% 0x2993;
    x = (x ^ (x >> 5)) *% 0xe877;
    x = (x ^ (x >> 9)) *% 0x0235;
    x = x ^ (x >> 10);
    return x;
}

/// DEPRECATED: use std.hash.int()
/// Source: https://github.com/skeeto/hash-prospector
pub fn uint32(input: u32) u32 {
    var x: u32 = input;
    x = (x ^ (x >> 17)) *% 0xed5ad4bb;
    x = (x ^ (x >> 11)) *% 0xac4c1b51;
    x = (x ^ (x >> 15)) *% 0x31848bab;
    x = x ^ (x >> 14);
    return x;
}

/// Source: https://github.com/jonmaiga/mx3
fn uint64(input: u64) u64 {
    var x: u64 = input;
    const c = 0xbea225f9eb34556d;
    x = (x ^ (x >> 32)) *% c;
    x = (x ^ (x >> 29)) *% c;
    x = (x ^ (x >> 32)) *% c;
    x = x ^ (x >> 29);
    return x;
}

test int {
    const expectEqual = @import("std").testing.expectEqual;
    try expectEqual(0x1, int(@as(u1, 1)));
    try expectEqual(0x3, int(@as(u2, 1)));
    try expectEqual(0x4, int(@as(u3, 1)));
    try expectEqual(0xD6, int(@as(u8, 1)));
    try expectEqual(0x2880, int(@as(u16, 1)));
    try expectEqual(0x2880, int(@as(i16, 1)));
    try expectEqual(0x838380, int(@as(u24, 1)));
    try expectEqual(0x42741D6, int(@as(u32, 1)));
    try expectEqual(0x42741D6, int(@as(i32, 1)));
    try expectEqual(0x71894DE00D9981F, int(@as(u64, 1)));
    try expectEqual(0x71894DE00D9981F, int(@as(i64, 1)));
}

test {
    _ = adler;
    _ = auto_hash;
    _ = crc;
    _ = fnv;
    _ = murmur;
    _ = cityhash;
    _ = wyhash;
    _ = xxhash;
}