diff --git a/lib/std/bloom_filter.zig b/lib/std/bloom_filter.zig index 34fa42fe00064873349a7ad8c31df5c52c06bcab..0e251f548fff8438d4c9d411295983004c76df94 100644 --- a/lib/std/bloom_filter.zig +++ b/lib/std/bloom_filter.zig @@ -158,7 +158,7 @@ pub fn BloomFilter( } fn hashFunc(out: []u8, Ki: usize, in: []const u8) void { - var st = std.crypto.gimli.Hash.init(); + var st = std.crypto.hash.Gimli.init(.{}); st.update(std.mem.asBytes(&Ki)); st.update(in); st.final(out); diff --git a/lib/std/build/write_file.zig b/lib/std/build/write_file.zig index fe15e6e0e30b5d985b0723c9e66b4081e42d73a1..222de7c79ab76a5918e6ab02848ebf24a2def1ff 100644 --- a/lib/std/build/write_file.zig +++ b/lib/std/build/write_file.zig @@ -58,7 +58,7 @@ pub const WriteFileStep = struct { // TODO port the cache system from stage1 to zig std lib. Until then we use blake2b // directly and construct the path, and no "cache hit" detection happens; the files // are always written. - var hash = std.crypto.Blake2b384.init(); + var hash = std.crypto.hash.blake2.Blake2b384.init(); // Random bytes to make WriteFileStep unique. Refresh this with // new random bytes when WriteFileStep implementation is modified diff --git a/lib/std/cache_hash.zig b/lib/std/cache_hash.zig index 58c9f444f31ae252603f3e30b70b596d3af8bf02..edd0ebf12688f6778b062635d38b7a8f5478be20 100644 --- a/lib/std/cache_hash.zig +++ b/lib/std/cache_hash.zig @@ -4,7 +4,7 @@ // The MIT license requires this copyright notice to be included in all copies // and substantial portions of the software. const std = @import("std.zig"); -const Blake3 = std.crypto.Blake3; +const Blake3 = std.crypto.hash.Blake3; const fs = std.fs; const base64 = std.base64; const ArrayList = std.ArrayList; @@ -56,7 +56,7 @@ pub const CacheHash = struct { pub fn init(allocator: *Allocator, dir: fs.Dir, manifest_dir_path: []const u8) !CacheHash { return CacheHash{ .allocator = allocator, - .blake3 = Blake3.init(), + .blake3 = Blake3.init(.{}), .manifest_dir = try dir.makeOpenPath(manifest_dir_path, .{}), .manifest_file = null, .manifest_dirty = false, @@ -137,7 +137,7 @@ pub const CacheHash = struct { base64_encoder.encode(self.b64_digest[0..], &bin_digest); - self.blake3 = Blake3.init(); + self.blake3 = Blake3.init(.{}); self.blake3.update(&bin_digest); const manifest_file_path = try fmt.allocPrint(self.allocator, "{}.txt", .{self.b64_digest}); @@ -256,7 +256,7 @@ pub const CacheHash = struct { // cache miss // keep the manifest file open // reset the hash - self.blake3 = Blake3.init(); + self.blake3 = Blake3.init(.{}); self.blake3.update(&bin_digest); // Remove files not in the initial hash @@ -304,7 +304,7 @@ pub const CacheHash = struct { // Hash while reading from disk, to keep the contents in the cpu cache while // doing hashing. - var blake3 = Blake3.init(); + var blake3 = Blake3.init(.{}); var off: usize = 0; while (true) { // give me everything you've got, captain @@ -434,7 +434,7 @@ pub const CacheHash = struct { }; fn hashFile(file: fs.File, bin_digest: []u8) !void { - var blake3 = Blake3.init(); + var blake3 = Blake3.init(.{}); var buf: [1024]u8 = undefined; while (true) { diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig index edca2bc2ff4775368aa75c8ba8d5b914865bca11..32ab5071c588d769d78031a2b48ecf273da39051 100644 --- a/lib/std/crypto.zig +++ b/lib/std/crypto.zig @@ -3,60 +3,68 @@ // This file is part of [zig](https://ziglang.org/), which is MIT licensed. // The MIT license requires this copyright notice to be included in all copies // and substantial portions of the software. -pub const Md5 = @import("crypto/md5.zig").Md5; -pub const Sha1 = @import("crypto/sha1.zig").Sha1; - -const sha2 = @import("crypto/sha2.zig"); -pub const Sha224 = sha2.Sha224; -pub const Sha256 = sha2.Sha256; -pub const Sha384 = sha2.Sha384; -pub const Sha512 = sha2.Sha512; - -const sha3 = @import("crypto/sha3.zig"); -pub const Sha3_224 = sha3.Sha3_224; -pub const Sha3_256 = sha3.Sha3_256; -pub const Sha3_384 = sha3.Sha3_384; -pub const Sha3_512 = sha3.Sha3_512; - -pub const gimli = @import("crypto/gimli.zig"); - -const blake2 = @import("crypto/blake2.zig"); -pub const Blake2s224 = blake2.Blake2s224; -pub const Blake2s256 = blake2.Blake2s256; -pub const Blake2b384 = blake2.Blake2b384; -pub const Blake2b512 = blake2.Blake2b512; - -pub const Blake3 = @import("crypto/blake3.zig").Blake3; - -const hmac = @import("crypto/hmac.zig"); -pub const HmacMd5 = hmac.HmacMd5; -pub const HmacSha1 = hmac.HmacSha1; -pub const HmacSha256 = hmac.HmacSha256; -pub const HmacBlake2s256 = hmac.HmacBlake2s256; - -pub const chacha20 = @import("crypto/chacha20.zig"); -pub const chaCha20IETF = chacha20.chaCha20IETF; -pub const chaCha20With64BitNonce = chacha20.chaCha20With64BitNonce; -pub const xChaCha20IETF = chacha20.xChaCha20IETF; - -pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305; - -const import_aes = @import("crypto/aes.zig"); -pub const AES128 = import_aes.AES128; -pub const AES256 = import_aes.AES256; - -pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519; -pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519; -pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519; -pub const X25519 = @import("crypto/25519/x25519.zig").X25519; -pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255; +/// Hash functions. +pub const hash = struct { + pub const Md5 = @import("crypto/md5.zig").Md5; + pub const Sha1 = @import("crypto/sha1.zig").Sha1; + pub const sha2 = @import("crypto/sha2.zig"); + pub const sha3 = @import("crypto/sha3.zig"); + pub const blake2 = @import("crypto/blake2.zig"); + pub const Blake3 = @import("crypto/blake3.zig").Blake3; + pub const Gimli = @import("crypto/gimli.zig").Hash; +}; + +/// Authentication (MAC) functions. +pub const auth = struct { + pub const hmac = @import("crypto/hmac.zig"); +}; + +/// Authenticated Encryption with Associated Data pub const aead = struct { - pub const Gimli = gimli.Aead; + const chacha20 = @import("crypto/chacha20.zig"); + + pub const Gimli = @import("crypto/gimli.zig").Aead; pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305; pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305; }; +/// MAC functions requiring single-use secret keys. +pub const onetimeauth = struct { + pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305; +}; + +/// Core functions, that should rarely be used directly by applications. +pub const core = struct { + pub const aes = @import("crypto/aes.zig"); + pub const Gimli = @import("crypto/gimli.zig").State; +}; + +/// Elliptic-curve arithmetic. +pub const ecc = struct { + pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519; + pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519; + pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255; +}; + +/// Diffie-Hellman key exchange functions. +pub const dh = struct { + pub const X25519 = @import("crypto/25519/x25519.zig").X25519; +}; + +/// Digital signature functions. +pub const sign = struct { + pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519; +}; + +/// Stream ciphers. These do not provide any kind of authentication. +/// Most applications should be using AEAD constructions instead of stream ciphers directly. +pub const stream = struct { + pub const ChaCha20IETF = @import("crypto/chacha20.zig").ChaCha20IETF; + pub const XChaCha20IETF = @import("crypto/chacha20.zig").XChaCha20IETF; + pub const ChaCha20With64BitNonce = @import("crypto/chacha20.zig").ChaCha20With64BitNonce; +}; + const std = @import("std.zig"); pub const randomBytes = std.os.getrandom; @@ -83,27 +91,32 @@ test "crypto" { test "issue #4532: no index out of bounds" { const types = [_]type{ - Md5, - Sha1, - Sha224, - Sha256, - Sha384, - Sha512, - Blake2s224, - Blake2s256, - Blake2b384, - Blake2b512, + hash.Md5, + hash.Sha1, + hash.sha2.Sha224, + hash.sha2.Sha256, + hash.sha2.Sha384, + hash.sha2.Sha512, + hash.sha3.Sha3_224, + hash.sha3.Sha3_256, + hash.sha3.Sha3_384, + hash.sha3.Sha3_512, + hash.blake2.Blake2s224, + hash.blake2.Blake2s256, + hash.blake2.Blake2b384, + hash.blake2.Blake2b512, + hash.Gimli, }; inline for (types) |Hasher| { var block = [_]u8{'#'} ** Hasher.block_length; var out1: [Hasher.digest_length]u8 = undefined; var out2: [Hasher.digest_length]u8 = undefined; - - var h = Hasher.init(); + const h0 = Hasher.init(.{}); + var h = h0; h.update(block[0..]); h.final(out1[0..]); - h.reset(); + h = h0; h.update(block[0..1]); h.update(block[1..]); h.final(out2[0..]); diff --git a/lib/std/crypto/25519/ed25519.zig b/lib/std/crypto/25519/ed25519.zig index 935abaecb39def38927e317f2b9a7b32537b1208..9993afb6d2dec072bf7df7fe654542b39e7ecd16 100644 --- a/lib/std/crypto/25519/ed25519.zig +++ b/lib/std/crypto/25519/ed25519.zig @@ -6,7 +6,7 @@ const std = @import("std"); const fmt = std.fmt; const mem = std.mem; -const Sha512 = std.crypto.Sha512; +const Sha512 = std.crypto.hash.sha2.Sha512; /// Ed25519 (EdDSA) signatures. pub const Ed25519 = struct { @@ -33,7 +33,7 @@ pub const Ed25519 = struct { /// from which the actual secret is derived. pub fn createKeyPair(seed: [seed_length]u8) ![keypair_length]u8 { var az: [Sha512.digest_length]u8 = undefined; - var h = Sha512.init(); + var h = Sha512.init(.{}); h.update(&seed); h.final(&az); const p = try Curve.basePoint.clampedMul(az[0..32].*); @@ -56,11 +56,11 @@ pub const Ed25519 = struct { pub fn sign(msg: []const u8, key_pair: [keypair_length]u8, noise: ?[noise_length]u8) ![signature_length]u8 { const public_key = key_pair[32..]; var az: [Sha512.digest_length]u8 = undefined; - var h = Sha512.init(); + var h = Sha512.init(.{}); h.update(key_pair[0..seed_length]); h.final(&az); - h = Sha512.init(); + h = Sha512.init(.{}); if (noise) |*z| { h.update(z); } @@ -74,7 +74,7 @@ pub const Ed25519 = struct { var sig: [signature_length]u8 = undefined; mem.copy(u8, sig[0..32], &r.toBytes()); mem.copy(u8, sig[32..], public_key); - h = Sha512.init(); + h = Sha512.init(.{}); h.update(&sig); h.update(msg); var hram64: [Sha512.digest_length]u8 = undefined; @@ -98,7 +98,7 @@ pub const Ed25519 = struct { const a = try Curve.fromBytes(public_key); try a.rejectIdentity(); - var h = Sha512.init(); + var h = Sha512.init(.{}); h.update(r); h.update(&public_key); h.update(msg); diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig index 5c27f2f4f5374f75e6ad5c603c7911fb741def1e..70bd30d6bbf6e0a8ecddb22f0b1cbefe3b59ea73 100644 --- a/lib/std/crypto/benchmark.zig +++ b/lib/std/crypto/benchmark.zig @@ -22,20 +22,20 @@ const Crypto = struct { }; const hashes = [_]Crypto{ - Crypto{ .ty = crypto.Md5, .name = "md5" }, - Crypto{ .ty = crypto.Sha1, .name = "sha1" }, - Crypto{ .ty = crypto.Sha256, .name = "sha256" }, - Crypto{ .ty = crypto.Sha512, .name = "sha512" }, - Crypto{ .ty = crypto.Sha3_256, .name = "sha3-256" }, - Crypto{ .ty = crypto.Sha3_512, .name = "sha3-512" }, - Crypto{ .ty = crypto.gimli.Hash, .name = "gimli-hash" }, - Crypto{ .ty = crypto.Blake2s256, .name = "blake2s" }, - Crypto{ .ty = crypto.Blake2b512, .name = "blake2b" }, - Crypto{ .ty = crypto.Blake3, .name = "blake3" }, + Crypto{ .ty = crypto.hash.Md5, .name = "md5" }, + Crypto{ .ty = crypto.hash.Sha1, .name = "sha1" }, + Crypto{ .ty = crypto.hash.sha2.Sha256, .name = "sha256" }, + Crypto{ .ty = crypto.hash.sha2.Sha512, .name = "sha512" }, + Crypto{ .ty = crypto.hash.sha3.Sha3_256, .name = "sha3-256" }, + Crypto{ .ty = crypto.hash.sha3.Sha3_512, .name = "sha3-512" }, + Crypto{ .ty = crypto.hash.Gimli, .name = "gimli-hash" }, + Crypto{ .ty = crypto.hash.blake2.Blake2s256, .name = "blake2s" }, + Crypto{ .ty = crypto.hash.blake2.Blake2b512, .name = "blake2b" }, + Crypto{ .ty = crypto.hash.Blake3, .name = "blake3" }, }; pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 { - var h = Hash.init(); + var h = Hash.init(.{}); var block: [Hash.digest_length]u8 = undefined; prng.random.bytes(block[0..]); @@ -55,19 +55,20 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 } const macs = [_]Crypto{ - Crypto{ .ty = crypto.Poly1305, .name = "poly1305" }, - Crypto{ .ty = crypto.HmacMd5, .name = "hmac-md5" }, - Crypto{ .ty = crypto.HmacSha1, .name = "hmac-sha1" }, - Crypto{ .ty = crypto.HmacSha256, .name = "hmac-sha256" }, + Crypto{ .ty = crypto.onetimeauth.Poly1305, .name = "poly1305" }, + Crypto{ .ty = crypto.auth.hmac.HmacMd5, .name = "hmac-md5" }, + Crypto{ .ty = crypto.auth.hmac.HmacSha1, .name = "hmac-sha1" }, + Crypto{ .ty = crypto.auth.hmac.sha2.HmacSha256, .name = "hmac-sha256" }, + Crypto{ .ty = crypto.auth.hmac.sha2.HmacSha512, .name = "hmac-sha512" }, }; pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 { - std.debug.assert(32 >= Mac.mac_length and 32 >= Mac.minimum_key_length); + std.debug.assert(64 >= Mac.mac_length and 32 >= Mac.minimum_key_length); var in: [1 * MiB]u8 = undefined; prng.random.bytes(in[0..]); - var key: [32]u8 = undefined; + var key: [64]u8 = undefined; prng.random.bytes(key[0..]); var offset: usize = 0; @@ -84,7 +85,7 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 { return throughput; } -const exchanges = [_]Crypto{Crypto{ .ty = crypto.X25519, .name = "x25519" }}; +const exchanges = [_]Crypto{Crypto{ .ty = crypto.dh.X25519, .name = "x25519" }}; pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_count: comptime_int) !u64 { std.debug.assert(DhKeyExchange.minimum_key_length >= DhKeyExchange.secret_length); @@ -111,7 +112,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c return throughput; } -const signatures = [_]Crypto{Crypto{ .ty = crypto.Ed25519, .name = "ed25519" }}; +const signatures = [_]Crypto{Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" }}; pub fn benchmarkSignatures(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 { var seed: [Signature.seed_length]u8 = undefined; diff --git a/lib/std/crypto/blake2.zig b/lib/std/crypto/blake2.zig index 9f5194994deb73ba9b927db0b7d746185f6589bc..1cb143811cf3f861035f0ddfa4148105fb46d709 100644 --- a/lib/std/crypto/blake2.zig +++ b/lib/std/crypto/blake2.zig @@ -40,6 +40,7 @@ pub fn Blake2s(comptime out_len: usize) type { const Self = @This(); pub const block_length = 64; pub const digest_length = out_len / 8; + pub const Options = struct { key: ?[]const u8 = null, salt: ?[8]u8 = null, context: ?[8]u8 = null }; const iv = [8]u32{ 0x6A09E667, @@ -71,42 +72,36 @@ pub fn Blake2s(comptime out_len: usize) type { buf: [64]u8, buf_len: u8, - key: []const u8, - - pub fn init() Self { - return init_keyed(""); - } - - pub fn init_keyed(key: []const u8) Self { + pub fn init(options: Options) Self { debug.assert(8 <= out_len and out_len <= 512); - var s: Self = undefined; - s.key = key; - s.reset(); - return s; - } - - pub fn reset(d: *Self) void { + var d: Self = undefined; mem.copy(u32, d.h[0..], iv[0..]); + const key_len = if (options.key) |key| key.len else 0; // default parameters - d.h[0] ^= 0x01010000 ^ @truncate(u32, d.key.len << 8) ^ @intCast(u32, out_len >> 3); + d.h[0] ^= 0x01010000 ^ @truncate(u32, key_len << 8) ^ @intCast(u32, out_len >> 3); d.t = 0; d.buf_len = 0; - if (d.key.len > 0) { - mem.set(u8, d.buf[d.key.len..], 0); - d.update(d.key); + if (options.salt) |salt| { + d.h[4] ^= mem.readIntLittle(u32, salt[0..4]); + d.h[5] ^= mem.readIntLittle(u32, salt[4..8]); + } + if (options.context) |context| { + d.h[6] ^= mem.readIntLittle(u32, context[0..4]); + d.h[7] ^= mem.readIntLittle(u32, context[4..8]); + } + if (key_len > 0) { + mem.set(u8, d.buf[key_len..], 0); + d.update(options.key.?); d.buf_len = 64; } + return d; } - pub fn hash(b: []const u8, out: []u8) void { - Self.hash_keyed("", b, out); - } - - pub fn hash_keyed(key: []const u8, b: []const u8, out: []u8) void { - var d = Self.init_keyed(key); + pub fn hash(b: []const u8, out: []u8, options: Options) void { + var d = Self.init(options); d.update(b); d.final(out); } @@ -215,7 +210,7 @@ test "blake2s224 single" { } test "blake2s224 streaming" { - var h = Blake2s224.init(); + var h = Blake2s224.init(.{}); var out: [28]u8 = undefined; const h1 = "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4"; @@ -225,12 +220,12 @@ test "blake2s224 streaming" { const h2 = "0b033fc226df7abde29f67a05d3dc62cf271ef3dfea4d387407fbd55"; - h.reset(); + h = Blake2s224.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual(h2, out[0..]); - h.reset(); + h = Blake2s224.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -239,16 +234,29 @@ test "blake2s224 streaming" { const h3 = "557381a78facd2b298640f4e32113e58967d61420af1aa939d0cfe01"; - h.reset(); + h = Blake2s224.init(.{}); h.update("a" ** 32); h.update("b" ** 32); h.final(out[0..]); htest.assertEqual(h3, out[0..]); - h.reset(); + h = Blake2s224.init(.{}); h.update("a" ** 32 ++ "b" ** 32); h.final(out[0..]); htest.assertEqual(h3, out[0..]); + + const h4 = "a4d6a9d253441b80e5dfd60a04db169ffab77aec56a2855c402828c3"; + + h = Blake2s224.init(.{ .context = [_]u8{0x69} ** 8, .salt = [_]u8{0x42} ** 8 }); + h.update("a" ** 32); + h.update("b" ** 32); + h.final(out[0..]); + htest.assertEqual(h4, out[0..]); + + h = Blake2s224.init(.{ .context = [_]u8{0x69} ** 8, .salt = [_]u8{0x42} ** 8 }); + h.update("a" ** 32 ++ "b" ** 32); + h.final(out[0..]); + htest.assertEqual(h4, out[0..]); } test "comptime blake2s224" { @@ -261,7 +269,7 @@ test "comptime blake2s224" { htest.assertEqualHash(Blake2s224, h1, block[0..]); - var h = Blake2s224.init(); + var h = Blake2s224.init(.{}); h.update(&block); h.final(out[0..]); @@ -284,7 +292,7 @@ test "blake2s256 single" { } test "blake2s256 streaming" { - var h = Blake2s256.init(); + var h = Blake2s256.init(.{}); var out: [32]u8 = undefined; const h1 = "69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9"; @@ -294,12 +302,12 @@ test "blake2s256 streaming" { const h2 = "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"; - h.reset(); + h = Blake2s256.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual(h2, out[0..]); - h.reset(); + h = Blake2s256.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -308,13 +316,13 @@ test "blake2s256 streaming" { const h3 = "8d8711dade07a6b92b9a3ea1f40bee9b2c53ff3edd2a273dec170b0163568977"; - h.reset(); + h = Blake2s256.init(.{}); h.update("a" ** 32); h.update("b" ** 32); h.final(out[0..]); htest.assertEqual(h3, out[0..]); - h.reset(); + h = Blake2s256.init(.{}); h.update("a" ** 32 ++ "b" ** 32); h.final(out[0..]); htest.assertEqual(h3, out[0..]); @@ -326,16 +334,16 @@ test "blake2s256 keyed" { const h1 = "10f918da4d74fab3302e48a5d67d03804b1ec95372a62a0f33b7c9fa28ba1ae6"; const key = "secret_key"; - Blake2s256.hash_keyed(key, "a" ** 64 ++ "b" ** 64, &out); + Blake2s256.hash("a" ** 64 ++ "b" ** 64, &out, .{ .key = key }); htest.assertEqual(h1, out[0..]); - var h = Blake2s256.init_keyed(key); + var h = Blake2s256.init(.{ .key = key }); h.update("a" ** 64 ++ "b" ** 64); h.final(out[0..]); htest.assertEqual(h1, out[0..]); - h.reset(); + h = Blake2s256.init(.{ .key = key }); h.update("a" ** 64); h.update("b" ** 64); h.final(out[0..]); @@ -353,7 +361,7 @@ test "comptime blake2s256" { htest.assertEqualHash(Blake2s256, h1, block[0..]); - var h = Blake2s256.init(); + var h = Blake2s256.init(.{}); h.update(&block); h.final(out[0..]); @@ -364,6 +372,7 @@ test "comptime blake2s256" { ///////////////////// // Blake2b +pub const Blake2b256 = Blake2b(256); pub const Blake2b384 = Blake2b(384); pub const Blake2b512 = Blake2b(512); @@ -372,6 +381,7 @@ pub fn Blake2b(comptime out_len: usize) type { const Self = @This(); pub const block_length = 128; pub const digest_length = out_len / 8; + pub const Options = struct { key: ?[]const u8 = null, salt: ?[16]u8 = null, context: ?[16]u8 = null }; const iv = [8]u64{ 0x6a09e667f3bcc908, @@ -405,42 +415,36 @@ pub fn Blake2b(comptime out_len: usize) type { buf: [128]u8, buf_len: u8, - key: []const u8, - - pub fn init() Self { - return init_keyed(""); - } - - pub fn init_keyed(key: []const u8) Self { + pub fn init(options: Options) Self { debug.assert(8 <= out_len and out_len <= 512); - var s: Self = undefined; - s.key = key; - s.reset(); - return s; - } - - pub fn reset(d: *Self) void { + var d: Self = undefined; mem.copy(u64, d.h[0..], iv[0..]); + const key_len = if (options.key) |key| key.len else 0; // default parameters - d.h[0] ^= 0x01010000 ^ (d.key.len << 8) ^ (out_len >> 3); + d.h[0] ^= 0x01010000 ^ (key_len << 8) ^ (out_len >> 3); d.t = 0; d.buf_len = 0; - if (d.key.len > 0) { - mem.set(u8, d.buf[d.key.len..], 0); - d.update(d.key); + if (options.salt) |salt| { + d.h[4] ^= mem.readIntLittle(u64, salt[0..8]); + d.h[5] ^= mem.readIntLittle(u64, salt[8..16]); + } + if (options.context) |context| { + d.h[6] ^= mem.readIntLittle(u64, context[0..8]); + d.h[7] ^= mem.readIntLittle(u64, context[8..16]); + } + if (key_len > 0) { + mem.set(u8, d.buf[key_len..], 0); + d.update(options.key.?); d.buf_len = 128; } + return d; } - pub fn hash(b: []const u8, out: []u8) void { - Self.hash_keyed("", b, out); - } - - pub fn hash_keyed(key: []const u8, b: []const u8, out: []u8) void { - var d = Self.init_keyed(key); + pub fn hash(b: []const u8, out: []u8, options: Options) void { + var d = Self.init(options); d.update(b); d.final(out); } @@ -547,7 +551,7 @@ test "blake2b384 single" { } test "blake2b384 streaming" { - var h = Blake2b384.init(); + var h = Blake2b384.init(.{}); var out: [48]u8 = undefined; const h1 = "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100"; @@ -557,12 +561,12 @@ test "blake2b384 streaming" { const h2 = "6f56a82c8e7ef526dfe182eb5212f7db9df1317e57815dbda46083fc30f54ee6c66ba83be64b302d7cba6ce15bb556f4"; - h.reset(); + h = Blake2b384.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual(h2, out[0..]); - h.reset(); + h = Blake2b384.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -571,16 +575,36 @@ test "blake2b384 streaming" { const h3 = "b7283f0172fecbbd7eca32ce10d8a6c06b453cb3cf675b33eb4246f0da2bb94a6c0bdd6eec0b5fd71ec4fd51be80bf4c"; - h.reset(); + h = Blake2b384.init(.{}); h.update("a" ** 64 ++ "b" ** 64); h.final(out[0..]); htest.assertEqual(h3, out[0..]); - h.reset(); + h = Blake2b384.init(.{}); h.update("a" ** 64); h.update("b" ** 64); h.final(out[0..]); htest.assertEqual(h3, out[0..]); + + h = Blake2b384.init(.{}); + h.update("a" ** 64); + h.update("b" ** 64); + h.final(out[0..]); + htest.assertEqual(h3, out[0..]); + + const h4 = "934c48fcb197031c71f583d92f98703510805e72142e0b46f5752d1e971bc86c355d556035613ff7a4154b4de09dac5c"; + + h = Blake2b384.init(.{ .context = [_]u8{0x69} ** 16, .salt = [_]u8{0x42} ** 16 }); + h.update("a" ** 64); + h.update("b" ** 64); + h.final(out[0..]); + htest.assertEqual(h4, out[0..]); + + h = Blake2b384.init(.{ .context = [_]u8{0x69} ** 16, .salt = [_]u8{0x42} ** 16 }); + h.update("a" ** 64); + h.update("b" ** 64); + h.final(out[0..]); + htest.assertEqual(h4, out[0..]); } test "comptime blake2b384" { @@ -593,7 +617,7 @@ test "comptime blake2b384" { htest.assertEqualHash(Blake2b384, h1, block[0..]); - var h = Blake2b384.init(); + var h = Blake2b384.init(.{}); h.update(&block); h.final(out[0..]); @@ -616,7 +640,7 @@ test "blake2b512 single" { } test "blake2b512 streaming" { - var h = Blake2b512.init(); + var h = Blake2b512.init(.{}); var out: [64]u8 = undefined; const h1 = "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce"; @@ -626,12 +650,12 @@ test "blake2b512 streaming" { const h2 = "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"; - h.reset(); + h = Blake2b512.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual(h2, out[0..]); - h.reset(); + h = Blake2b512.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -640,12 +664,12 @@ test "blake2b512 streaming" { const h3 = "049980af04d6a2cf16b4b49793c3ed7e40732073788806f2c989ebe9547bda0541d63abe298ec8955d08af48ae731f2e8a0bd6d201655a5473b4aa79d211b920"; - h.reset(); + h = Blake2b512.init(.{}); h.update("a" ** 64 ++ "b" ** 64); h.final(out[0..]); htest.assertEqual(h3, out[0..]); - h.reset(); + h = Blake2b512.init(.{}); h.update("a" ** 64); h.update("b" ** 64); h.final(out[0..]); @@ -658,16 +682,16 @@ test "blake2b512 keyed" { const h1 = "8a978060ccaf582f388f37454363071ac9a67e3a704585fd879fb8a419a447e389c7c6de790faa20a7a7dccf197de736bc5b40b98a930b36df5bee7555750c4d"; const key = "secret_key"; - Blake2b512.hash_keyed(key, "a" ** 64 ++ "b" ** 64, &out); + Blake2b512.hash("a" ** 64 ++ "b" ** 64, &out, .{ .key = key }); htest.assertEqual(h1, out[0..]); - var h = Blake2b512.init_keyed(key); + var h = Blake2b512.init(.{ .key = key }); h.update("a" ** 64 ++ "b" ** 64); h.final(out[0..]); htest.assertEqual(h1, out[0..]); - h.reset(); + h = Blake2b512.init(.{ .key = key }); h.update("a" ** 64); h.update("b" ** 64); h.final(out[0..]); @@ -685,7 +709,7 @@ test "comptime blake2b512" { htest.assertEqualHash(Blake2b512, h1, block[0..]); - var h = Blake2b512.init(); + var h = Blake2b512.init(.{}); h.update(&block); h.final(out[0..]); diff --git a/lib/std/crypto/blake3.zig b/lib/std/crypto/blake3.zig index 08986965fc4a58b9d62adefbe23419bcff13ee9a..163c91b3584bd768801f4f593b36380ee15de6ae 100644 --- a/lib/std/crypto/blake3.zig +++ b/lib/std/crypto/blake3.zig @@ -279,6 +279,9 @@ fn parent_cv( /// An incremental hasher that can accept any number of writes. pub const Blake3 = struct { + pub const Options = struct { key: ?[KEY_LEN]u8 = null }; + pub const KdfOptions = struct {}; + chunk_state: ChunkState, key: [8]u32, cv_stack: [54][8]u32 = undefined, // Space for 54 subtree chaining values: @@ -296,21 +299,20 @@ pub const Blake3 = struct { }; } - /// Construct a new `Blake3` for the regular hash function. - pub fn init() Blake3 { - return Blake3.init_internal(IV, 0); - } - - /// Construct a new `Blake3` for the keyed hash function. - pub fn init_keyed(key: [KEY_LEN]u8) Blake3 { - var key_words: [8]u32 = undefined; - words_from_little_endian_bytes(key_words[0..], key[0..]); - return Blake3.init_internal(key_words, KEYED_HASH); + /// Construct a new `Blake3` for the hash function, with an optional key + pub fn init(options: Options) Blake3 { + if (options.key) |key| { + var key_words: [8]u32 = undefined; + words_from_little_endian_bytes(key_words[0..], key[0..]); + return Blake3.init_internal(key_words, KEYED_HASH); + } else { + return Blake3.init_internal(IV, 0); + } } /// Construct a new `Blake3` for the key derivation function. The context /// string should be hardcoded, globally unique, and application-specific. - pub fn init_derive_key(context: []const u8) Blake3 { + pub fn initKdf(context: []const u8, options: KdfOptions) Blake3 { var context_hasher = Blake3.init_internal(IV, DERIVE_KEY_CONTEXT); context_hasher.update(context); var context_key: [KEY_LEN]u8 = undefined; @@ -320,18 +322,12 @@ pub const Blake3 = struct { return Blake3.init_internal(context_key_words, DERIVE_KEY_MATERIAL); } - pub fn hash(in: []const u8, out: []u8) void { - var hasher = Blake3.init(); + pub fn hash(in: []const u8, out: []u8, options: Options) void { + var hasher = Blake3.init(options); hasher.update(in); hasher.final(out); } - /// Reset the `Blake3` to its initial state. - pub fn reset(self: *Blake3) void { - self.chunk_state = ChunkState.init(self.key, 0, self.flags); - self.cv_stack_len = 0; - } - fn push_cv(self: *Blake3, cv: [8]u32) void { self.cv_stack[self.cv_stack_len] = cv; self.cv_stack_len += 1; @@ -566,6 +562,9 @@ const reference_test = ReferenceTest{ }; fn test_blake3(hasher: *Blake3, input_len: usize, expected_hex: [262]u8) void { + // Save initial state + const initial_state = hasher.*; + // Setup input pattern var input_pattern: [251]u8 = undefined; for (input_pattern) |*e, i| e.* = @truncate(u8, i); @@ -581,18 +580,20 @@ fn test_blake3(hasher: *Blake3, input_len: usize, expected_hex: [262]u8) void { // Read final hash value var actual_bytes: [expected_hex.len / 2]u8 = undefined; hasher.final(actual_bytes[0..]); - hasher.reset(); // Compare to expected value var expected_bytes: [expected_hex.len / 2]u8 = undefined; fmt.hexToBytes(expected_bytes[0..], expected_hex[0..]) catch unreachable; testing.expectEqual(actual_bytes, expected_bytes); + + // Restore initial state + hasher.* = initial_state; } test "BLAKE3 reference test cases" { - var hash = &Blake3.init(); - var keyed_hash = &Blake3.init_keyed(reference_test.key.*); - var derive_key = &Blake3.init_derive_key(reference_test.context_string); + var hash = &Blake3.init(.{}); + var keyed_hash = &Blake3.init(.{ .key = reference_test.key.* }); + var derive_key = &Blake3.initKdf(reference_test.context_string, .{}); for (reference_test.cases) |t| { test_blake3(hash, t.input_len, t.hash.*); diff --git a/lib/std/crypto/chacha20.zig b/lib/std/crypto/chacha20.zig index d402eb67505c855da37c00f8ff1b96d91c55fd03..1a359ecfc75a93045b60a2056320bd6345e94f49 100644 --- a/lib/std/crypto/chacha20.zig +++ b/lib/std/crypto/chacha20.zig @@ -12,7 +12,7 @@ const assert = std.debug.assert; const testing = std.testing; const builtin = @import("builtin"); const maxInt = std.math.maxInt; -const Poly1305 = std.crypto.Poly1305; +const Poly1305 = std.crypto.onetimeauth.Poly1305; const QuarterRound = struct { a: usize, @@ -137,56 +137,60 @@ fn keyToWords(key: [32]u8) [8]u32 { /// /// ChaCha20 is self-reversing. To decrypt just run the cipher with the same /// counter, nonce, and key. -pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [12]u8) void { - assert(in.len >= out.len); - assert((in.len >> 6) + counter <= maxInt(u32)); +pub const ChaCha20IETF = struct { + pub fn xor(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [12]u8) void { + assert(in.len >= out.len); + assert((in.len >> 6) + counter <= maxInt(u32)); - var c: [4]u32 = undefined; - c[0] = counter; - c[1] = mem.readIntLittle(u32, nonce[0..4]); - c[2] = mem.readIntLittle(u32, nonce[4..8]); - c[3] = mem.readIntLittle(u32, nonce[8..12]); - chaCha20_internal(out, in, keyToWords(key), c); -} + var c: [4]u32 = undefined; + c[0] = counter; + c[1] = mem.readIntLittle(u32, nonce[0..4]); + c[2] = mem.readIntLittle(u32, nonce[4..8]); + c[3] = mem.readIntLittle(u32, nonce[8..12]); + chaCha20_internal(out, in, keyToWords(key), c); + } +}; /// This is the original ChaCha20 before RFC 7539, which recommends using the /// orgininal version on applications such as disk or file encryption that might /// exceed the 256 GiB limit of the 96-bit nonce version. -pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]u8, nonce: [8]u8) void { - assert(in.len >= out.len); - assert(counter +% (in.len >> 6) >= counter); +pub const ChaCha20With64BitNonce = struct { + pub fn xor(out: []u8, in: []const u8, counter: u64, key: [32]u8, nonce: [8]u8) void { + assert(in.len >= out.len); + assert(counter +% (in.len >> 6) >= counter); - var cursor: usize = 0; - const k = keyToWords(key); - var c: [4]u32 = undefined; - c[0] = @truncate(u32, counter); - c[1] = @truncate(u32, counter >> 32); - c[2] = mem.readIntLittle(u32, nonce[0..4]); - c[3] = mem.readIntLittle(u32, nonce[4..8]); + var cursor: usize = 0; + const k = keyToWords(key); + var c: [4]u32 = undefined; + c[0] = @truncate(u32, counter); + c[1] = @truncate(u32, counter >> 32); + c[2] = mem.readIntLittle(u32, nonce[0..4]); + c[3] = mem.readIntLittle(u32, nonce[4..8]); - const block_size = (1 << 6); - // The full block size is greater than the address space on a 32bit machine - const big_block = if (@sizeOf(usize) > 4) (block_size << 32) else maxInt(usize); + const block_size = (1 << 6); + // The full block size is greater than the address space on a 32bit machine + const big_block = if (@sizeOf(usize) > 4) (block_size << 32) else maxInt(usize); - // first partial big block - if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) { - chaCha20_internal(out[cursor..big_block], in[cursor..big_block], k, c); - cursor = big_block - cursor; - c[1] += 1; - if (comptime @sizeOf(usize) > 4) { - // A big block is giant: 256 GiB, but we can avoid this limitation - var remaining_blocks: u32 = @intCast(u32, (in.len / big_block)); - var i: u32 = 0; - while (remaining_blocks > 0) : (remaining_blocks -= 1) { - chaCha20_internal(out[cursor .. cursor + big_block], in[cursor .. cursor + big_block], k, c); - c[1] += 1; // upper 32-bit of counter, generic chaCha20_internal() doesn't know about this. - cursor += big_block; + // first partial big block + if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) { + chaCha20_internal(out[cursor..big_block], in[cursor..big_block], k, c); + cursor = big_block - cursor; + c[1] += 1; + if (comptime @sizeOf(usize) > 4) { + // A big block is giant: 256 GiB, but we can avoid this limitation + var remaining_blocks: u32 = @intCast(u32, (in.len / big_block)); + var i: u32 = 0; + while (remaining_blocks > 0) : (remaining_blocks -= 1) { + chaCha20_internal(out[cursor .. cursor + big_block], in[cursor .. cursor + big_block], k, c); + c[1] += 1; // upper 32-bit of counter, generic chaCha20_internal() doesn't know about this. + cursor += big_block; + } } } - } - chaCha20_internal(out[cursor..], in[cursor..], k, c); -} + chaCha20_internal(out[cursor..], in[cursor..], k, c); + } +}; // https://tools.ietf.org/html/rfc7539#section-2.4.2 test "crypto.chacha20 test vector sunscreen" { @@ -221,12 +225,12 @@ test "crypto.chacha20 test vector sunscreen" { 0, 0, 0, 0, }; - chaCha20IETF(result[0..], input[0..], 1, key, nonce); + ChaCha20IETF.xor(result[0..], input[0..], 1, key, nonce); testing.expectEqualSlices(u8, &expected_result, &result); // Chacha20 is self-reversing. var plaintext: [114]u8 = undefined; - chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce); + ChaCha20IETF.xor(plaintext[0..], result[0..], 1, key, nonce); testing.expect(mem.order(u8, input, &plaintext) == .eq); } @@ -261,7 +265,7 @@ test "crypto.chacha20 test vector 1" { }; const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 }; - chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); + ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce); testing.expectEqualSlices(u8, &expected_result, &result); } @@ -295,7 +299,7 @@ test "crypto.chacha20 test vector 2" { }; const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 }; - chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); + ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce); testing.expectEqualSlices(u8, &expected_result, &result); } @@ -329,7 +333,7 @@ test "crypto.chacha20 test vector 3" { }; const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 1 }; - chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); + ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce); testing.expectEqualSlices(u8, &expected_result, &result); } @@ -363,7 +367,7 @@ test "crypto.chacha20 test vector 4" { }; const nonce = [_]u8{ 1, 0, 0, 0, 0, 0, 0, 0 }; - chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); + ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce); testing.expectEqualSlices(u8, &expected_result, &result); } @@ -435,21 +439,21 @@ test "crypto.chacha20 test vector 5" { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, }; - chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); + ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce); testing.expectEqualSlices(u8, &expected_result, &result); } pub const chacha20poly1305_tag_size = 16; -pub fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void { +fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void { assert(ciphertext.len >= plaintext.len); // derive poly1305 key var polyKey = [_]u8{0} ** 32; - chaCha20IETF(polyKey[0..], polyKey[0..], 0, key, nonce); + ChaCha20IETF.xor(polyKey[0..], polyKey[0..], 0, key, nonce); // encrypt plaintext - chaCha20IETF(ciphertext[0..plaintext.len], plaintext, 1, key, nonce); + ChaCha20IETF.xor(ciphertext[0..plaintext.len], plaintext, 1, key, nonce); // construct mac var mac = Poly1305.init(polyKey[0..]); @@ -472,18 +476,18 @@ pub fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_ta mac.final(tag); } -pub fn chacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void { +fn chacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void { return chacha20poly1305SealDetached(ciphertextAndTag[0..plaintext.len], ciphertextAndTag[plaintext.len..][0..chacha20poly1305_tag_size], plaintext, data, key, nonce); } /// Verifies and decrypts an authenticated message produced by chacha20poly1305SealDetached. -pub fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { +fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { // split ciphertext and tag assert(dst.len >= ciphertext.len); // derive poly1305 key var polyKey = [_]u8{0} ** 32; - chaCha20IETF(polyKey[0..], polyKey[0..], 0, key, nonce); + ChaCha20IETF.xor(polyKey[0..], polyKey[0..], 0, key, nonce); // construct mac var mac = Poly1305.init(polyKey[0..]); @@ -519,11 +523,11 @@ pub fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *con } // decrypt ciphertext - chaCha20IETF(dst[0..ciphertext.len], ciphertext, 1, key, nonce); + ChaCha20IETF.xor(dst[0..ciphertext.len], ciphertext, 1, key, nonce); } /// Verifies and decrypts an authenticated message produced by chacha20poly1305Seal. -pub fn chacha20poly1305Open(dst: []u8, ciphertextAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { +fn chacha20poly1305Open(dst: []u8, ciphertextAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { if (ciphertextAndTag.len < chacha20poly1305_tag_size) { return error.InvalidMessage; } @@ -562,31 +566,33 @@ fn extend(key: [32]u8, nonce: [24]u8) struct { key: [32]u8, nonce: [12]u8 } { }; } -pub fn xChaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [24]u8) void { - const extended = extend(key, nonce); - chaCha20IETF(out, in, counter, extended.key, extended.nonce); -} +pub const XChaCha20IETF = struct { + pub fn xor(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [24]u8) void { + const extended = extend(key, nonce); + ChaCha20IETF.xor(out, in, counter, extended.key, extended.nonce); + } +}; pub const xchacha20poly1305_tag_size = 16; -pub fn xchacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void { +fn xchacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void { const extended = extend(key, nonce); return chacha20poly1305SealDetached(ciphertext, tag, plaintext, data, extended.key, extended.nonce); } -pub fn xchacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void { +fn xchacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void { const extended = extend(key, nonce); return chacha20poly1305Seal(ciphertextAndTag, plaintext, data, extended.key, extended.nonce); } /// Verifies and decrypts an authenticated message produced by xchacha20poly1305SealDetached. -pub fn xchacha20poly1305OpenDetached(plaintext: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { +fn xchacha20poly1305OpenDetached(plaintext: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { const extended = extend(key, nonce); return try chacha20poly1305OpenDetached(plaintext, ciphertext, tag, data, extended.key, extended.nonce); } /// Verifies and decrypts an authenticated message produced by xchacha20poly1305Seal. -pub fn xchacha20poly1305Open(ciphertextAndTag: []u8, msgAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { +fn xchacha20poly1305Open(ciphertextAndTag: []u8, msgAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { const extended = extend(key, nonce); return try chacha20poly1305Open(ciphertextAndTag, msgAndTag, data, extended.key, extended.nonce); } @@ -714,7 +720,7 @@ test "crypto.xchacha20" { const input = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; { var ciphertext: [input.len]u8 = undefined; - xChaCha20IETF(ciphertext[0..], input[0..], 0, key, nonce); + XChaCha20IETF.xor(ciphertext[0..], input[0..], 0, key, nonce); var buf: [2 * ciphertext.len]u8 = undefined; testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{ciphertext}), "E0A1BCF939654AFDBDC1746EC49832647C19D891F0D1A81FC0C1703B4514BDEA584B512F6908C2C5E9DD18D5CBC1805DE5803FE3B9CA5F193FB8359E91FAB0C3BB40309A292EB1CF49685C65C4A3ADF4F11DB0CD2B6B67FBC174BC2E860E8F769FD3565BBFAD1C845E05A0FED9BE167C240D"); } diff --git a/lib/std/crypto/gimli.zig b/lib/std/crypto/gimli.zig index 33afae5f82c5a311da4f677b18191f214ce0fc8c..9d139d6716f438d13eca733ac638965637d36383 100644 --- a/lib/std/crypto/gimli.zig +++ b/lib/std/crypto/gimli.zig @@ -109,13 +109,14 @@ pub const Hash = struct { state: State, buf_off: usize, + pub const block_length = State.RATE; + pub const Options = struct {}; + const Self = @This(); - pub fn init() Self { + pub fn init(options: Options) Self { return Self{ - .state = State{ - .data = [_]u32{0} ** (State.BLOCKBYTES / 4), - }, + .state = State{ .data = [_]u32{0} ** (State.BLOCKBYTES / 4) }, .buf_off = 0, }; } @@ -160,8 +161,8 @@ pub const Hash = struct { } }; -pub fn hash(out: []u8, in: []const u8) void { - var st = Hash.init(); +pub fn hash(out: []u8, in: []const u8, options: Hash.Options) void { + var st = Hash.init(options); st.update(in); st.final(out); } @@ -174,7 +175,7 @@ test "hash" { var msg: [58 / 2]u8 = undefined; try std.fmt.hexToBytes(&msg, "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C"); var md: [32]u8 = undefined; - hash(&md, &msg); + hash(&md, &msg, .{}); htest.assertEqual("1C9A03DC6A5DDC5444CFC6F4B154CFF5CF081633B2CEA4D7D0AE7CCFED5AAA44", &md); } diff --git a/lib/std/crypto/hmac.zig b/lib/std/crypto/hmac.zig index 984dacc96783e799595e14fb5abc6d6a0e4f1eac..700904555d4498c79565cec52f219e4f059eb100 100644 --- a/lib/std/crypto/hmac.zig +++ b/lib/std/crypto/hmac.zig @@ -8,10 +8,19 @@ const crypto = std.crypto; const debug = std.debug; const mem = std.mem; -pub const HmacMd5 = Hmac(crypto.Md5); -pub const HmacSha1 = Hmac(crypto.Sha1); -pub const HmacSha256 = Hmac(crypto.Sha256); -pub const HmacBlake2s256 = Hmac(crypto.Blake2s256); +pub const HmacMd5 = Hmac(crypto.hash.Md5); +pub const HmacSha1 = Hmac(crypto.hash.Sha1); + +pub const sha2 = struct { + pub const HmacSha224 = Hmac(crypto.hash.sha2.Sha224); + pub const HmacSha256 = Hmac(crypto.hash.sha2.Sha256); + pub const HmacSha384 = Hmac(crypto.hash.sha2.Sha384); + pub const HmacSha512 = Hmac(crypto.hash.sha2.Sha512); +}; + +pub const blake2 = struct { + pub const HmacBlake2s256 = Hmac(crypto.hash.blake2.Blake2s256); +}; pub fn Hmac(comptime Hash: type) type { return struct { @@ -36,7 +45,7 @@ pub fn Hmac(comptime Hash: type) type { // Normalize key length to block size of hash if (key.len > Hash.block_length) { - Hash.hash(key, ctx.scratch[0..mac_length]); + Hash.hash(key, ctx.scratch[0..mac_length], .{}); mem.set(u8, ctx.scratch[mac_length..Hash.block_length], 0); } else if (key.len < Hash.block_length) { mem.copy(u8, ctx.scratch[0..key.len], key); @@ -53,7 +62,7 @@ pub fn Hmac(comptime Hash: type) type { b.* = ctx.scratch[i] ^ 0x36; } - ctx.hash = Hash.init(); + ctx.hash = Hash.init(.{}); ctx.hash.update(ctx.i_key_pad[0..]); return ctx; } @@ -66,10 +75,10 @@ pub fn Hmac(comptime Hash: type) type { debug.assert(Hash.block_length >= out.len and out.len >= mac_length); ctx.hash.final(ctx.scratch[0..mac_length]); - ctx.hash.reset(); - ctx.hash.update(ctx.o_key_pad[0..]); - ctx.hash.update(ctx.scratch[0..mac_length]); - ctx.hash.final(out[0..mac_length]); + var ohash = Hash.init(.{}); + ohash.update(ctx.o_key_pad[0..]); + ohash.update(ctx.scratch[0..mac_length]); + ohash.final(out[0..mac_length]); } }; } @@ -95,10 +104,10 @@ test "hmac sha1" { } test "hmac sha256" { - var out: [HmacSha256.mac_length]u8 = undefined; - HmacSha256.create(out[0..], "", ""); + var out: [sha2.HmacSha256.mac_length]u8 = undefined; + sha2.HmacSha256.create(out[0..], "", ""); htest.assertEqual("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", out[0..]); - HmacSha256.create(out[0..], "The quick brown fox jumps over the lazy dog", "key"); + sha2.HmacSha256.create(out[0..], "The quick brown fox jumps over the lazy dog", "key"); htest.assertEqual("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8", out[0..]); } diff --git a/lib/std/crypto/md5.zig b/lib/std/crypto/md5.zig index d578ba8b957b6e0dc47358ecc81cdf5251c7e30d..0d221fabf682a8150e924e6536dbb0ae85b68a6f 100644 --- a/lib/std/crypto/md5.zig +++ b/lib/std/crypto/md5.zig @@ -32,10 +32,14 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar }; } +/// The MD5 function is now considered cryptographically broken. +/// Namely, it is trivial to find multiple inputs producing the same hash. +/// For a fast-performing, cryptographically secure hash function, see SHA512/256, BLAKE2 or BLAKE3. pub const Md5 = struct { const Self = @This(); pub const block_length = 64; pub const digest_length = 16; + pub const Options = struct {}; s: [4]u32, // Streaming Cache @@ -43,23 +47,22 @@ pub const Md5 = struct { buf_len: u8, total_len: u64, - pub fn init() Self { - var d: Self = undefined; - d.reset(); - return d; + pub fn init(options: Options) Self { + return Self{ + .s = [_]u32{ + 0x67452301, + 0xEFCDAB89, + 0x98BADCFE, + 0x10325476, + }, + .buf = undefined, + .buf_len = 0, + .total_len = 0, + }; } - pub fn reset(d: *Self) void { - d.s[0] = 0x67452301; - d.s[1] = 0xEFCDAB89; - d.s[2] = 0x98BADCFE; - d.s[3] = 0x10325476; - d.buf_len = 0; - d.total_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Md5.init(); + pub fn hash(b: []const u8, out: []u8, options: Options) void { + var d = Md5.init(options); d.update(b); d.final(out); } @@ -255,18 +258,18 @@ test "md5 single" { } test "md5 streaming" { - var h = Md5.init(); + var h = Md5.init(.{}); var out: [16]u8 = undefined; h.final(out[0..]); htest.assertEqual("d41d8cd98f00b204e9800998ecf8427e", out[0..]); - h.reset(); + h = Md5.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual("900150983cd24fb0d6963f7d28e17f72", out[0..]); - h.reset(); + h = Md5.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -279,7 +282,7 @@ test "md5 aligned final" { var block = [_]u8{0} ** Md5.block_length; var out: [Md5.digest_length]u8 = undefined; - var h = Md5.init(); + var h = Md5.init(.{}); h.update(&block); h.final(out[0..]); } diff --git a/lib/std/crypto/sha1.zig b/lib/std/crypto/sha1.zig index 7cb4fbcf36becff4ae793f2223abd884053c216b..03fd55b6a0e1bc82d76dd59960a1b475fcecad63 100644 --- a/lib/std/crypto/sha1.zig +++ b/lib/std/crypto/sha1.zig @@ -29,35 +29,35 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam { }; } +/// The SHA-1 function is now considered cryptographically broken. +/// Namely, it is feasible to find multiple inputs producing the same hash. +/// For a fast-performing, cryptographically secure hash function, see SHA512/256, BLAKE2 or BLAKE3. pub const Sha1 = struct { const Self = @This(); pub const block_length = 64; pub const digest_length = 20; + pub const Options = struct {}; s: [5]u32, // Streaming Cache - buf: [64]u8, - buf_len: u8, - total_len: u64, + buf: [64]u8 = undefined, + buf_len: u8 = 0, + total_len: u64 = 0, - pub fn init() Self { - var d: Self = undefined; - d.reset(); - return d; + pub fn init(options: Options) Self { + return Self{ + .s = [_]u32{ + 0x67452301, + 0xEFCDAB89, + 0x98BADCFE, + 0x10325476, + 0xC3D2E1F0, + }, + }; } - pub fn reset(d: *Self) void { - d.s[0] = 0x67452301; - d.s[1] = 0xEFCDAB89; - d.s[2] = 0x98BADCFE; - d.s[3] = 0x10325476; - d.s[4] = 0xC3D2E1F0; - d.buf_len = 0; - d.total_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Sha1.init(); + pub fn hash(b: []const u8, out: []u8, options: Options) void { + var d = Sha1.init(options); d.update(b); d.final(out); } @@ -277,18 +277,18 @@ test "sha1 single" { } test "sha1 streaming" { - var h = Sha1.init(); + var h = Sha1.init(.{}); var out: [20]u8 = undefined; h.final(out[0..]); htest.assertEqual("da39a3ee5e6b4b0d3255bfef95601890afd80709", out[0..]); - h.reset(); + h = Sha1.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual("a9993e364706816aba3e25717850c26c9cd0d89d", out[0..]); - h.reset(); + h = Sha1.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -300,7 +300,7 @@ test "sha1 aligned final" { var block = [_]u8{0} ** Sha1.block_length; var out: [Sha1.digest_length]u8 = undefined; - var h = Sha1.init(); + var h = Sha1.init(.{}); h.update(&block); h.final(out[0..]); } diff --git a/lib/std/crypto/sha2.zig b/lib/std/crypto/sha2.zig index cac18ca1f7b0f6e2faa90cdc19a3c927ba7002db..af2c22fe1ca6237887e59793ae61ecd05b22847e 100644 --- a/lib/std/crypto/sha2.zig +++ b/lib/std/crypto/sha2.zig @@ -77,7 +77,10 @@ const Sha256Params = Sha2Params32{ .out_len = 256, }; +/// SHA-224 pub const Sha224 = Sha2_32(Sha224Params); + +/// SHA-256 pub const Sha256 = Sha2_32(Sha256Params); fn Sha2_32(comptime params: Sha2Params32) type { @@ -85,34 +88,31 @@ fn Sha2_32(comptime params: Sha2Params32) type { const Self = @This(); pub const block_length = 64; pub const digest_length = params.out_len / 8; + pub const Options = struct {}; s: [8]u32, // Streaming Cache - buf: [64]u8, - buf_len: u8, - total_len: u64, + buf: [64]u8 = undefined, + buf_len: u8 = 0, + total_len: u64 = 0, - pub fn init() Self { - var d: Self = undefined; - d.reset(); - return d; + pub fn init(options: Options) Self { + return Self{ + .s = [_]u32{ + params.iv0, + params.iv1, + params.iv2, + params.iv3, + params.iv4, + params.iv5, + params.iv6, + params.iv7, + }, + }; } - pub fn reset(d: *Self) void { - d.s[0] = params.iv0; - d.s[1] = params.iv1; - d.s[2] = params.iv2; - d.s[3] = params.iv3; - d.s[4] = params.iv4; - d.s[5] = params.iv5; - d.s[6] = params.iv6; - d.s[7] = params.iv7; - d.buf_len = 0; - d.total_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); + pub fn hash(b: []const u8, out: []u8, options: Options) void { + var d = Self.init(options); d.update(b); d.final(out); } @@ -297,18 +297,18 @@ test "sha224 single" { } test "sha224 streaming" { - var h = Sha224.init(); + var h = Sha224.init(.{}); var out: [28]u8 = undefined; h.final(out[0..]); htest.assertEqual("d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", out[0..]); - h.reset(); + h = Sha224.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual("23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", out[0..]); - h.reset(); + h = Sha224.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -323,18 +323,18 @@ test "sha256 single" { } test "sha256 streaming" { - var h = Sha256.init(); + var h = Sha256.init(.{}); var out: [32]u8 = undefined; h.final(out[0..]); htest.assertEqual("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", out[0..]); - h.reset(); + h = Sha256.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", out[0..]); - h.reset(); + h = Sha256.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -346,7 +346,7 @@ test "sha256 aligned final" { var block = [_]u8{0} ** Sha256.block_length; var out: [Sha256.digest_length]u8 = undefined; - var h = Sha256.init(); + var h = Sha256.init(.{}); h.update(&block); h.final(out[0..]); } @@ -418,42 +418,72 @@ const Sha512Params = Sha2Params64{ .out_len = 512, }; +const Sha512256Params = Sha2Params64{ + .iv0 = 0x22312194FC2BF72C, + .iv1 = 0x9F555FA3C84C64C2, + .iv2 = 0x2393B86B6F53B151, + .iv3 = 0x963877195940EABD, + .iv4 = 0x96283EE2A88EFFE3, + .iv5 = 0xBE5E1E2553863992, + .iv6 = 0x2B0199FC2C85B8AA, + .iv7 = 0x0EB72DDC81C52CA2, + .out_len = 256, +}; + +const Sha512T256Params = Sha2Params64{ + .iv0 = 0x6A09E667F3BCC908, + .iv1 = 0xBB67AE8584CAA73B, + .iv2 = 0x3C6EF372FE94F82B, + .iv3 = 0xA54FF53A5F1D36F1, + .iv4 = 0x510E527FADE682D1, + .iv5 = 0x9B05688C2B3E6C1F, + .iv6 = 0x1F83D9ABFB41BD6B, + .iv7 = 0x5BE0CD19137E2179, + .out_len = 256, +}; + +/// SHA-384 pub const Sha384 = Sha2_64(Sha384Params); + +/// SHA-512 pub const Sha512 = Sha2_64(Sha512Params); +/// SHA-512/256 +pub const Sha512256 = Sha2_64(Sha512256Params); + +/// Truncated SHA-512 +pub const Sha512T256 = Sha2_64(Sha512T256Params); + fn Sha2_64(comptime params: Sha2Params64) type { return struct { const Self = @This(); pub const block_length = 128; pub const digest_length = params.out_len / 8; + pub const Options = struct {}; s: [8]u64, // Streaming Cache - buf: [128]u8, - buf_len: u8, - total_len: u128, + buf: [128]u8 = undefined, + buf_len: u8 = 0, + total_len: u128 = 0, - pub fn init() Self { - var d: Self = undefined; - d.reset(); - return d; + pub fn init(options: Options) Self { + return Self{ + .s = [_]u64{ + params.iv0, + params.iv1, + params.iv2, + params.iv3, + params.iv4, + params.iv5, + params.iv6, + params.iv7, + }, + }; } - pub fn reset(d: *Self) void { - d.s[0] = params.iv0; - d.s[1] = params.iv1; - d.s[2] = params.iv2; - d.s[3] = params.iv3; - d.s[4] = params.iv4; - d.s[5] = params.iv5; - d.s[6] = params.iv6; - d.s[7] = params.iv7; - d.buf_len = 0; - d.total_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); + pub fn hash(b: []const u8, out: []u8, options: Options) void { + var d = Self.init(options); d.update(b); d.final(out); } @@ -665,7 +695,7 @@ test "sha384 single" { } test "sha384 streaming" { - var h = Sha384.init(); + var h = Sha384.init(.{}); var out: [48]u8 = undefined; const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"; @@ -674,12 +704,12 @@ test "sha384 streaming" { const h2 = "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"; - h.reset(); + h = Sha384.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual(h2, out[0..]); - h.reset(); + h = Sha384.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -699,7 +729,7 @@ test "sha512 single" { } test "sha512 streaming" { - var h = Sha512.init(); + var h = Sha512.init(.{}); var out: [64]u8 = undefined; const h1 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"; @@ -708,12 +738,12 @@ test "sha512 streaming" { const h2 = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"; - h.reset(); + h = Sha512.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual(h2, out[0..]); - h.reset(); + h = Sha512.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -725,7 +755,7 @@ test "sha512 aligned final" { var block = [_]u8{0} ** Sha512.block_length; var out: [Sha512.digest_length]u8 = undefined; - var h = Sha512.init(); + var h = Sha512.init(.{}); h.update(&block); h.final(out[0..]); } diff --git a/lib/std/crypto/sha3.zig b/lib/std/crypto/sha3.zig index 03635ca55378345371d049f4bbad4f8a23007e5b..3d6dad1be17078ece1e7459f213778dd10b49936 100644 --- a/lib/std/crypto/sha3.zig +++ b/lib/std/crypto/sha3.zig @@ -20,25 +20,18 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type { const Self = @This(); pub const block_length = 200; pub const digest_length = bits / 8; + pub const Options = struct {}; s: [200]u8, offset: usize, rate: usize, - pub fn init() Self { - var d: Self = undefined; - d.reset(); - return d; + pub fn init(options: Options) Self { + return Self{ .s = [_]u8{0} ** 200, .offset = 0, .rate = 200 - (bits / 4) }; } - pub fn reset(d: *Self) void { - mem.set(u8, d.s[0..], 0); - d.offset = 0; - d.rate = 200 - (bits / 4); - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); + pub fn hash(b: []const u8, out: []u8, options: Options) void { + var d = Self.init(options); d.update(b); d.final(out); } @@ -183,18 +176,18 @@ test "sha3-224 single" { } test "sha3-224 streaming" { - var h = Sha3_224.init(); + var h = Sha3_224.init(.{}); var out: [28]u8 = undefined; h.final(out[0..]); htest.assertEqual("6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", out[0..]); - h.reset(); + h = Sha3_224.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual("e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", out[0..]); - h.reset(); + h = Sha3_224.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -209,18 +202,18 @@ test "sha3-256 single" { } test "sha3-256 streaming" { - var h = Sha3_256.init(); + var h = Sha3_256.init(.{}); var out: [32]u8 = undefined; h.final(out[0..]); htest.assertEqual("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", out[0..]); - h.reset(); + h = Sha3_256.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual("3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", out[0..]); - h.reset(); + h = Sha3_256.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -232,7 +225,7 @@ test "sha3-256 aligned final" { var block = [_]u8{0} ** Sha3_256.block_length; var out: [Sha3_256.digest_length]u8 = undefined; - var h = Sha3_256.init(); + var h = Sha3_256.init(.{}); h.update(&block); h.final(out[0..]); } @@ -247,7 +240,7 @@ test "sha3-384 single" { } test "sha3-384 streaming" { - var h = Sha3_384.init(); + var h = Sha3_384.init(.{}); var out: [48]u8 = undefined; const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"; @@ -255,12 +248,12 @@ test "sha3-384 streaming" { htest.assertEqual(h1, out[0..]); const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25"; - h.reset(); + h = Sha3_384.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual(h2, out[0..]); - h.reset(); + h = Sha3_384.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -278,7 +271,7 @@ test "sha3-512 single" { } test "sha3-512 streaming" { - var h = Sha3_512.init(); + var h = Sha3_512.init(.{}); var out: [64]u8 = undefined; const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"; @@ -286,12 +279,12 @@ test "sha3-512 streaming" { htest.assertEqual(h1, out[0..]); const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"; - h.reset(); + h = Sha3_512.init(.{}); h.update("abc"); h.final(out[0..]); htest.assertEqual(h2, out[0..]); - h.reset(); + h = Sha3_512.init(.{}); h.update("a"); h.update("b"); h.update("c"); @@ -303,7 +296,7 @@ test "sha3-512 aligned final" { var block = [_]u8{0} ** Sha3_512.block_length; var out: [Sha3_512.digest_length]u8 = undefined; - var h = Sha3_512.init(); + var h = Sha3_512.init(.{}); h.update(&block); h.final(out[0..]); } diff --git a/lib/std/crypto/test.zig b/lib/std/crypto/test.zig index e4e34e543b95f2732df65c61afdbaa3b91757898..2987706b11aa5e2db0481d8ca8c80206bb235e30 100644 --- a/lib/std/crypto/test.zig +++ b/lib/std/crypto/test.zig @@ -11,7 +11,7 @@ const fmt = std.fmt; // Hash using the specified hasher `H` asserting `expected == H(input)`. pub fn assertEqualHash(comptime Hasher: anytype, comptime expected: []const u8, input: []const u8) void { var h: [expected.len / 2]u8 = undefined; - Hasher.hash(input, h[0..]); + Hasher.hash(input, h[0..], .{}); assertEqual(expected, &h); } diff --git a/lib/std/rand.zig b/lib/std/rand.zig index 85f11ff44992131bad4ec11ec1fbc2e8c3333256..42726472bf4703ca879cb74bf091ca5ed374e342 100644 --- a/lib/std/rand.zig +++ b/lib/std/rand.zig @@ -737,12 +737,12 @@ test "xoroshiro sequence" { // CSPRNG pub const Gimli = struct { random: Random, - state: std.crypto.gimli.State, + state: std.crypto.core.Gimli, pub fn init(init_s: u64) Gimli { var self = Gimli{ .random = Random{ .fillFn = fill }, - .state = std.crypto.gimli.State{ + .state = std.crypto.core.Gimli{ .data = [_]u32{0} ** (std.crypto.gimli.State.BLOCKBYTES / 4), }, }; diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 34e03eb1648c3e1b99b214f53adca9db5750f0be..e86a12884ffce894500740007300a945fbd61e24 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -26,7 +26,7 @@ pub fn hashSrc(src: []const u8) SrcHash { std.mem.copy(u8, &out, src); std.mem.set(u8, out[src.len..], 0); } else { - std.crypto.Blake3.hash(src, &out); + std.crypto.hash.Blake3.hash(src, &out, .{}); } return out; } diff --git a/tools/process_headers.zig b/tools/process_headers.zig index d17069401e5cc79f3f15e4dc364945e814761c79..918802f65d091ffe54b40077b5e359a29e7bd761 100644 --- a/tools/process_headers.zig +++ b/tools/process_headers.zig @@ -313,7 +313,7 @@ pub fn main() !void { var max_bytes_saved: usize = 0; var total_bytes: usize = 0; - var hasher = std.crypto.Sha256.init(); + var hasher = std.crypto.hash.sha2.Sha256.init(.{}); for (libc_targets) |libc_target| { const dest_target = DestTarget{