authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-20 19:01:22-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-08-20 19:01:22-04:00
log21106b9c9f9287a7f4477ac9a0b1b8ad04e245c3
tree3aff693b14dc10730329168ad65a85b04eaed730
parent9cfcd0c29677e11f76846b006757ff49e05e3d6f
parent3edace34d38c95673e56930ccfee1d16d0003359
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6095 from jedisct1/crypto-reorg

Breaking: sort std/crypto functions into categories

19 files changed, 492 insertions(+), 411 deletions(-)

lib/std/bloom_filter.zig+1-1
...@@ -158,7 +158,7 @@ pub fn BloomFilter(...@@ -158,7 +158,7 @@ pub fn BloomFilter(
158}158}
159159
160fn hashFunc(out: []u8, Ki: usize, in: []const u8) void {160fn hashFunc(out: []u8, Ki: usize, in: []const u8) void {
161 var st = std.crypto.gimli.Hash.init();161 var st = std.crypto.hash.Gimli.init(.{});
162 st.update(std.mem.asBytes(&Ki));162 st.update(std.mem.asBytes(&Ki));
163 st.update(in);163 st.update(in);
164 st.final(out);164 st.final(out);
lib/std/build/write_file.zig+1-1
...@@ -58,7 +58,7 @@ pub const WriteFileStep = struct {...@@ -58,7 +58,7 @@ pub const WriteFileStep = struct {
58 // TODO port the cache system from stage1 to zig std lib. Until then we use blake2b58 // TODO port the cache system from stage1 to zig std lib. Until then we use blake2b
59 // directly and construct the path, and no "cache hit" detection happens; the files59 // directly and construct the path, and no "cache hit" detection happens; the files
60 // are always written.60 // are always written.
61 var hash = std.crypto.Blake2b384.init();61 var hash = std.crypto.hash.blake2.Blake2b384.init();
6262
63 // Random bytes to make WriteFileStep unique. Refresh this with63 // Random bytes to make WriteFileStep unique. Refresh this with
64 // new random bytes when WriteFileStep implementation is modified64 // new random bytes when WriteFileStep implementation is modified
lib/std/cache_hash.zig+6-6
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std.zig");6const std = @import("std.zig");
7const Blake3 = std.crypto.Blake3;7const Blake3 = std.crypto.hash.Blake3;
8const fs = std.fs;8const fs = std.fs;
9const base64 = std.base64;9const base64 = std.base64;
10const ArrayList = std.ArrayList;10const ArrayList = std.ArrayList;
...@@ -56,7 +56,7 @@ pub const CacheHash = struct {...@@ -56,7 +56,7 @@ pub const CacheHash = struct {
56 pub fn init(allocator: *Allocator, dir: fs.Dir, manifest_dir_path: []const u8) !CacheHash {56 pub fn init(allocator: *Allocator, dir: fs.Dir, manifest_dir_path: []const u8) !CacheHash {
57 return CacheHash{57 return CacheHash{
58 .allocator = allocator,58 .allocator = allocator,
59 .blake3 = Blake3.init(),59 .blake3 = Blake3.init(.{}),
60 .manifest_dir = try dir.makeOpenPath(manifest_dir_path, .{}),60 .manifest_dir = try dir.makeOpenPath(manifest_dir_path, .{}),
61 .manifest_file = null,61 .manifest_file = null,
62 .manifest_dirty = false,62 .manifest_dirty = false,
...@@ -137,7 +137,7 @@ pub const CacheHash = struct {...@@ -137,7 +137,7 @@ pub const CacheHash = struct {
137137
138 base64_encoder.encode(self.b64_digest[0..], &bin_digest);138 base64_encoder.encode(self.b64_digest[0..], &bin_digest);
139139
140 self.blake3 = Blake3.init();140 self.blake3 = Blake3.init(.{});
141 self.blake3.update(&bin_digest);141 self.blake3.update(&bin_digest);
142142
143 const manifest_file_path = try fmt.allocPrint(self.allocator, "{}.txt", .{self.b64_digest});143 const manifest_file_path = try fmt.allocPrint(self.allocator, "{}.txt", .{self.b64_digest});
...@@ -256,7 +256,7 @@ pub const CacheHash = struct {...@@ -256,7 +256,7 @@ pub const CacheHash = struct {
256 // cache miss256 // cache miss
257 // keep the manifest file open257 // keep the manifest file open
258 // reset the hash258 // reset the hash
259 self.blake3 = Blake3.init();259 self.blake3 = Blake3.init(.{});
260 self.blake3.update(&bin_digest);260 self.blake3.update(&bin_digest);
261261
262 // Remove files not in the initial hash262 // Remove files not in the initial hash
...@@ -304,7 +304,7 @@ pub const CacheHash = struct {...@@ -304,7 +304,7 @@ pub const CacheHash = struct {
304304
305 // Hash while reading from disk, to keep the contents in the cpu cache while305 // Hash while reading from disk, to keep the contents in the cpu cache while
306 // doing hashing.306 // doing hashing.
307 var blake3 = Blake3.init();307 var blake3 = Blake3.init(.{});
308 var off: usize = 0;308 var off: usize = 0;
309 while (true) {309 while (true) {
310 // give me everything you've got, captain310 // give me everything you've got, captain
...@@ -434,7 +434,7 @@ pub const CacheHash = struct {...@@ -434,7 +434,7 @@ pub const CacheHash = struct {
434};434};
435435
436fn hashFile(file: fs.File, bin_digest: []u8) !void {436fn hashFile(file: fs.File, bin_digest: []u8) !void {
437 var blake3 = Blake3.init();437 var blake3 = Blake3.init(.{});
438 var buf: [1024]u8 = undefined;438 var buf: [1024]u8 = undefined;
439439
440 while (true) {440 while (true) {
lib/std/crypto.zig+68-55
...@@ -3,58 +3,66 @@...@@ -3,58 +3,66 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6pub const Md5 = @import("crypto/md5.zig").Md5;
7pub const Sha1 = @import("crypto/sha1.zig").Sha1;
86
9const sha2 = @import("crypto/sha2.zig");7/// Hash functions.
10pub const Sha224 = sha2.Sha224;8pub const hash = struct {
11pub const Sha256 = sha2.Sha256;9 pub const Md5 = @import("crypto/md5.zig").Md5;
12pub const Sha384 = sha2.Sha384;10 pub const Sha1 = @import("crypto/sha1.zig").Sha1;
13pub const Sha512 = sha2.Sha512;11 pub const sha2 = @import("crypto/sha2.zig");
1412 pub const sha3 = @import("crypto/sha3.zig");
15const sha3 = @import("crypto/sha3.zig");13 pub const blake2 = @import("crypto/blake2.zig");
16pub const Sha3_224 = sha3.Sha3_224;14 pub const Blake3 = @import("crypto/blake3.zig").Blake3;
17pub const Sha3_256 = sha3.Sha3_256;15 pub const Gimli = @import("crypto/gimli.zig").Hash;
18pub const Sha3_384 = sha3.Sha3_384;16};
19pub const Sha3_512 = sha3.Sha3_512;
2017
21pub const gimli = @import("crypto/gimli.zig");18/// Authentication (MAC) functions.
19pub const auth = struct {
20 pub const hmac = @import("crypto/hmac.zig");
21};
2222
23const blake2 = @import("crypto/blake2.zig");23/// Authenticated Encryption with Associated Data
24pub const Blake2s224 = blake2.Blake2s224;24pub const aead = struct {
25pub const Blake2s256 = blake2.Blake2s256;25 const chacha20 = @import("crypto/chacha20.zig");
26pub const Blake2b384 = blake2.Blake2b384;
27pub const Blake2b512 = blake2.Blake2b512;
2826
29pub const Blake3 = @import("crypto/blake3.zig").Blake3;27 pub const Gimli = @import("crypto/gimli.zig").Aead;
28 pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305;
29 pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305;
30};
3031
31const hmac = @import("crypto/hmac.zig");32/// MAC functions requiring single-use secret keys.
32pub const HmacMd5 = hmac.HmacMd5;33pub const onetimeauth = struct {
33pub const HmacSha1 = hmac.HmacSha1;34 pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;
34pub const HmacSha256 = hmac.HmacSha256;35};
35pub const HmacBlake2s256 = hmac.HmacBlake2s256;
3636
37pub const chacha20 = @import("crypto/chacha20.zig");37/// Core functions, that should rarely be used directly by applications.
38pub const chaCha20IETF = chacha20.chaCha20IETF;38pub const core = struct {
39pub const chaCha20With64BitNonce = chacha20.chaCha20With64BitNonce;39 pub const aes = @import("crypto/aes.zig");
40pub const xChaCha20IETF = chacha20.xChaCha20IETF;40 pub const Gimli = @import("crypto/gimli.zig").State;
41};
4142
42pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;43/// Elliptic-curve arithmetic.
44pub const ecc = struct {
45 pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
46 pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;
47 pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
48};
4349
44const import_aes = @import("crypto/aes.zig");50/// Diffie-Hellman key exchange functions.
45pub const AES128 = import_aes.AES128;51pub const dh = struct {
46pub const AES256 = import_aes.AES256;52 pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
53};
4754
48pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;55/// Digital signature functions.
49pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519;56pub const sign = struct {
50pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;57 pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519;
51pub const X25519 = @import("crypto/25519/x25519.zig").X25519;58};
52pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
5359
54pub const aead = struct {60/// Stream ciphers. These do not provide any kind of authentication.
55 pub const Gimli = gimli.Aead;61/// Most applications should be using AEAD constructions instead of stream ciphers directly.
56 pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305;62pub const stream = struct {
57 pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305;63 pub const ChaCha20IETF = @import("crypto/chacha20.zig").ChaCha20IETF;
64 pub const XChaCha20IETF = @import("crypto/chacha20.zig").XChaCha20IETF;
65 pub const ChaCha20With64BitNonce = @import("crypto/chacha20.zig").ChaCha20With64BitNonce;
58};66};
5967
60const std = @import("std.zig");68const std = @import("std.zig");
...@@ -83,27 +91,32 @@ test "crypto" {...@@ -83,27 +91,32 @@ test "crypto" {
8391
84test "issue #4532: no index out of bounds" {92test "issue #4532: no index out of bounds" {
85 const types = [_]type{93 const types = [_]type{
86 Md5,94 hash.Md5,
87 Sha1,95 hash.Sha1,
88 Sha224,96 hash.sha2.Sha224,
89 Sha256,97 hash.sha2.Sha256,
90 Sha384,98 hash.sha2.Sha384,
91 Sha512,99 hash.sha2.Sha512,
92 Blake2s224,100 hash.sha3.Sha3_224,
93 Blake2s256,101 hash.sha3.Sha3_256,
94 Blake2b384,102 hash.sha3.Sha3_384,
95 Blake2b512,103 hash.sha3.Sha3_512,
104 hash.blake2.Blake2s224,
105 hash.blake2.Blake2s256,
106 hash.blake2.Blake2b384,
107 hash.blake2.Blake2b512,
108 hash.Gimli,
96 };109 };
97110
98 inline for (types) |Hasher| {111 inline for (types) |Hasher| {
99 var block = [_]u8{'#'} ** Hasher.block_length;112 var block = [_]u8{'#'} ** Hasher.block_length;
100 var out1: [Hasher.digest_length]u8 = undefined;113 var out1: [Hasher.digest_length]u8 = undefined;
101 var out2: [Hasher.digest_length]u8 = undefined;114 var out2: [Hasher.digest_length]u8 = undefined;
102115 const h0 = Hasher.init(.{});
103 var h = Hasher.init();116 var h = h0;
104 h.update(block[0..]);117 h.update(block[0..]);
105 h.final(out1[0..]);118 h.final(out1[0..]);
106 h.reset();119 h = h0;
107 h.update(block[0..1]);120 h.update(block[0..1]);
108 h.update(block[1..]);121 h.update(block[1..]);
109 h.final(out2[0..]);122 h.final(out2[0..]);
lib/std/crypto/25519/ed25519.zig+6-6
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6const std = @import("std");6const std = @import("std");
7const fmt = std.fmt;7const fmt = std.fmt;
8const mem = std.mem;8const mem = std.mem;
9const Sha512 = std.crypto.Sha512;9const Sha512 = std.crypto.hash.sha2.Sha512;
1010
11/// Ed25519 (EdDSA) signatures.11/// Ed25519 (EdDSA) signatures.
12pub const Ed25519 = struct {12pub const Ed25519 = struct {
...@@ -33,7 +33,7 @@ pub const Ed25519 = struct {...@@ -33,7 +33,7 @@ pub const Ed25519 = struct {
33 /// from which the actual secret is derived.33 /// from which the actual secret is derived.
34 pub fn createKeyPair(seed: [seed_length]u8) ![keypair_length]u8 {34 pub fn createKeyPair(seed: [seed_length]u8) ![keypair_length]u8 {
35 var az: [Sha512.digest_length]u8 = undefined;35 var az: [Sha512.digest_length]u8 = undefined;
36 var h = Sha512.init();36 var h = Sha512.init(.{});
37 h.update(&seed);37 h.update(&seed);
38 h.final(&az);38 h.final(&az);
39 const p = try Curve.basePoint.clampedMul(az[0..32].*);39 const p = try Curve.basePoint.clampedMul(az[0..32].*);
...@@ -56,11 +56,11 @@ pub const Ed25519 = struct {...@@ -56,11 +56,11 @@ pub const Ed25519 = struct {
56 pub fn sign(msg: []const u8, key_pair: [keypair_length]u8, noise: ?[noise_length]u8) ![signature_length]u8 {56 pub fn sign(msg: []const u8, key_pair: [keypair_length]u8, noise: ?[noise_length]u8) ![signature_length]u8 {
57 const public_key = key_pair[32..];57 const public_key = key_pair[32..];
58 var az: [Sha512.digest_length]u8 = undefined;58 var az: [Sha512.digest_length]u8 = undefined;
59 var h = Sha512.init();59 var h = Sha512.init(.{});
60 h.update(key_pair[0..seed_length]);60 h.update(key_pair[0..seed_length]);
61 h.final(&az);61 h.final(&az);
6262
63 h = Sha512.init();63 h = Sha512.init(.{});
64 if (noise) |*z| {64 if (noise) |*z| {
65 h.update(z);65 h.update(z);
66 }66 }
...@@ -74,7 +74,7 @@ pub const Ed25519 = struct {...@@ -74,7 +74,7 @@ pub const Ed25519 = struct {
74 var sig: [signature_length]u8 = undefined;74 var sig: [signature_length]u8 = undefined;
75 mem.copy(u8, sig[0..32], &r.toBytes());75 mem.copy(u8, sig[0..32], &r.toBytes());
76 mem.copy(u8, sig[32..], public_key);76 mem.copy(u8, sig[32..], public_key);
77 h = Sha512.init();77 h = Sha512.init(.{});
78 h.update(&sig);78 h.update(&sig);
79 h.update(msg);79 h.update(msg);
80 var hram64: [Sha512.digest_length]u8 = undefined;80 var hram64: [Sha512.digest_length]u8 = undefined;
...@@ -98,7 +98,7 @@ pub const Ed25519 = struct {...@@ -98,7 +98,7 @@ pub const Ed25519 = struct {
98 const a = try Curve.fromBytes(public_key);98 const a = try Curve.fromBytes(public_key);
99 try a.rejectIdentity();99 try a.rejectIdentity();
100100
101 var h = Sha512.init();101 var h = Sha512.init(.{});
102 h.update(r);102 h.update(r);
103 h.update(&public_key);103 h.update(&public_key);
104 h.update(msg);104 h.update(msg);
lib/std/crypto/benchmark.zig+20-19
...@@ -22,20 +22,20 @@ const Crypto = struct {...@@ -22,20 +22,20 @@ const Crypto = struct {
22};22};
2323
24const hashes = [_]Crypto{24const hashes = [_]Crypto{
25 Crypto{ .ty = crypto.Md5, .name = "md5" },25 Crypto{ .ty = crypto.hash.Md5, .name = "md5" },
26 Crypto{ .ty = crypto.Sha1, .name = "sha1" },26 Crypto{ .ty = crypto.hash.Sha1, .name = "sha1" },
27 Crypto{ .ty = crypto.Sha256, .name = "sha256" },27 Crypto{ .ty = crypto.hash.sha2.Sha256, .name = "sha256" },
28 Crypto{ .ty = crypto.Sha512, .name = "sha512" },28 Crypto{ .ty = crypto.hash.sha2.Sha512, .name = "sha512" },
29 Crypto{ .ty = crypto.Sha3_256, .name = "sha3-256" },29 Crypto{ .ty = crypto.hash.sha3.Sha3_256, .name = "sha3-256" },
30 Crypto{ .ty = crypto.Sha3_512, .name = "sha3-512" },30 Crypto{ .ty = crypto.hash.sha3.Sha3_512, .name = "sha3-512" },
31 Crypto{ .ty = crypto.gimli.Hash, .name = "gimli-hash" },31 Crypto{ .ty = crypto.hash.Gimli, .name = "gimli-hash" },
32 Crypto{ .ty = crypto.Blake2s256, .name = "blake2s" },32 Crypto{ .ty = crypto.hash.blake2.Blake2s256, .name = "blake2s" },
33 Crypto{ .ty = crypto.Blake2b512, .name = "blake2b" },33 Crypto{ .ty = crypto.hash.blake2.Blake2b512, .name = "blake2b" },
34 Crypto{ .ty = crypto.Blake3, .name = "blake3" },34 Crypto{ .ty = crypto.hash.Blake3, .name = "blake3" },
35};35};
3636
37pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 {37pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 {
38 var h = Hash.init();38 var h = Hash.init(.{});
3939
40 var block: [Hash.digest_length]u8 = undefined;40 var block: [Hash.digest_length]u8 = undefined;
41 prng.random.bytes(block[0..]);41 prng.random.bytes(block[0..]);
...@@ -55,19 +55,20 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64...@@ -55,19 +55,20 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64
55}55}
5656
57const macs = [_]Crypto{57const macs = [_]Crypto{
58 Crypto{ .ty = crypto.Poly1305, .name = "poly1305" },58 Crypto{ .ty = crypto.onetimeauth.Poly1305, .name = "poly1305" },
59 Crypto{ .ty = crypto.HmacMd5, .name = "hmac-md5" },59 Crypto{ .ty = crypto.auth.hmac.HmacMd5, .name = "hmac-md5" },
60 Crypto{ .ty = crypto.HmacSha1, .name = "hmac-sha1" },60 Crypto{ .ty = crypto.auth.hmac.HmacSha1, .name = "hmac-sha1" },
61 Crypto{ .ty = crypto.HmacSha256, .name = "hmac-sha256" },61 Crypto{ .ty = crypto.auth.hmac.sha2.HmacSha256, .name = "hmac-sha256" },
62 Crypto{ .ty = crypto.auth.hmac.sha2.HmacSha512, .name = "hmac-sha512" },
62};63};
6364
64pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {65pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {
65 std.debug.assert(32 >= Mac.mac_length and 32 >= Mac.minimum_key_length);66 std.debug.assert(64 >= Mac.mac_length and 32 >= Mac.minimum_key_length);
6667
67 var in: [1 * MiB]u8 = undefined;68 var in: [1 * MiB]u8 = undefined;
68 prng.random.bytes(in[0..]);69 prng.random.bytes(in[0..]);
6970
70 var key: [32]u8 = undefined;71 var key: [64]u8 = undefined;
71 prng.random.bytes(key[0..]);72 prng.random.bytes(key[0..]);
7273
73 var offset: usize = 0;74 var offset: usize = 0;
...@@ -84,7 +85,7 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {...@@ -84,7 +85,7 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {
84 return throughput;85 return throughput;
85}86}
8687
87const exchanges = [_]Crypto{Crypto{ .ty = crypto.X25519, .name = "x25519" }};88const exchanges = [_]Crypto{Crypto{ .ty = crypto.dh.X25519, .name = "x25519" }};
8889
89pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_count: comptime_int) !u64 {90pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_count: comptime_int) !u64 {
90 std.debug.assert(DhKeyExchange.minimum_key_length >= DhKeyExchange.secret_length);91 std.debug.assert(DhKeyExchange.minimum_key_length >= DhKeyExchange.secret_length);
...@@ -111,7 +112,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c...@@ -111,7 +112,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c
111 return throughput;112 return throughput;
112}113}
113114
114const signatures = [_]Crypto{Crypto{ .ty = crypto.Ed25519, .name = "ed25519" }};115const signatures = [_]Crypto{Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" }};
115116
116pub fn benchmarkSignatures(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {117pub fn benchmarkSignatures(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {
117 var seed: [Signature.seed_length]u8 = undefined;118 var seed: [Signature.seed_length]u8 = undefined;
lib/std/crypto/blake2.zig+102-78
...@@ -40,6 +40,7 @@ pub fn Blake2s(comptime out_len: usize) type {...@@ -40,6 +40,7 @@ pub fn Blake2s(comptime out_len: usize) type {
40 const Self = @This();40 const Self = @This();
41 pub const block_length = 64;41 pub const block_length = 64;
42 pub const digest_length = out_len / 8;42 pub const digest_length = out_len / 8;
43 pub const Options = struct { key: ?[]const u8 = null, salt: ?[8]u8 = null, context: ?[8]u8 = null };
4344
44 const iv = [8]u32{45 const iv = [8]u32{
45 0x6A09E667,46 0x6A09E667,
...@@ -71,42 +72,36 @@ pub fn Blake2s(comptime out_len: usize) type {...@@ -71,42 +72,36 @@ pub fn Blake2s(comptime out_len: usize) type {
71 buf: [64]u8,72 buf: [64]u8,
72 buf_len: u8,73 buf_len: u8,
7374
74 key: []const u8,75 pub fn init(options: Options) Self {
75
76 pub fn init() Self {
77 return init_keyed("");
78 }
79
80 pub fn init_keyed(key: []const u8) Self {
81 debug.assert(8 <= out_len and out_len <= 512);76 debug.assert(8 <= out_len and out_len <= 512);
8277
83 var s: Self = undefined;78 var d: Self = undefined;
84 s.key = key;
85 s.reset();
86 return s;
87 }
88
89 pub fn reset(d: *Self) void {
90 mem.copy(u32, d.h[0..], iv[0..]);79 mem.copy(u32, d.h[0..], iv[0..]);
9180
81 const key_len = if (options.key) |key| key.len else 0;
92 // default parameters82 // default parameters
93 d.h[0] ^= 0x01010000 ^ @truncate(u32, d.key.len << 8) ^ @intCast(u32, out_len >> 3);83 d.h[0] ^= 0x01010000 ^ @truncate(u32, key_len << 8) ^ @intCast(u32, out_len >> 3);
94 d.t = 0;84 d.t = 0;
95 d.buf_len = 0;85 d.buf_len = 0;
9686
97 if (d.key.len > 0) {87 if (options.salt) |salt| {
98 mem.set(u8, d.buf[d.key.len..], 0);88 d.h[4] ^= mem.readIntLittle(u32, salt[0..4]);
99 d.update(d.key);89 d.h[5] ^= mem.readIntLittle(u32, salt[4..8]);
90 }
91 if (options.context) |context| {
92 d.h[6] ^= mem.readIntLittle(u32, context[0..4]);
93 d.h[7] ^= mem.readIntLittle(u32, context[4..8]);
94 }
95 if (key_len > 0) {
96 mem.set(u8, d.buf[key_len..], 0);
97 d.update(options.key.?);
100 d.buf_len = 64;98 d.buf_len = 64;
101 }99 }
100 return d;
102 }101 }
103102
104 pub fn hash(b: []const u8, out: []u8) void {103 pub fn hash(b: []const u8, out: []u8, options: Options) void {
105 Self.hash_keyed("", b, out);104 var d = Self.init(options);
106 }
107
108 pub fn hash_keyed(key: []const u8, b: []const u8, out: []u8) void {
109 var d = Self.init_keyed(key);
110 d.update(b);105 d.update(b);
111 d.final(out);106 d.final(out);
112 }107 }
...@@ -215,7 +210,7 @@ test "blake2s224 single" {...@@ -215,7 +210,7 @@ test "blake2s224 single" {
215}210}
216211
217test "blake2s224 streaming" {212test "blake2s224 streaming" {
218 var h = Blake2s224.init();213 var h = Blake2s224.init(.{});
219 var out: [28]u8 = undefined;214 var out: [28]u8 = undefined;
220215
221 const h1 = "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4";216 const h1 = "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4";
...@@ -225,12 +220,12 @@ test "blake2s224 streaming" {...@@ -225,12 +220,12 @@ test "blake2s224 streaming" {
225220
226 const h2 = "0b033fc226df7abde29f67a05d3dc62cf271ef3dfea4d387407fbd55";221 const h2 = "0b033fc226df7abde29f67a05d3dc62cf271ef3dfea4d387407fbd55";
227222
228 h.reset();223 h = Blake2s224.init(.{});
229 h.update("abc");224 h.update("abc");
230 h.final(out[0..]);225 h.final(out[0..]);
231 htest.assertEqual(h2, out[0..]);226 htest.assertEqual(h2, out[0..]);
232227
233 h.reset();228 h = Blake2s224.init(.{});
234 h.update("a");229 h.update("a");
235 h.update("b");230 h.update("b");
236 h.update("c");231 h.update("c");
...@@ -239,16 +234,29 @@ test "blake2s224 streaming" {...@@ -239,16 +234,29 @@ test "blake2s224 streaming" {
239234
240 const h3 = "557381a78facd2b298640f4e32113e58967d61420af1aa939d0cfe01";235 const h3 = "557381a78facd2b298640f4e32113e58967d61420af1aa939d0cfe01";
241236
242 h.reset();237 h = Blake2s224.init(.{});
243 h.update("a" ** 32);238 h.update("a" ** 32);
244 h.update("b" ** 32);239 h.update("b" ** 32);
245 h.final(out[0..]);240 h.final(out[0..]);
246 htest.assertEqual(h3, out[0..]);241 htest.assertEqual(h3, out[0..]);
247242
248 h.reset();243 h = Blake2s224.init(.{});
249 h.update("a" ** 32 ++ "b" ** 32);244 h.update("a" ** 32 ++ "b" ** 32);
250 h.final(out[0..]);245 h.final(out[0..]);
251 htest.assertEqual(h3, out[0..]);246 htest.assertEqual(h3, out[0..]);
247
248 const h4 = "a4d6a9d253441b80e5dfd60a04db169ffab77aec56a2855c402828c3";
249
250 h = Blake2s224.init(.{ .context = [_]u8{0x69} ** 8, .salt = [_]u8{0x42} ** 8 });
251 h.update("a" ** 32);
252 h.update("b" ** 32);
253 h.final(out[0..]);
254 htest.assertEqual(h4, out[0..]);
255
256 h = Blake2s224.init(.{ .context = [_]u8{0x69} ** 8, .salt = [_]u8{0x42} ** 8 });
257 h.update("a" ** 32 ++ "b" ** 32);
258 h.final(out[0..]);
259 htest.assertEqual(h4, out[0..]);
252}260}
253261
254test "comptime blake2s224" {262test "comptime blake2s224" {
...@@ -261,7 +269,7 @@ test "comptime blake2s224" {...@@ -261,7 +269,7 @@ test "comptime blake2s224" {
261269
262 htest.assertEqualHash(Blake2s224, h1, block[0..]);270 htest.assertEqualHash(Blake2s224, h1, block[0..]);
263271
264 var h = Blake2s224.init();272 var h = Blake2s224.init(.{});
265 h.update(&block);273 h.update(&block);
266 h.final(out[0..]);274 h.final(out[0..]);
267275
...@@ -284,7 +292,7 @@ test "blake2s256 single" {...@@ -284,7 +292,7 @@ test "blake2s256 single" {
284}292}
285293
286test "blake2s256 streaming" {294test "blake2s256 streaming" {
287 var h = Blake2s256.init();295 var h = Blake2s256.init(.{});
288 var out: [32]u8 = undefined;296 var out: [32]u8 = undefined;
289297
290 const h1 = "69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9";298 const h1 = "69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9";
...@@ -294,12 +302,12 @@ test "blake2s256 streaming" {...@@ -294,12 +302,12 @@ test "blake2s256 streaming" {
294302
295 const h2 = "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982";303 const h2 = "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982";
296304
297 h.reset();305 h = Blake2s256.init(.{});
298 h.update("abc");306 h.update("abc");
299 h.final(out[0..]);307 h.final(out[0..]);
300 htest.assertEqual(h2, out[0..]);308 htest.assertEqual(h2, out[0..]);
301309
302 h.reset();310 h = Blake2s256.init(.{});
303 h.update("a");311 h.update("a");
304 h.update("b");312 h.update("b");
305 h.update("c");313 h.update("c");
...@@ -308,13 +316,13 @@ test "blake2s256 streaming" {...@@ -308,13 +316,13 @@ test "blake2s256 streaming" {
308316
309 const h3 = "8d8711dade07a6b92b9a3ea1f40bee9b2c53ff3edd2a273dec170b0163568977";317 const h3 = "8d8711dade07a6b92b9a3ea1f40bee9b2c53ff3edd2a273dec170b0163568977";
310318
311 h.reset();319 h = Blake2s256.init(.{});
312 h.update("a" ** 32);320 h.update("a" ** 32);
313 h.update("b" ** 32);321 h.update("b" ** 32);
314 h.final(out[0..]);322 h.final(out[0..]);
315 htest.assertEqual(h3, out[0..]);323 htest.assertEqual(h3, out[0..]);
316324
317 h.reset();325 h = Blake2s256.init(.{});
318 h.update("a" ** 32 ++ "b" ** 32);326 h.update("a" ** 32 ++ "b" ** 32);
319 h.final(out[0..]);327 h.final(out[0..]);
320 htest.assertEqual(h3, out[0..]);328 htest.assertEqual(h3, out[0..]);
...@@ -326,16 +334,16 @@ test "blake2s256 keyed" {...@@ -326,16 +334,16 @@ test "blake2s256 keyed" {
326 const h1 = "10f918da4d74fab3302e48a5d67d03804b1ec95372a62a0f33b7c9fa28ba1ae6";334 const h1 = "10f918da4d74fab3302e48a5d67d03804b1ec95372a62a0f33b7c9fa28ba1ae6";
327 const key = "secret_key";335 const key = "secret_key";
328336
329 Blake2s256.hash_keyed(key, "a" ** 64 ++ "b" ** 64, &out);337 Blake2s256.hash("a" ** 64 ++ "b" ** 64, &out, .{ .key = key });
330 htest.assertEqual(h1, out[0..]);338 htest.assertEqual(h1, out[0..]);
331339
332 var h = Blake2s256.init_keyed(key);340 var h = Blake2s256.init(.{ .key = key });
333 h.update("a" ** 64 ++ "b" ** 64);341 h.update("a" ** 64 ++ "b" ** 64);
334 h.final(out[0..]);342 h.final(out[0..]);
335343
336 htest.assertEqual(h1, out[0..]);344 htest.assertEqual(h1, out[0..]);
337345
338 h.reset();346 h = Blake2s256.init(.{ .key = key });
339 h.update("a" ** 64);347 h.update("a" ** 64);
340 h.update("b" ** 64);348 h.update("b" ** 64);
341 h.final(out[0..]);349 h.final(out[0..]);
...@@ -353,7 +361,7 @@ test "comptime blake2s256" {...@@ -353,7 +361,7 @@ test "comptime blake2s256" {
353361
354 htest.assertEqualHash(Blake2s256, h1, block[0..]);362 htest.assertEqualHash(Blake2s256, h1, block[0..]);
355363
356 var h = Blake2s256.init();364 var h = Blake2s256.init(.{});
357 h.update(&block);365 h.update(&block);
358 h.final(out[0..]);366 h.final(out[0..]);
359367
...@@ -364,6 +372,7 @@ test "comptime blake2s256" {...@@ -364,6 +372,7 @@ test "comptime blake2s256" {
364/////////////////////372/////////////////////
365// Blake2b373// Blake2b
366374
375pub const Blake2b256 = Blake2b(256);
367pub const Blake2b384 = Blake2b(384);376pub const Blake2b384 = Blake2b(384);
368pub const Blake2b512 = Blake2b(512);377pub const Blake2b512 = Blake2b(512);
369378
...@@ -372,6 +381,7 @@ pub fn Blake2b(comptime out_len: usize) type {...@@ -372,6 +381,7 @@ pub fn Blake2b(comptime out_len: usize) type {
372 const Self = @This();381 const Self = @This();
373 pub const block_length = 128;382 pub const block_length = 128;
374 pub const digest_length = out_len / 8;383 pub const digest_length = out_len / 8;
384 pub const Options = struct { key: ?[]const u8 = null, salt: ?[16]u8 = null, context: ?[16]u8 = null };
375385
376 const iv = [8]u64{386 const iv = [8]u64{
377 0x6a09e667f3bcc908,387 0x6a09e667f3bcc908,
...@@ -405,42 +415,36 @@ pub fn Blake2b(comptime out_len: usize) type {...@@ -405,42 +415,36 @@ pub fn Blake2b(comptime out_len: usize) type {
405 buf: [128]u8,415 buf: [128]u8,
406 buf_len: u8,416 buf_len: u8,
407417
408 key: []const u8,418 pub fn init(options: Options) Self {
409
410 pub fn init() Self {
411 return init_keyed("");
412 }
413
414 pub fn init_keyed(key: []const u8) Self {
415 debug.assert(8 <= out_len and out_len <= 512);419 debug.assert(8 <= out_len and out_len <= 512);
416420
417 var s: Self = undefined;421 var d: Self = undefined;
418 s.key = key;
419 s.reset();
420 return s;
421 }
422
423 pub fn reset(d: *Self) void {
424 mem.copy(u64, d.h[0..], iv[0..]);422 mem.copy(u64, d.h[0..], iv[0..]);
425423
424 const key_len = if (options.key) |key| key.len else 0;
426 // default parameters425 // default parameters
427 d.h[0] ^= 0x01010000 ^ (d.key.len << 8) ^ (out_len >> 3);426 d.h[0] ^= 0x01010000 ^ (key_len << 8) ^ (out_len >> 3);
428 d.t = 0;427 d.t = 0;
429 d.buf_len = 0;428 d.buf_len = 0;
430429
431 if (d.key.len > 0) {430 if (options.salt) |salt| {
432 mem.set(u8, d.buf[d.key.len..], 0);431 d.h[4] ^= mem.readIntLittle(u64, salt[0..8]);
433 d.update(d.key);432 d.h[5] ^= mem.readIntLittle(u64, salt[8..16]);
433 }
434 if (options.context) |context| {
435 d.h[6] ^= mem.readIntLittle(u64, context[0..8]);
436 d.h[7] ^= mem.readIntLittle(u64, context[8..16]);
437 }
438 if (key_len > 0) {
439 mem.set(u8, d.buf[key_len..], 0);
440 d.update(options.key.?);
434 d.buf_len = 128;441 d.buf_len = 128;
435 }442 }
443 return d;
436 }444 }
437445
438 pub fn hash(b: []const u8, out: []u8) void {446 pub fn hash(b: []const u8, out: []u8, options: Options) void {
439 Self.hash_keyed("", b, out);447 var d = Self.init(options);
440 }
441
442 pub fn hash_keyed(key: []const u8, b: []const u8, out: []u8) void {
443 var d = Self.init_keyed(key);
444 d.update(b);448 d.update(b);
445 d.final(out);449 d.final(out);
446 }450 }
...@@ -547,7 +551,7 @@ test "blake2b384 single" {...@@ -547,7 +551,7 @@ test "blake2b384 single" {
547}551}
548552
549test "blake2b384 streaming" {553test "blake2b384 streaming" {
550 var h = Blake2b384.init();554 var h = Blake2b384.init(.{});
551 var out: [48]u8 = undefined;555 var out: [48]u8 = undefined;
552556
553 const h1 = "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100";557 const h1 = "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100";
...@@ -557,12 +561,12 @@ test "blake2b384 streaming" {...@@ -557,12 +561,12 @@ test "blake2b384 streaming" {
557561
558 const h2 = "6f56a82c8e7ef526dfe182eb5212f7db9df1317e57815dbda46083fc30f54ee6c66ba83be64b302d7cba6ce15bb556f4";562 const h2 = "6f56a82c8e7ef526dfe182eb5212f7db9df1317e57815dbda46083fc30f54ee6c66ba83be64b302d7cba6ce15bb556f4";
559563
560 h.reset();564 h = Blake2b384.init(.{});
561 h.update("abc");565 h.update("abc");
562 h.final(out[0..]);566 h.final(out[0..]);
563 htest.assertEqual(h2, out[0..]);567 htest.assertEqual(h2, out[0..]);
564568
565 h.reset();569 h = Blake2b384.init(.{});
566 h.update("a");570 h.update("a");
567 h.update("b");571 h.update("b");
568 h.update("c");572 h.update("c");
...@@ -571,16 +575,36 @@ test "blake2b384 streaming" {...@@ -571,16 +575,36 @@ test "blake2b384 streaming" {
571575
572 const h3 = "b7283f0172fecbbd7eca32ce10d8a6c06b453cb3cf675b33eb4246f0da2bb94a6c0bdd6eec0b5fd71ec4fd51be80bf4c";576 const h3 = "b7283f0172fecbbd7eca32ce10d8a6c06b453cb3cf675b33eb4246f0da2bb94a6c0bdd6eec0b5fd71ec4fd51be80bf4c";
573577
574 h.reset();578 h = Blake2b384.init(.{});
575 h.update("a" ** 64 ++ "b" ** 64);579 h.update("a" ** 64 ++ "b" ** 64);
576 h.final(out[0..]);580 h.final(out[0..]);
577 htest.assertEqual(h3, out[0..]);581 htest.assertEqual(h3, out[0..]);
578582
579 h.reset();583 h = Blake2b384.init(.{});
584 h.update("a" ** 64);
585 h.update("b" ** 64);
586 h.final(out[0..]);
587 htest.assertEqual(h3, out[0..]);
588
589 h = Blake2b384.init(.{});
580 h.update("a" ** 64);590 h.update("a" ** 64);
581 h.update("b" ** 64);591 h.update("b" ** 64);
582 h.final(out[0..]);592 h.final(out[0..]);
583 htest.assertEqual(h3, out[0..]);593 htest.assertEqual(h3, out[0..]);
594
595 const h4 = "934c48fcb197031c71f583d92f98703510805e72142e0b46f5752d1e971bc86c355d556035613ff7a4154b4de09dac5c";
596
597 h = Blake2b384.init(.{ .context = [_]u8{0x69} ** 16, .salt = [_]u8{0x42} ** 16 });
598 h.update("a" ** 64);
599 h.update("b" ** 64);
600 h.final(out[0..]);
601 htest.assertEqual(h4, out[0..]);
602
603 h = Blake2b384.init(.{ .context = [_]u8{0x69} ** 16, .salt = [_]u8{0x42} ** 16 });
604 h.update("a" ** 64);
605 h.update("b" ** 64);
606 h.final(out[0..]);
607 htest.assertEqual(h4, out[0..]);
584}608}
585609
586test "comptime blake2b384" {610test "comptime blake2b384" {
...@@ -593,7 +617,7 @@ test "comptime blake2b384" {...@@ -593,7 +617,7 @@ test "comptime blake2b384" {
593617
594 htest.assertEqualHash(Blake2b384, h1, block[0..]);618 htest.assertEqualHash(Blake2b384, h1, block[0..]);
595619
596 var h = Blake2b384.init();620 var h = Blake2b384.init(.{});
597 h.update(&block);621 h.update(&block);
598 h.final(out[0..]);622 h.final(out[0..]);
599623
...@@ -616,7 +640,7 @@ test "blake2b512 single" {...@@ -616,7 +640,7 @@ test "blake2b512 single" {
616}640}
617641
618test "blake2b512 streaming" {642test "blake2b512 streaming" {
619 var h = Blake2b512.init();643 var h = Blake2b512.init(.{});
620 var out: [64]u8 = undefined;644 var out: [64]u8 = undefined;
621645
622 const h1 = "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce";646 const h1 = "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce";
...@@ -626,12 +650,12 @@ test "blake2b512 streaming" {...@@ -626,12 +650,12 @@ test "blake2b512 streaming" {
626650
627 const h2 = "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923";651 const h2 = "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923";
628652
629 h.reset();653 h = Blake2b512.init(.{});
630 h.update("abc");654 h.update("abc");
631 h.final(out[0..]);655 h.final(out[0..]);
632 htest.assertEqual(h2, out[0..]);656 htest.assertEqual(h2, out[0..]);
633657
634 h.reset();658 h = Blake2b512.init(.{});
635 h.update("a");659 h.update("a");
636 h.update("b");660 h.update("b");
637 h.update("c");661 h.update("c");
...@@ -640,12 +664,12 @@ test "blake2b512 streaming" {...@@ -640,12 +664,12 @@ test "blake2b512 streaming" {
640664
641 const h3 = "049980af04d6a2cf16b4b49793c3ed7e40732073788806f2c989ebe9547bda0541d63abe298ec8955d08af48ae731f2e8a0bd6d201655a5473b4aa79d211b920";665 const h3 = "049980af04d6a2cf16b4b49793c3ed7e40732073788806f2c989ebe9547bda0541d63abe298ec8955d08af48ae731f2e8a0bd6d201655a5473b4aa79d211b920";
642666
643 h.reset();667 h = Blake2b512.init(.{});
644 h.update("a" ** 64 ++ "b" ** 64);668 h.update("a" ** 64 ++ "b" ** 64);
645 h.final(out[0..]);669 h.final(out[0..]);
646 htest.assertEqual(h3, out[0..]);670 htest.assertEqual(h3, out[0..]);
647671
648 h.reset();672 h = Blake2b512.init(.{});
649 h.update("a" ** 64);673 h.update("a" ** 64);
650 h.update("b" ** 64);674 h.update("b" ** 64);
651 h.final(out[0..]);675 h.final(out[0..]);
...@@ -658,16 +682,16 @@ test "blake2b512 keyed" {...@@ -658,16 +682,16 @@ test "blake2b512 keyed" {
658 const h1 = "8a978060ccaf582f388f37454363071ac9a67e3a704585fd879fb8a419a447e389c7c6de790faa20a7a7dccf197de736bc5b40b98a930b36df5bee7555750c4d";682 const h1 = "8a978060ccaf582f388f37454363071ac9a67e3a704585fd879fb8a419a447e389c7c6de790faa20a7a7dccf197de736bc5b40b98a930b36df5bee7555750c4d";
659 const key = "secret_key";683 const key = "secret_key";
660684
661 Blake2b512.hash_keyed(key, "a" ** 64 ++ "b" ** 64, &out);685 Blake2b512.hash("a" ** 64 ++ "b" ** 64, &out, .{ .key = key });
662 htest.assertEqual(h1, out[0..]);686 htest.assertEqual(h1, out[0..]);
663687
664 var h = Blake2b512.init_keyed(key);688 var h = Blake2b512.init(.{ .key = key });
665 h.update("a" ** 64 ++ "b" ** 64);689 h.update("a" ** 64 ++ "b" ** 64);
666 h.final(out[0..]);690 h.final(out[0..]);
667691
668 htest.assertEqual(h1, out[0..]);692 htest.assertEqual(h1, out[0..]);
669693
670 h.reset();694 h = Blake2b512.init(.{ .key = key });
671 h.update("a" ** 64);695 h.update("a" ** 64);
672 h.update("b" ** 64);696 h.update("b" ** 64);
673 h.final(out[0..]);697 h.final(out[0..]);
...@@ -685,7 +709,7 @@ test "comptime blake2b512" {...@@ -685,7 +709,7 @@ test "comptime blake2b512" {
685709
686 htest.assertEqualHash(Blake2b512, h1, block[0..]);710 htest.assertEqualHash(Blake2b512, h1, block[0..]);
687711
688 var h = Blake2b512.init();712 var h = Blake2b512.init(.{});
689 h.update(&block);713 h.update(&block);
690 h.final(out[0..]);714 h.final(out[0..]);
691715
lib/std/crypto/blake3.zig+24-23
...@@ -279,6 +279,9 @@ fn parent_cv(...@@ -279,6 +279,9 @@ fn parent_cv(
279279
280/// An incremental hasher that can accept any number of writes.280/// An incremental hasher that can accept any number of writes.
281pub const Blake3 = struct {281pub const Blake3 = struct {
282 pub const Options = struct { key: ?[KEY_LEN]u8 = null };
283 pub const KdfOptions = struct {};
284
282 chunk_state: ChunkState,285 chunk_state: ChunkState,
283 key: [8]u32,286 key: [8]u32,
284 cv_stack: [54][8]u32 = undefined, // Space for 54 subtree chaining values:287 cv_stack: [54][8]u32 = undefined, // Space for 54 subtree chaining values:
...@@ -296,21 +299,20 @@ pub const Blake3 = struct {...@@ -296,21 +299,20 @@ pub const Blake3 = struct {
296 };299 };
297 }300 }
298301
299 /// Construct a new `Blake3` for the regular hash function.302 /// Construct a new `Blake3` for the hash function, with an optional key
300 pub fn init() Blake3 {303 pub fn init(options: Options) Blake3 {
301 return Blake3.init_internal(IV, 0);304 if (options.key) |key| {
302 }305 var key_words: [8]u32 = undefined;
303306 words_from_little_endian_bytes(key_words[0..], key[0..]);
304 /// Construct a new `Blake3` for the keyed hash function.307 return Blake3.init_internal(key_words, KEYED_HASH);
305 pub fn init_keyed(key: [KEY_LEN]u8) Blake3 {308 } else {
306 var key_words: [8]u32 = undefined;309 return Blake3.init_internal(IV, 0);
307 words_from_little_endian_bytes(key_words[0..], key[0..]);310 }
308 return Blake3.init_internal(key_words, KEYED_HASH);
309 }311 }
310312
311 /// Construct a new `Blake3` for the key derivation function. The context313 /// Construct a new `Blake3` for the key derivation function. The context
312 /// string should be hardcoded, globally unique, and application-specific.314 /// string should be hardcoded, globally unique, and application-specific.
313 pub fn init_derive_key(context: []const u8) Blake3 {315 pub fn initKdf(context: []const u8, options: KdfOptions) Blake3 {
314 var context_hasher = Blake3.init_internal(IV, DERIVE_KEY_CONTEXT);316 var context_hasher = Blake3.init_internal(IV, DERIVE_KEY_CONTEXT);
315 context_hasher.update(context);317 context_hasher.update(context);
316 var context_key: [KEY_LEN]u8 = undefined;318 var context_key: [KEY_LEN]u8 = undefined;
...@@ -320,18 +322,12 @@ pub const Blake3 = struct {...@@ -320,18 +322,12 @@ pub const Blake3 = struct {
320 return Blake3.init_internal(context_key_words, DERIVE_KEY_MATERIAL);322 return Blake3.init_internal(context_key_words, DERIVE_KEY_MATERIAL);
321 }323 }
322324
323 pub fn hash(in: []const u8, out: []u8) void {325 pub fn hash(in: []const u8, out: []u8, options: Options) void {
324 var hasher = Blake3.init();326 var hasher = Blake3.init(options);
325 hasher.update(in);327 hasher.update(in);
326 hasher.final(out);328 hasher.final(out);
327 }329 }
328330
329 /// Reset the `Blake3` to its initial state.
330 pub fn reset(self: *Blake3) void {
331 self.chunk_state = ChunkState.init(self.key, 0, self.flags);
332 self.cv_stack_len = 0;
333 }
334
335 fn push_cv(self: *Blake3, cv: [8]u32) void {331 fn push_cv(self: *Blake3, cv: [8]u32) void {
336 self.cv_stack[self.cv_stack_len] = cv;332 self.cv_stack[self.cv_stack_len] = cv;
337 self.cv_stack_len += 1;333 self.cv_stack_len += 1;
...@@ -566,6 +562,9 @@ const reference_test = ReferenceTest{...@@ -566,6 +562,9 @@ const reference_test = ReferenceTest{
566};562};
567563
568fn test_blake3(hasher: *Blake3, input_len: usize, expected_hex: [262]u8) void {564fn test_blake3(hasher: *Blake3, input_len: usize, expected_hex: [262]u8) void {
565 // Save initial state
566 const initial_state = hasher.*;
567
569 // Setup input pattern568 // Setup input pattern
570 var input_pattern: [251]u8 = undefined;569 var input_pattern: [251]u8 = undefined;
571 for (input_pattern) |*e, i| e.* = @truncate(u8, i);570 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 {...@@ -581,18 +580,20 @@ fn test_blake3(hasher: *Blake3, input_len: usize, expected_hex: [262]u8) void {
581 // Read final hash value580 // Read final hash value
582 var actual_bytes: [expected_hex.len / 2]u8 = undefined;581 var actual_bytes: [expected_hex.len / 2]u8 = undefined;
583 hasher.final(actual_bytes[0..]);582 hasher.final(actual_bytes[0..]);
584 hasher.reset();
585583
586 // Compare to expected value584 // Compare to expected value
587 var expected_bytes: [expected_hex.len / 2]u8 = undefined;585 var expected_bytes: [expected_hex.len / 2]u8 = undefined;
588 fmt.hexToBytes(expected_bytes[0..], expected_hex[0..]) catch unreachable;586 fmt.hexToBytes(expected_bytes[0..], expected_hex[0..]) catch unreachable;
589 testing.expectEqual(actual_bytes, expected_bytes);587 testing.expectEqual(actual_bytes, expected_bytes);
588
589 // Restore initial state
590 hasher.* = initial_state;
590}591}
591592
592test "BLAKE3 reference test cases" {593test "BLAKE3 reference test cases" {
593 var hash = &Blake3.init();594 var hash = &Blake3.init(.{});
594 var keyed_hash = &Blake3.init_keyed(reference_test.key.*);595 var keyed_hash = &Blake3.init(.{ .key = reference_test.key.* });
595 var derive_key = &Blake3.init_derive_key(reference_test.context_string);596 var derive_key = &Blake3.initKdf(reference_test.context_string, .{});
596597
597 for (reference_test.cases) |t| {598 for (reference_test.cases) |t| {
598 test_blake3(hash, t.input_len, t.hash.*);599 test_blake3(hash, t.input_len, t.hash.*);
lib/std/crypto/chacha20.zig+74-68
...@@ -12,7 +12,7 @@ const assert = std.debug.assert;...@@ -12,7 +12,7 @@ const assert = std.debug.assert;
12const testing = std.testing;12const testing = std.testing;
13const builtin = @import("builtin");13const builtin = @import("builtin");
14const maxInt = std.math.maxInt;14const maxInt = std.math.maxInt;
15const Poly1305 = std.crypto.Poly1305;15const Poly1305 = std.crypto.onetimeauth.Poly1305;
1616
17const QuarterRound = struct {17const QuarterRound = struct {
18 a: usize,18 a: usize,
...@@ -137,56 +137,60 @@ fn keyToWords(key: [32]u8) [8]u32 {...@@ -137,56 +137,60 @@ fn keyToWords(key: [32]u8) [8]u32 {
137///137///
138/// ChaCha20 is self-reversing. To decrypt just run the cipher with the same138/// ChaCha20 is self-reversing. To decrypt just run the cipher with the same
139/// counter, nonce, and key.139/// counter, nonce, and key.
140pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [12]u8) void {140pub const ChaCha20IETF = struct {
141 assert(in.len >= out.len);141 pub fn xor(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [12]u8) void {
142 assert((in.len >> 6) + counter <= maxInt(u32));142 assert(in.len >= out.len);
143143 assert((in.len >> 6) + counter <= maxInt(u32));
144 var c: [4]u32 = undefined;144
145 c[0] = counter;145 var c: [4]u32 = undefined;
146 c[1] = mem.readIntLittle(u32, nonce[0..4]);146 c[0] = counter;
147 c[2] = mem.readIntLittle(u32, nonce[4..8]);147 c[1] = mem.readIntLittle(u32, nonce[0..4]);
148 c[3] = mem.readIntLittle(u32, nonce[8..12]);148 c[2] = mem.readIntLittle(u32, nonce[4..8]);
149 chaCha20_internal(out, in, keyToWords(key), c);149 c[3] = mem.readIntLittle(u32, nonce[8..12]);
150}150 chaCha20_internal(out, in, keyToWords(key), c);
151 }
152};
151153
152/// This is the original ChaCha20 before RFC 7539, which recommends using the154/// This is the original ChaCha20 before RFC 7539, which recommends using the
153/// orgininal version on applications such as disk or file encryption that might155/// orgininal version on applications such as disk or file encryption that might
154/// exceed the 256 GiB limit of the 96-bit nonce version.156/// exceed the 256 GiB limit of the 96-bit nonce version.
155pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]u8, nonce: [8]u8) void {157pub const ChaCha20With64BitNonce = struct {
156 assert(in.len >= out.len);158 pub fn xor(out: []u8, in: []const u8, counter: u64, key: [32]u8, nonce: [8]u8) void {
157 assert(counter +% (in.len >> 6) >= counter);159 assert(in.len >= out.len);
158160 assert(counter +% (in.len >> 6) >= counter);
159 var cursor: usize = 0;161
160 const k = keyToWords(key);162 var cursor: usize = 0;
161 var c: [4]u32 = undefined;163 const k = keyToWords(key);
162 c[0] = @truncate(u32, counter);164 var c: [4]u32 = undefined;
163 c[1] = @truncate(u32, counter >> 32);165 c[0] = @truncate(u32, counter);
164 c[2] = mem.readIntLittle(u32, nonce[0..4]);166 c[1] = @truncate(u32, counter >> 32);
165 c[3] = mem.readIntLittle(u32, nonce[4..8]);167 c[2] = mem.readIntLittle(u32, nonce[0..4]);
166168 c[3] = mem.readIntLittle(u32, nonce[4..8]);
167 const block_size = (1 << 6);169
168 // The full block size is greater than the address space on a 32bit machine170 const block_size = (1 << 6);
169 const big_block = if (@sizeOf(usize) > 4) (block_size << 32) else maxInt(usize);171 // The full block size is greater than the address space on a 32bit machine
170172 const big_block = if (@sizeOf(usize) > 4) (block_size << 32) else maxInt(usize);
171 // first partial big block173
172 if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) {174 // first partial big block
173 chaCha20_internal(out[cursor..big_block], in[cursor..big_block], k, c);175 if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) {
174 cursor = big_block - cursor;176 chaCha20_internal(out[cursor..big_block], in[cursor..big_block], k, c);
175 c[1] += 1;177 cursor = big_block - cursor;
176 if (comptime @sizeOf(usize) > 4) {178 c[1] += 1;
177 // A big block is giant: 256 GiB, but we can avoid this limitation179 if (comptime @sizeOf(usize) > 4) {
178 var remaining_blocks: u32 = @intCast(u32, (in.len / big_block));180 // A big block is giant: 256 GiB, but we can avoid this limitation
179 var i: u32 = 0;181 var remaining_blocks: u32 = @intCast(u32, (in.len / big_block));
180 while (remaining_blocks > 0) : (remaining_blocks -= 1) {182 var i: u32 = 0;
181 chaCha20_internal(out[cursor .. cursor + big_block], in[cursor .. cursor + big_block], k, c);183 while (remaining_blocks > 0) : (remaining_blocks -= 1) {
182 c[1] += 1; // upper 32-bit of counter, generic chaCha20_internal() doesn't know about this.184 chaCha20_internal(out[cursor .. cursor + big_block], in[cursor .. cursor + big_block], k, c);
183 cursor += big_block;185 c[1] += 1; // upper 32-bit of counter, generic chaCha20_internal() doesn't know about this.
186 cursor += big_block;
187 }
184 }188 }
185 }189 }
186 }
187190
188 chaCha20_internal(out[cursor..], in[cursor..], k, c);191 chaCha20_internal(out[cursor..], in[cursor..], k, c);
189}192 }
193};
190194
191// https://tools.ietf.org/html/rfc7539#section-2.4.2195// https://tools.ietf.org/html/rfc7539#section-2.4.2
192test "crypto.chacha20 test vector sunscreen" {196test "crypto.chacha20 test vector sunscreen" {
...@@ -221,12 +225,12 @@ test "crypto.chacha20 test vector sunscreen" {...@@ -221,12 +225,12 @@ test "crypto.chacha20 test vector sunscreen" {
221 0, 0, 0, 0,225 0, 0, 0, 0,
222 };226 };
223227
224 chaCha20IETF(result[0..], input[0..], 1, key, nonce);228 ChaCha20IETF.xor(result[0..], input[0..], 1, key, nonce);
225 testing.expectEqualSlices(u8, &expected_result, &result);229 testing.expectEqualSlices(u8, &expected_result, &result);
226230
227 // Chacha20 is self-reversing.231 // Chacha20 is self-reversing.
228 var plaintext: [114]u8 = undefined;232 var plaintext: [114]u8 = undefined;
229 chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce);233 ChaCha20IETF.xor(plaintext[0..], result[0..], 1, key, nonce);
230 testing.expect(mem.order(u8, input, &plaintext) == .eq);234 testing.expect(mem.order(u8, input, &plaintext) == .eq);
231}235}
232236
...@@ -261,7 +265,7 @@ test "crypto.chacha20 test vector 1" {...@@ -261,7 +265,7 @@ test "crypto.chacha20 test vector 1" {
261 };265 };
262 const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 };266 const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
263267
264 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);268 ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce);
265 testing.expectEqualSlices(u8, &expected_result, &result);269 testing.expectEqualSlices(u8, &expected_result, &result);
266}270}
267271
...@@ -295,7 +299,7 @@ test "crypto.chacha20 test vector 2" {...@@ -295,7 +299,7 @@ test "crypto.chacha20 test vector 2" {
295 };299 };
296 const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 };300 const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
297301
298 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);302 ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce);
299 testing.expectEqualSlices(u8, &expected_result, &result);303 testing.expectEqualSlices(u8, &expected_result, &result);
300}304}
301305
...@@ -329,7 +333,7 @@ test "crypto.chacha20 test vector 3" {...@@ -329,7 +333,7 @@ test "crypto.chacha20 test vector 3" {
329 };333 };
330 const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 1 };334 const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 1 };
331335
332 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);336 ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce);
333 testing.expectEqualSlices(u8, &expected_result, &result);337 testing.expectEqualSlices(u8, &expected_result, &result);
334}338}
335339
...@@ -363,7 +367,7 @@ test "crypto.chacha20 test vector 4" {...@@ -363,7 +367,7 @@ test "crypto.chacha20 test vector 4" {
363 };367 };
364 const nonce = [_]u8{ 1, 0, 0, 0, 0, 0, 0, 0 };368 const nonce = [_]u8{ 1, 0, 0, 0, 0, 0, 0, 0 };
365369
366 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);370 ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce);
367 testing.expectEqualSlices(u8, &expected_result, &result);371 testing.expectEqualSlices(u8, &expected_result, &result);
368}372}
369373
...@@ -435,21 +439,21 @@ test "crypto.chacha20 test vector 5" {...@@ -435,21 +439,21 @@ test "crypto.chacha20 test vector 5" {
435 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,439 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
436 };440 };
437441
438 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);442 ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce);
439 testing.expectEqualSlices(u8, &expected_result, &result);443 testing.expectEqualSlices(u8, &expected_result, &result);
440}444}
441445
442pub const chacha20poly1305_tag_size = 16;446pub const chacha20poly1305_tag_size = 16;
443447
444pub fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void {448fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void {
445 assert(ciphertext.len >= plaintext.len);449 assert(ciphertext.len >= plaintext.len);
446450
447 // derive poly1305 key451 // derive poly1305 key
448 var polyKey = [_]u8{0} ** 32;452 var polyKey = [_]u8{0} ** 32;
449 chaCha20IETF(polyKey[0..], polyKey[0..], 0, key, nonce);453 ChaCha20IETF.xor(polyKey[0..], polyKey[0..], 0, key, nonce);
450454
451 // encrypt plaintext455 // encrypt plaintext
452 chaCha20IETF(ciphertext[0..plaintext.len], plaintext, 1, key, nonce);456 ChaCha20IETF.xor(ciphertext[0..plaintext.len], plaintext, 1, key, nonce);
453457
454 // construct mac458 // construct mac
455 var mac = Poly1305.init(polyKey[0..]);459 var mac = Poly1305.init(polyKey[0..]);
...@@ -472,18 +476,18 @@ pub fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_ta...@@ -472,18 +476,18 @@ pub fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_ta
472 mac.final(tag);476 mac.final(tag);
473}477}
474478
475pub fn chacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void {479fn chacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void {
476 return chacha20poly1305SealDetached(ciphertextAndTag[0..plaintext.len], ciphertextAndTag[plaintext.len..][0..chacha20poly1305_tag_size], plaintext, data, key, nonce);480 return chacha20poly1305SealDetached(ciphertextAndTag[0..plaintext.len], ciphertextAndTag[plaintext.len..][0..chacha20poly1305_tag_size], plaintext, data, key, nonce);
477}481}
478482
479/// Verifies and decrypts an authenticated message produced by chacha20poly1305SealDetached.483/// Verifies and decrypts an authenticated message produced by chacha20poly1305SealDetached.
480pub fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void {484fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void {
481 // split ciphertext and tag485 // split ciphertext and tag
482 assert(dst.len >= ciphertext.len);486 assert(dst.len >= ciphertext.len);
483487
484 // derive poly1305 key488 // derive poly1305 key
485 var polyKey = [_]u8{0} ** 32;489 var polyKey = [_]u8{0} ** 32;
486 chaCha20IETF(polyKey[0..], polyKey[0..], 0, key, nonce);490 ChaCha20IETF.xor(polyKey[0..], polyKey[0..], 0, key, nonce);
487491
488 // construct mac492 // construct mac
489 var mac = Poly1305.init(polyKey[0..]);493 var mac = Poly1305.init(polyKey[0..]);
...@@ -519,11 +523,11 @@ pub fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *con...@@ -519,11 +523,11 @@ pub fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *con
519 }523 }
520524
521 // decrypt ciphertext525 // decrypt ciphertext
522 chaCha20IETF(dst[0..ciphertext.len], ciphertext, 1, key, nonce);526 ChaCha20IETF.xor(dst[0..ciphertext.len], ciphertext, 1, key, nonce);
523}527}
524528
525/// Verifies and decrypts an authenticated message produced by chacha20poly1305Seal.529/// Verifies and decrypts an authenticated message produced by chacha20poly1305Seal.
526pub fn chacha20poly1305Open(dst: []u8, ciphertextAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void {530fn chacha20poly1305Open(dst: []u8, ciphertextAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void {
527 if (ciphertextAndTag.len < chacha20poly1305_tag_size) {531 if (ciphertextAndTag.len < chacha20poly1305_tag_size) {
528 return error.InvalidMessage;532 return error.InvalidMessage;
529 }533 }
...@@ -562,31 +566,33 @@ fn extend(key: [32]u8, nonce: [24]u8) struct { key: [32]u8, nonce: [12]u8 } {...@@ -562,31 +566,33 @@ fn extend(key: [32]u8, nonce: [24]u8) struct { key: [32]u8, nonce: [12]u8 } {
562 };566 };
563}567}
564568
565pub fn xChaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [24]u8) void {569pub const XChaCha20IETF = struct {
566 const extended = extend(key, nonce);570 pub fn xor(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [24]u8) void {
567 chaCha20IETF(out, in, counter, extended.key, extended.nonce);571 const extended = extend(key, nonce);
568}572 ChaCha20IETF.xor(out, in, counter, extended.key, extended.nonce);
573 }
574};
569575
570pub const xchacha20poly1305_tag_size = 16;576pub const xchacha20poly1305_tag_size = 16;
571577
572pub fn xchacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void {578fn xchacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void {
573 const extended = extend(key, nonce);579 const extended = extend(key, nonce);
574 return chacha20poly1305SealDetached(ciphertext, tag, plaintext, data, extended.key, extended.nonce);580 return chacha20poly1305SealDetached(ciphertext, tag, plaintext, data, extended.key, extended.nonce);
575}581}
576582
577pub fn xchacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void {583fn xchacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void {
578 const extended = extend(key, nonce);584 const extended = extend(key, nonce);
579 return chacha20poly1305Seal(ciphertextAndTag, plaintext, data, extended.key, extended.nonce);585 return chacha20poly1305Seal(ciphertextAndTag, plaintext, data, extended.key, extended.nonce);
580}586}
581587
582/// Verifies and decrypts an authenticated message produced by xchacha20poly1305SealDetached.588/// Verifies and decrypts an authenticated message produced by xchacha20poly1305SealDetached.
583pub fn xchacha20poly1305OpenDetached(plaintext: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void {589fn xchacha20poly1305OpenDetached(plaintext: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void {
584 const extended = extend(key, nonce);590 const extended = extend(key, nonce);
585 return try chacha20poly1305OpenDetached(plaintext, ciphertext, tag, data, extended.key, extended.nonce);591 return try chacha20poly1305OpenDetached(plaintext, ciphertext, tag, data, extended.key, extended.nonce);
586}592}
587593
588/// Verifies and decrypts an authenticated message produced by xchacha20poly1305Seal.594/// Verifies and decrypts an authenticated message produced by xchacha20poly1305Seal.
589pub fn xchacha20poly1305Open(ciphertextAndTag: []u8, msgAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void {595fn xchacha20poly1305Open(ciphertextAndTag: []u8, msgAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void {
590 const extended = extend(key, nonce);596 const extended = extend(key, nonce);
591 return try chacha20poly1305Open(ciphertextAndTag, msgAndTag, data, extended.key, extended.nonce);597 return try chacha20poly1305Open(ciphertextAndTag, msgAndTag, data, extended.key, extended.nonce);
592}598}
...@@ -714,7 +720,7 @@ test "crypto.xchacha20" {...@@ -714,7 +720,7 @@ test "crypto.xchacha20" {
714 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.";720 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.";
715 {721 {
716 var ciphertext: [input.len]u8 = undefined;722 var ciphertext: [input.len]u8 = undefined;
717 xChaCha20IETF(ciphertext[0..], input[0..], 0, key, nonce);723 XChaCha20IETF.xor(ciphertext[0..], input[0..], 0, key, nonce);
718 var buf: [2 * ciphertext.len]u8 = undefined;724 var buf: [2 * ciphertext.len]u8 = undefined;
719 testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{ciphertext}), "E0A1BCF939654AFDBDC1746EC49832647C19D891F0D1A81FC0C1703B4514BDEA584B512F6908C2C5E9DD18D5CBC1805DE5803FE3B9CA5F193FB8359E91FAB0C3BB40309A292EB1CF49685C65C4A3ADF4F11DB0CD2B6B67FBC174BC2E860E8F769FD3565BBFAD1C845E05A0FED9BE167C240D");725 testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{ciphertext}), "E0A1BCF939654AFDBDC1746EC49832647C19D891F0D1A81FC0C1703B4514BDEA584B512F6908C2C5E9DD18D5CBC1805DE5803FE3B9CA5F193FB8359E91FAB0C3BB40309A292EB1CF49685C65C4A3ADF4F11DB0CD2B6B67FBC174BC2E860E8F769FD3565BBFAD1C845E05A0FED9BE167C240D");
720 }726 }
lib/std/crypto/gimli.zig+8-7
...@@ -109,13 +109,14 @@ pub const Hash = struct {...@@ -109,13 +109,14 @@ pub const Hash = struct {
109 state: State,109 state: State,
110 buf_off: usize,110 buf_off: usize,
111111
112 pub const block_length = State.RATE;
113 pub const Options = struct {};
114
112 const Self = @This();115 const Self = @This();
113116
114 pub fn init() Self {117 pub fn init(options: Options) Self {
115 return Self{118 return Self{
116 .state = State{119 .state = State{ .data = [_]u32{0} ** (State.BLOCKBYTES / 4) },
117 .data = [_]u32{0} ** (State.BLOCKBYTES / 4),
118 },
119 .buf_off = 0,120 .buf_off = 0,
120 };121 };
121 }122 }
...@@ -160,8 +161,8 @@ pub const Hash = struct {...@@ -160,8 +161,8 @@ pub const Hash = struct {
160 }161 }
161};162};
162163
163pub fn hash(out: []u8, in: []const u8) void {164pub fn hash(out: []u8, in: []const u8, options: Hash.Options) void {
164 var st = Hash.init();165 var st = Hash.init(options);
165 st.update(in);166 st.update(in);
166 st.final(out);167 st.final(out);
167}168}
...@@ -174,7 +175,7 @@ test "hash" {...@@ -174,7 +175,7 @@ test "hash" {
174 var msg: [58 / 2]u8 = undefined;175 var msg: [58 / 2]u8 = undefined;
175 try std.fmt.hexToBytes(&msg, "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C");176 try std.fmt.hexToBytes(&msg, "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C");
176 var md: [32]u8 = undefined;177 var md: [32]u8 = undefined;
177 hash(&md, &msg);178 hash(&md, &msg, .{});
178 htest.assertEqual("1C9A03DC6A5DDC5444CFC6F4B154CFF5CF081633B2CEA4D7D0AE7CCFED5AAA44", &md);179 htest.assertEqual("1C9A03DC6A5DDC5444CFC6F4B154CFF5CF081633B2CEA4D7D0AE7CCFED5AAA44", &md);
179}180}
180181
lib/std/crypto/hmac.zig+22-13
...@@ -8,10 +8,19 @@ const crypto = std.crypto;...@@ -8,10 +8,19 @@ const crypto = std.crypto;
8const debug = std.debug;8const debug = std.debug;
9const mem = std.mem;9const mem = std.mem;
1010
11pub const HmacMd5 = Hmac(crypto.Md5);11pub const HmacMd5 = Hmac(crypto.hash.Md5);
12pub const HmacSha1 = Hmac(crypto.Sha1);12pub const HmacSha1 = Hmac(crypto.hash.Sha1);
13pub const HmacSha256 = Hmac(crypto.Sha256);13
14pub const HmacBlake2s256 = Hmac(crypto.Blake2s256);14pub const sha2 = struct {
15 pub const HmacSha224 = Hmac(crypto.hash.sha2.Sha224);
16 pub const HmacSha256 = Hmac(crypto.hash.sha2.Sha256);
17 pub const HmacSha384 = Hmac(crypto.hash.sha2.Sha384);
18 pub const HmacSha512 = Hmac(crypto.hash.sha2.Sha512);
19};
20
21pub const blake2 = struct {
22 pub const HmacBlake2s256 = Hmac(crypto.hash.blake2.Blake2s256);
23};
1524
16pub fn Hmac(comptime Hash: type) type {25pub fn Hmac(comptime Hash: type) type {
17 return struct {26 return struct {
...@@ -36,7 +45,7 @@ pub fn Hmac(comptime Hash: type) type {...@@ -36,7 +45,7 @@ pub fn Hmac(comptime Hash: type) type {
3645
37 // Normalize key length to block size of hash46 // Normalize key length to block size of hash
38 if (key.len > Hash.block_length) {47 if (key.len > Hash.block_length) {
39 Hash.hash(key, ctx.scratch[0..mac_length]);48 Hash.hash(key, ctx.scratch[0..mac_length], .{});
40 mem.set(u8, ctx.scratch[mac_length..Hash.block_length], 0);49 mem.set(u8, ctx.scratch[mac_length..Hash.block_length], 0);
41 } else if (key.len < Hash.block_length) {50 } else if (key.len < Hash.block_length) {
42 mem.copy(u8, ctx.scratch[0..key.len], key);51 mem.copy(u8, ctx.scratch[0..key.len], key);
...@@ -53,7 +62,7 @@ pub fn Hmac(comptime Hash: type) type {...@@ -53,7 +62,7 @@ pub fn Hmac(comptime Hash: type) type {
53 b.* = ctx.scratch[i] ^ 0x36;62 b.* = ctx.scratch[i] ^ 0x36;
54 }63 }
5564
56 ctx.hash = Hash.init();65 ctx.hash = Hash.init(.{});
57 ctx.hash.update(ctx.i_key_pad[0..]);66 ctx.hash.update(ctx.i_key_pad[0..]);
58 return ctx;67 return ctx;
59 }68 }
...@@ -66,10 +75,10 @@ pub fn Hmac(comptime Hash: type) type {...@@ -66,10 +75,10 @@ pub fn Hmac(comptime Hash: type) type {
66 debug.assert(Hash.block_length >= out.len and out.len >= mac_length);75 debug.assert(Hash.block_length >= out.len and out.len >= mac_length);
6776
68 ctx.hash.final(ctx.scratch[0..mac_length]);77 ctx.hash.final(ctx.scratch[0..mac_length]);
69 ctx.hash.reset();78 var ohash = Hash.init(.{});
70 ctx.hash.update(ctx.o_key_pad[0..]);79 ohash.update(ctx.o_key_pad[0..]);
71 ctx.hash.update(ctx.scratch[0..mac_length]);80 ohash.update(ctx.scratch[0..mac_length]);
72 ctx.hash.final(out[0..mac_length]);81 ohash.final(out[0..mac_length]);
73 }82 }
74 };83 };
75}84}
...@@ -95,10 +104,10 @@ test "hmac sha1" {...@@ -95,10 +104,10 @@ test "hmac sha1" {
95}104}
96105
97test "hmac sha256" {106test "hmac sha256" {
98 var out: [HmacSha256.mac_length]u8 = undefined;107 var out: [sha2.HmacSha256.mac_length]u8 = undefined;
99 HmacSha256.create(out[0..], "", "");108 sha2.HmacSha256.create(out[0..], "", "");
100 htest.assertEqual("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", out[0..]);109 htest.assertEqual("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", out[0..]);
101110
102 HmacSha256.create(out[0..], "The quick brown fox jumps over the lazy dog", "key");111 sha2.HmacSha256.create(out[0..], "The quick brown fox jumps over the lazy dog", "key");
103 htest.assertEqual("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8", out[0..]);112 htest.assertEqual("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8", out[0..]);
104}113}
lib/std/crypto/md5.zig+22-19
...@@ -32,10 +32,14 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar...@@ -32,10 +32,14 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar
32 };32 };
33}33}
3434
35/// The MD5 function is now considered cryptographically broken.
36/// Namely, it is trivial to find multiple inputs producing the same hash.
37/// For a fast-performing, cryptographically secure hash function, see SHA512/256, BLAKE2 or BLAKE3.
35pub const Md5 = struct {38pub const Md5 = struct {
36 const Self = @This();39 const Self = @This();
37 pub const block_length = 64;40 pub const block_length = 64;
38 pub const digest_length = 16;41 pub const digest_length = 16;
42 pub const Options = struct {};
3943
40 s: [4]u32,44 s: [4]u32,
41 // Streaming Cache45 // Streaming Cache
...@@ -43,23 +47,22 @@ pub const Md5 = struct {...@@ -43,23 +47,22 @@ pub const Md5 = struct {
43 buf_len: u8,47 buf_len: u8,
44 total_len: u64,48 total_len: u64,
4549
46 pub fn init() Self {50 pub fn init(options: Options) Self {
47 var d: Self = undefined;51 return Self{
48 d.reset();52 .s = [_]u32{
49 return d;53 0x67452301,
50 }54 0xEFCDAB89,
5155 0x98BADCFE,
52 pub fn reset(d: *Self) void {56 0x10325476,
53 d.s[0] = 0x67452301;57 },
54 d.s[1] = 0xEFCDAB89;58 .buf = undefined,
55 d.s[2] = 0x98BADCFE;59 .buf_len = 0,
56 d.s[3] = 0x10325476;60 .total_len = 0,
57 d.buf_len = 0;61 };
58 d.total_len = 0;
59 }62 }
6063
61 pub fn hash(b: []const u8, out: []u8) void {64 pub fn hash(b: []const u8, out: []u8, options: Options) void {
62 var d = Md5.init();65 var d = Md5.init(options);
63 d.update(b);66 d.update(b);
64 d.final(out);67 d.final(out);
65 }68 }
...@@ -255,18 +258,18 @@ test "md5 single" {...@@ -255,18 +258,18 @@ test "md5 single" {
255}258}
256259
257test "md5 streaming" {260test "md5 streaming" {
258 var h = Md5.init();261 var h = Md5.init(.{});
259 var out: [16]u8 = undefined;262 var out: [16]u8 = undefined;
260263
261 h.final(out[0..]);264 h.final(out[0..]);
262 htest.assertEqual("d41d8cd98f00b204e9800998ecf8427e", out[0..]);265 htest.assertEqual("d41d8cd98f00b204e9800998ecf8427e", out[0..]);
263266
264 h.reset();267 h = Md5.init(.{});
265 h.update("abc");268 h.update("abc");
266 h.final(out[0..]);269 h.final(out[0..]);
267 htest.assertEqual("900150983cd24fb0d6963f7d28e17f72", out[0..]);270 htest.assertEqual("900150983cd24fb0d6963f7d28e17f72", out[0..]);
268271
269 h.reset();272 h = Md5.init(.{});
270 h.update("a");273 h.update("a");
271 h.update("b");274 h.update("b");
272 h.update("c");275 h.update("c");
...@@ -279,7 +282,7 @@ test "md5 aligned final" {...@@ -279,7 +282,7 @@ test "md5 aligned final" {
279 var block = [_]u8{0} ** Md5.block_length;282 var block = [_]u8{0} ** Md5.block_length;
280 var out: [Md5.digest_length]u8 = undefined;283 var out: [Md5.digest_length]u8 = undefined;
281284
282 var h = Md5.init();285 var h = Md5.init(.{});
283 h.update(&block);286 h.update(&block);
284 h.final(out[0..]);287 h.final(out[0..]);
285}288}
lib/std/crypto/sha1.zig+24-24
...@@ -29,35 +29,35 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {...@@ -29,35 +29,35 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {
29 };29 };
30}30}
3131
32/// The SHA-1 function is now considered cryptographically broken.
33/// Namely, it is feasible to find multiple inputs producing the same hash.
34/// For a fast-performing, cryptographically secure hash function, see SHA512/256, BLAKE2 or BLAKE3.
32pub const Sha1 = struct {35pub const Sha1 = struct {
33 const Self = @This();36 const Self = @This();
34 pub const block_length = 64;37 pub const block_length = 64;
35 pub const digest_length = 20;38 pub const digest_length = 20;
39 pub const Options = struct {};
3640
37 s: [5]u32,41 s: [5]u32,
38 // Streaming Cache42 // Streaming Cache
39 buf: [64]u8,43 buf: [64]u8 = undefined,
40 buf_len: u8,44 buf_len: u8 = 0,
41 total_len: u64,45 total_len: u64 = 0,
4246
43 pub fn init() Self {47 pub fn init(options: Options) Self {
44 var d: Self = undefined;48 return Self{
45 d.reset();49 .s = [_]u32{
46 return d;50 0x67452301,
47 }51 0xEFCDAB89,
4852 0x98BADCFE,
49 pub fn reset(d: *Self) void {53 0x10325476,
50 d.s[0] = 0x67452301;54 0xC3D2E1F0,
51 d.s[1] = 0xEFCDAB89;55 },
52 d.s[2] = 0x98BADCFE;56 };
53 d.s[3] = 0x10325476;
54 d.s[4] = 0xC3D2E1F0;
55 d.buf_len = 0;
56 d.total_len = 0;
57 }57 }
5858
59 pub fn hash(b: []const u8, out: []u8) void {59 pub fn hash(b: []const u8, out: []u8, options: Options) void {
60 var d = Sha1.init();60 var d = Sha1.init(options);
61 d.update(b);61 d.update(b);
62 d.final(out);62 d.final(out);
63 }63 }
...@@ -277,18 +277,18 @@ test "sha1 single" {...@@ -277,18 +277,18 @@ test "sha1 single" {
277}277}
278278
279test "sha1 streaming" {279test "sha1 streaming" {
280 var h = Sha1.init();280 var h = Sha1.init(.{});
281 var out: [20]u8 = undefined;281 var out: [20]u8 = undefined;
282282
283 h.final(out[0..]);283 h.final(out[0..]);
284 htest.assertEqual("da39a3ee5e6b4b0d3255bfef95601890afd80709", out[0..]);284 htest.assertEqual("da39a3ee5e6b4b0d3255bfef95601890afd80709", out[0..]);
285285
286 h.reset();286 h = Sha1.init(.{});
287 h.update("abc");287 h.update("abc");
288 h.final(out[0..]);288 h.final(out[0..]);
289 htest.assertEqual("a9993e364706816aba3e25717850c26c9cd0d89d", out[0..]);289 htest.assertEqual("a9993e364706816aba3e25717850c26c9cd0d89d", out[0..]);
290290
291 h.reset();291 h = Sha1.init(.{});
292 h.update("a");292 h.update("a");
293 h.update("b");293 h.update("b");
294 h.update("c");294 h.update("c");
...@@ -300,7 +300,7 @@ test "sha1 aligned final" {...@@ -300,7 +300,7 @@ test "sha1 aligned final" {
300 var block = [_]u8{0} ** Sha1.block_length;300 var block = [_]u8{0} ** Sha1.block_length;
301 var out: [Sha1.digest_length]u8 = undefined;301 var out: [Sha1.digest_length]u8 = undefined;
302302
303 var h = Sha1.init();303 var h = Sha1.init(.{});
304 h.update(&block);304 h.update(&block);
305 h.final(out[0..]);305 h.final(out[0..]);
306}306}
lib/std/crypto/sha2.zig+90-60
...@@ -77,7 +77,10 @@ const Sha256Params = Sha2Params32{...@@ -77,7 +77,10 @@ const Sha256Params = Sha2Params32{
77 .out_len = 256,77 .out_len = 256,
78};78};
7979
80/// SHA-224
80pub const Sha224 = Sha2_32(Sha224Params);81pub const Sha224 = Sha2_32(Sha224Params);
82
83/// SHA-256
81pub const Sha256 = Sha2_32(Sha256Params);84pub const Sha256 = Sha2_32(Sha256Params);
8285
83fn Sha2_32(comptime params: Sha2Params32) type {86fn Sha2_32(comptime params: Sha2Params32) type {
...@@ -85,34 +88,31 @@ fn Sha2_32(comptime params: Sha2Params32) type {...@@ -85,34 +88,31 @@ fn Sha2_32(comptime params: Sha2Params32) type {
85 const Self = @This();88 const Self = @This();
86 pub const block_length = 64;89 pub const block_length = 64;
87 pub const digest_length = params.out_len / 8;90 pub const digest_length = params.out_len / 8;
91 pub const Options = struct {};
8892
89 s: [8]u32,93 s: [8]u32,
90 // Streaming Cache94 // Streaming Cache
91 buf: [64]u8,95 buf: [64]u8 = undefined,
92 buf_len: u8,96 buf_len: u8 = 0,
93 total_len: u64,97 total_len: u64 = 0,
9498
95 pub fn init() Self {99 pub fn init(options: Options) Self {
96 var d: Self = undefined;100 return Self{
97 d.reset();101 .s = [_]u32{
98 return d;102 params.iv0,
99 }103 params.iv1,
100104 params.iv2,
101 pub fn reset(d: *Self) void {105 params.iv3,
102 d.s[0] = params.iv0;106 params.iv4,
103 d.s[1] = params.iv1;107 params.iv5,
104 d.s[2] = params.iv2;108 params.iv6,
105 d.s[3] = params.iv3;109 params.iv7,
106 d.s[4] = params.iv4;110 },
107 d.s[5] = params.iv5;111 };
108 d.s[6] = params.iv6;
109 d.s[7] = params.iv7;
110 d.buf_len = 0;
111 d.total_len = 0;
112 }112 }
113113
114 pub fn hash(b: []const u8, out: []u8) void {114 pub fn hash(b: []const u8, out: []u8, options: Options) void {
115 var d = Self.init();115 var d = Self.init(options);
116 d.update(b);116 d.update(b);
117 d.final(out);117 d.final(out);
118 }118 }
...@@ -297,18 +297,18 @@ test "sha224 single" {...@@ -297,18 +297,18 @@ test "sha224 single" {
297}297}
298298
299test "sha224 streaming" {299test "sha224 streaming" {
300 var h = Sha224.init();300 var h = Sha224.init(.{});
301 var out: [28]u8 = undefined;301 var out: [28]u8 = undefined;
302302
303 h.final(out[0..]);303 h.final(out[0..]);
304 htest.assertEqual("d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", out[0..]);304 htest.assertEqual("d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", out[0..]);
305305
306 h.reset();306 h = Sha224.init(.{});
307 h.update("abc");307 h.update("abc");
308 h.final(out[0..]);308 h.final(out[0..]);
309 htest.assertEqual("23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", out[0..]);309 htest.assertEqual("23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", out[0..]);
310310
311 h.reset();311 h = Sha224.init(.{});
312 h.update("a");312 h.update("a");
313 h.update("b");313 h.update("b");
314 h.update("c");314 h.update("c");
...@@ -323,18 +323,18 @@ test "sha256 single" {...@@ -323,18 +323,18 @@ test "sha256 single" {
323}323}
324324
325test "sha256 streaming" {325test "sha256 streaming" {
326 var h = Sha256.init();326 var h = Sha256.init(.{});
327 var out: [32]u8 = undefined;327 var out: [32]u8 = undefined;
328328
329 h.final(out[0..]);329 h.final(out[0..]);
330 htest.assertEqual("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", out[0..]);330 htest.assertEqual("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", out[0..]);
331331
332 h.reset();332 h = Sha256.init(.{});
333 h.update("abc");333 h.update("abc");
334 h.final(out[0..]);334 h.final(out[0..]);
335 htest.assertEqual("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", out[0..]);335 htest.assertEqual("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", out[0..]);
336336
337 h.reset();337 h = Sha256.init(.{});
338 h.update("a");338 h.update("a");
339 h.update("b");339 h.update("b");
340 h.update("c");340 h.update("c");
...@@ -346,7 +346,7 @@ test "sha256 aligned final" {...@@ -346,7 +346,7 @@ test "sha256 aligned final" {
346 var block = [_]u8{0} ** Sha256.block_length;346 var block = [_]u8{0} ** Sha256.block_length;
347 var out: [Sha256.digest_length]u8 = undefined;347 var out: [Sha256.digest_length]u8 = undefined;
348348
349 var h = Sha256.init();349 var h = Sha256.init(.{});
350 h.update(&block);350 h.update(&block);
351 h.final(out[0..]);351 h.final(out[0..]);
352}352}
...@@ -418,42 +418,72 @@ const Sha512Params = Sha2Params64{...@@ -418,42 +418,72 @@ const Sha512Params = Sha2Params64{
418 .out_len = 512,418 .out_len = 512,
419};419};
420420
421const Sha512256Params = Sha2Params64{
422 .iv0 = 0x22312194FC2BF72C,
423 .iv1 = 0x9F555FA3C84C64C2,
424 .iv2 = 0x2393B86B6F53B151,
425 .iv3 = 0x963877195940EABD,
426 .iv4 = 0x96283EE2A88EFFE3,
427 .iv5 = 0xBE5E1E2553863992,
428 .iv6 = 0x2B0199FC2C85B8AA,
429 .iv7 = 0x0EB72DDC81C52CA2,
430 .out_len = 256,
431};
432
433const Sha512T256Params = Sha2Params64{
434 .iv0 = 0x6A09E667F3BCC908,
435 .iv1 = 0xBB67AE8584CAA73B,
436 .iv2 = 0x3C6EF372FE94F82B,
437 .iv3 = 0xA54FF53A5F1D36F1,
438 .iv4 = 0x510E527FADE682D1,
439 .iv5 = 0x9B05688C2B3E6C1F,
440 .iv6 = 0x1F83D9ABFB41BD6B,
441 .iv7 = 0x5BE0CD19137E2179,
442 .out_len = 256,
443};
444
445/// SHA-384
421pub const Sha384 = Sha2_64(Sha384Params);446pub const Sha384 = Sha2_64(Sha384Params);
447
448/// SHA-512
422pub const Sha512 = Sha2_64(Sha512Params);449pub const Sha512 = Sha2_64(Sha512Params);
423450
451/// SHA-512/256
452pub const Sha512256 = Sha2_64(Sha512256Params);
453
454/// Truncated SHA-512
455pub const Sha512T256 = Sha2_64(Sha512T256Params);
456
424fn Sha2_64(comptime params: Sha2Params64) type {457fn Sha2_64(comptime params: Sha2Params64) type {
425 return struct {458 return struct {
426 const Self = @This();459 const Self = @This();
427 pub const block_length = 128;460 pub const block_length = 128;
428 pub const digest_length = params.out_len / 8;461 pub const digest_length = params.out_len / 8;
462 pub const Options = struct {};
429463
430 s: [8]u64,464 s: [8]u64,
431 // Streaming Cache465 // Streaming Cache
432 buf: [128]u8,466 buf: [128]u8 = undefined,
433 buf_len: u8,467 buf_len: u8 = 0,
434 total_len: u128,468 total_len: u128 = 0,
435469
436 pub fn init() Self {470 pub fn init(options: Options) Self {
437 var d: Self = undefined;471 return Self{
438 d.reset();472 .s = [_]u64{
439 return d;473 params.iv0,
440 }474 params.iv1,
441475 params.iv2,
442 pub fn reset(d: *Self) void {476 params.iv3,
443 d.s[0] = params.iv0;477 params.iv4,
444 d.s[1] = params.iv1;478 params.iv5,
445 d.s[2] = params.iv2;479 params.iv6,
446 d.s[3] = params.iv3;480 params.iv7,
447 d.s[4] = params.iv4;481 },
448 d.s[5] = params.iv5;482 };
449 d.s[6] = params.iv6;
450 d.s[7] = params.iv7;
451 d.buf_len = 0;
452 d.total_len = 0;
453 }483 }
454484
455 pub fn hash(b: []const u8, out: []u8) void {485 pub fn hash(b: []const u8, out: []u8, options: Options) void {
456 var d = Self.init();486 var d = Self.init(options);
457 d.update(b);487 d.update(b);
458 d.final(out);488 d.final(out);
459 }489 }
...@@ -665,7 +695,7 @@ test "sha384 single" {...@@ -665,7 +695,7 @@ test "sha384 single" {
665}695}
666696
667test "sha384 streaming" {697test "sha384 streaming" {
668 var h = Sha384.init();698 var h = Sha384.init(.{});
669 var out: [48]u8 = undefined;699 var out: [48]u8 = undefined;
670700
671 const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b";701 const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b";
...@@ -674,12 +704,12 @@ test "sha384 streaming" {...@@ -674,12 +704,12 @@ test "sha384 streaming" {
674704
675 const h2 = "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7";705 const h2 = "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7";
676706
677 h.reset();707 h = Sha384.init(.{});
678 h.update("abc");708 h.update("abc");
679 h.final(out[0..]);709 h.final(out[0..]);
680 htest.assertEqual(h2, out[0..]);710 htest.assertEqual(h2, out[0..]);
681711
682 h.reset();712 h = Sha384.init(.{});
683 h.update("a");713 h.update("a");
684 h.update("b");714 h.update("b");
685 h.update("c");715 h.update("c");
...@@ -699,7 +729,7 @@ test "sha512 single" {...@@ -699,7 +729,7 @@ test "sha512 single" {
699}729}
700730
701test "sha512 streaming" {731test "sha512 streaming" {
702 var h = Sha512.init();732 var h = Sha512.init(.{});
703 var out: [64]u8 = undefined;733 var out: [64]u8 = undefined;
704734
705 const h1 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e";735 const h1 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e";
...@@ -708,12 +738,12 @@ test "sha512 streaming" {...@@ -708,12 +738,12 @@ test "sha512 streaming" {
708738
709 const h2 = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";739 const h2 = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
710740
711 h.reset();741 h = Sha512.init(.{});
712 h.update("abc");742 h.update("abc");
713 h.final(out[0..]);743 h.final(out[0..]);
714 htest.assertEqual(h2, out[0..]);744 htest.assertEqual(h2, out[0..]);
715745
716 h.reset();746 h = Sha512.init(.{});
717 h.update("a");747 h.update("a");
718 h.update("b");748 h.update("b");
719 h.update("c");749 h.update("c");
...@@ -725,7 +755,7 @@ test "sha512 aligned final" {...@@ -725,7 +755,7 @@ test "sha512 aligned final" {
725 var block = [_]u8{0} ** Sha512.block_length;755 var block = [_]u8{0} ** Sha512.block_length;
726 var out: [Sha512.digest_length]u8 = undefined;756 var out: [Sha512.digest_length]u8 = undefined;
727757
728 var h = Sha512.init();758 var h = Sha512.init(.{});
729 h.update(&block);759 h.update(&block);
730 h.final(out[0..]);760 h.final(out[0..]);
731}761}
lib/std/crypto/sha3.zig+19-26
...@@ -20,25 +20,18 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {...@@ -20,25 +20,18 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {
20 const Self = @This();20 const Self = @This();
21 pub const block_length = 200;21 pub const block_length = 200;
22 pub const digest_length = bits / 8;22 pub const digest_length = bits / 8;
23 pub const Options = struct {};
2324
24 s: [200]u8,25 s: [200]u8,
25 offset: usize,26 offset: usize,
26 rate: usize,27 rate: usize,
2728
28 pub fn init() Self {29 pub fn init(options: Options) Self {
29 var d: Self = undefined;30 return Self{ .s = [_]u8{0} ** 200, .offset = 0, .rate = 200 - (bits / 4) };
30 d.reset();
31 return d;
32 }31 }
3332
34 pub fn reset(d: *Self) void {33 pub fn hash(b: []const u8, out: []u8, options: Options) void {
35 mem.set(u8, d.s[0..], 0);34 var d = Self.init(options);
36 d.offset = 0;
37 d.rate = 200 - (bits / 4);
38 }
39
40 pub fn hash(b: []const u8, out: []u8) void {
41 var d = Self.init();
42 d.update(b);35 d.update(b);
43 d.final(out);36 d.final(out);
44 }37 }
...@@ -183,18 +176,18 @@ test "sha3-224 single" {...@@ -183,18 +176,18 @@ test "sha3-224 single" {
183}176}
184177
185test "sha3-224 streaming" {178test "sha3-224 streaming" {
186 var h = Sha3_224.init();179 var h = Sha3_224.init(.{});
187 var out: [28]u8 = undefined;180 var out: [28]u8 = undefined;
188181
189 h.final(out[0..]);182 h.final(out[0..]);
190 htest.assertEqual("6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", out[0..]);183 htest.assertEqual("6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", out[0..]);
191184
192 h.reset();185 h = Sha3_224.init(.{});
193 h.update("abc");186 h.update("abc");
194 h.final(out[0..]);187 h.final(out[0..]);
195 htest.assertEqual("e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", out[0..]);188 htest.assertEqual("e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", out[0..]);
196189
197 h.reset();190 h = Sha3_224.init(.{});
198 h.update("a");191 h.update("a");
199 h.update("b");192 h.update("b");
200 h.update("c");193 h.update("c");
...@@ -209,18 +202,18 @@ test "sha3-256 single" {...@@ -209,18 +202,18 @@ test "sha3-256 single" {
209}202}
210203
211test "sha3-256 streaming" {204test "sha3-256 streaming" {
212 var h = Sha3_256.init();205 var h = Sha3_256.init(.{});
213 var out: [32]u8 = undefined;206 var out: [32]u8 = undefined;
214207
215 h.final(out[0..]);208 h.final(out[0..]);
216 htest.assertEqual("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", out[0..]);209 htest.assertEqual("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", out[0..]);
217210
218 h.reset();211 h = Sha3_256.init(.{});
219 h.update("abc");212 h.update("abc");
220 h.final(out[0..]);213 h.final(out[0..]);
221 htest.assertEqual("3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", out[0..]);214 htest.assertEqual("3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", out[0..]);
222215
223 h.reset();216 h = Sha3_256.init(.{});
224 h.update("a");217 h.update("a");
225 h.update("b");218 h.update("b");
226 h.update("c");219 h.update("c");
...@@ -232,7 +225,7 @@ test "sha3-256 aligned final" {...@@ -232,7 +225,7 @@ test "sha3-256 aligned final" {
232 var block = [_]u8{0} ** Sha3_256.block_length;225 var block = [_]u8{0} ** Sha3_256.block_length;
233 var out: [Sha3_256.digest_length]u8 = undefined;226 var out: [Sha3_256.digest_length]u8 = undefined;
234227
235 var h = Sha3_256.init();228 var h = Sha3_256.init(.{});
236 h.update(&block);229 h.update(&block);
237 h.final(out[0..]);230 h.final(out[0..]);
238}231}
...@@ -247,7 +240,7 @@ test "sha3-384 single" {...@@ -247,7 +240,7 @@ test "sha3-384 single" {
247}240}
248241
249test "sha3-384 streaming" {242test "sha3-384 streaming" {
250 var h = Sha3_384.init();243 var h = Sha3_384.init(.{});
251 var out: [48]u8 = undefined;244 var out: [48]u8 = undefined;
252245
253 const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004";246 const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004";
...@@ -255,12 +248,12 @@ test "sha3-384 streaming" {...@@ -255,12 +248,12 @@ test "sha3-384 streaming" {
255 htest.assertEqual(h1, out[0..]);248 htest.assertEqual(h1, out[0..]);
256249
257 const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25";250 const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25";
258 h.reset();251 h = Sha3_384.init(.{});
259 h.update("abc");252 h.update("abc");
260 h.final(out[0..]);253 h.final(out[0..]);
261 htest.assertEqual(h2, out[0..]);254 htest.assertEqual(h2, out[0..]);
262255
263 h.reset();256 h = Sha3_384.init(.{});
264 h.update("a");257 h.update("a");
265 h.update("b");258 h.update("b");
266 h.update("c");259 h.update("c");
...@@ -278,7 +271,7 @@ test "sha3-512 single" {...@@ -278,7 +271,7 @@ test "sha3-512 single" {
278}271}
279272
280test "sha3-512 streaming" {273test "sha3-512 streaming" {
281 var h = Sha3_512.init();274 var h = Sha3_512.init(.{});
282 var out: [64]u8 = undefined;275 var out: [64]u8 = undefined;
283276
284 const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26";277 const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26";
...@@ -286,12 +279,12 @@ test "sha3-512 streaming" {...@@ -286,12 +279,12 @@ test "sha3-512 streaming" {
286 htest.assertEqual(h1, out[0..]);279 htest.assertEqual(h1, out[0..]);
287280
288 const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0";281 const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0";
289 h.reset();282 h = Sha3_512.init(.{});
290 h.update("abc");283 h.update("abc");
291 h.final(out[0..]);284 h.final(out[0..]);
292 htest.assertEqual(h2, out[0..]);285 htest.assertEqual(h2, out[0..]);
293286
294 h.reset();287 h = Sha3_512.init(.{});
295 h.update("a");288 h.update("a");
296 h.update("b");289 h.update("b");
297 h.update("c");290 h.update("c");
...@@ -303,7 +296,7 @@ test "sha3-512 aligned final" {...@@ -303,7 +296,7 @@ test "sha3-512 aligned final" {
303 var block = [_]u8{0} ** Sha3_512.block_length;296 var block = [_]u8{0} ** Sha3_512.block_length;
304 var out: [Sha3_512.digest_length]u8 = undefined;297 var out: [Sha3_512.digest_length]u8 = undefined;
305298
306 var h = Sha3_512.init();299 var h = Sha3_512.init(.{});
307 h.update(&block);300 h.update(&block);
308 h.final(out[0..]);301 h.final(out[0..]);
309}302}
lib/std/crypto/test.zig+1-1
...@@ -11,7 +11,7 @@ const fmt = std.fmt;...@@ -11,7 +11,7 @@ const fmt = std.fmt;
11// Hash using the specified hasher `H` asserting `expected == H(input)`.11// Hash using the specified hasher `H` asserting `expected == H(input)`.
12pub fn assertEqualHash(comptime Hasher: anytype, comptime expected: []const u8, input: []const u8) void {12pub fn assertEqualHash(comptime Hasher: anytype, comptime expected: []const u8, input: []const u8) void {
13 var h: [expected.len / 2]u8 = undefined;13 var h: [expected.len / 2]u8 = undefined;
14 Hasher.hash(input, h[0..]);14 Hasher.hash(input, h[0..], .{});
1515
16 assertEqual(expected, &h);16 assertEqual(expected, &h);
17}17}
lib/std/rand.zig+2-2
...@@ -737,12 +737,12 @@ test "xoroshiro sequence" {...@@ -737,12 +737,12 @@ test "xoroshiro sequence" {
737// CSPRNG737// CSPRNG
738pub const Gimli = struct {738pub const Gimli = struct {
739 random: Random,739 random: Random,
740 state: std.crypto.gimli.State,740 state: std.crypto.core.Gimli,
741741
742 pub fn init(init_s: u64) Gimli {742 pub fn init(init_s: u64) Gimli {
743 var self = Gimli{743 var self = Gimli{
744 .random = Random{ .fillFn = fill },744 .random = Random{ .fillFn = fill },
745 .state = std.crypto.gimli.State{745 .state = std.crypto.core.Gimli{
746 .data = [_]u32{0} ** (std.crypto.gimli.State.BLOCKBYTES / 4),746 .data = [_]u32{0} ** (std.crypto.gimli.State.BLOCKBYTES / 4),
747 },747 },
748 };748 };
lib/std/zig.zig+1-1
...@@ -26,7 +26,7 @@ pub fn hashSrc(src: []const u8) SrcHash {...@@ -26,7 +26,7 @@ pub fn hashSrc(src: []const u8) SrcHash {
26 std.mem.copy(u8, &out, src);26 std.mem.copy(u8, &out, src);
27 std.mem.set(u8, out[src.len..], 0);27 std.mem.set(u8, out[src.len..], 0);
28 } else {28 } else {
29 std.crypto.Blake3.hash(src, &out);29 std.crypto.hash.Blake3.hash(src, &out, .{});
30 }30 }
31 return out;31 return out;
32}32}
tools/process_headers.zig+1-1
...@@ -313,7 +313,7 @@ pub fn main() !void {...@@ -313,7 +313,7 @@ pub fn main() !void {
313 var max_bytes_saved: usize = 0;313 var max_bytes_saved: usize = 0;
314 var total_bytes: usize = 0;314 var total_bytes: usize = 0;
315315
316 var hasher = std.crypto.Sha256.init();316 var hasher = std.crypto.hash.sha2.Sha256.init(.{});
317317
318 for (libc_targets) |libc_target| {318 for (libc_targets) |libc_target| {
319 const dest_target = DestTarget{319 const dest_target = DestTarget{