authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2020-08-19 16:21:05+02:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2020-08-20 23:02:05+02:00
log6f9ea9eaef79863ebdc9bf44b2af67ec4caad031
tree4a34acd626affbf4e98484a357e6464c92952b2a
parent1a4059ed88740c0289b7fea5735115fa9481a8e5

Breaking: sort std/crypto functions into categories

Instead of having all primitives and constructions share the same namespace, they are now organized by category and function family. Types within the same category are expected to share the exact same API.

16 files changed, 248 insertions(+), 200 deletions(-)

lib/std/bloom_filter.zig+1-1
......@@ -158,7 +158,7 @@ pub fn BloomFilter(
158158}
159159
160160fn 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();
162162 st.update(std.mem.asBytes(&Ki));
163163 st.update(in);
164164 st.final(out);
lib/std/build/write_file.zig+1-1
......@@ -58,7 +58,7 @@ pub const WriteFileStep = struct {
5858 // TODO port the cache system from stage1 to zig std lib. Until then we use blake2b
5959 // directly and construct the path, and no "cache hit" detection happens; the files
6060 // are always written.
61 var hash = std.crypto.Blake2b384.init();
61 var hash = std.crypto.hash.blake2.Blake2b384.init();
6262
6363 // Random bytes to make WriteFileStep unique. Refresh this with
6464 // new random bytes when WriteFileStep implementation is modified
lib/std/cache_hash.zig+1-1
......@@ -4,7 +4,7 @@
44// The MIT license requires this copyright notice to be included in all copies
55// and substantial portions of the software.
66const std = @import("std.zig");
7const Blake3 = std.crypto.Blake3;
7const Blake3 = std.crypto.hash.Blake3;
88const fs = std.fs;
99const base64 = std.base64;
1010const ArrayList = std.ArrayList;
lib/std/crypto.zig+71-58
......@@ -3,60 +3,68 @@
33// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
44// The MIT license requires this copyright notice to be included in all copies
55// and substantial portions of the software.
6pub const Md5 = @import("crypto/md5.zig").Md5;
7pub const Sha1 = @import("crypto/sha1.zig").Sha1;
8
9const sha2 = @import("crypto/sha2.zig");
10pub const Sha224 = sha2.Sha224;
11pub const Sha256 = sha2.Sha256;
12pub const Sha384 = sha2.Sha384;
13pub const Sha512 = sha2.Sha512;
14
15const sha3 = @import("crypto/sha3.zig");
16pub const Sha3_224 = sha3.Sha3_224;
17pub const Sha3_256 = sha3.Sha3_256;
18pub const Sha3_384 = sha3.Sha3_384;
19pub const Sha3_512 = sha3.Sha3_512;
20
21pub const gimli = @import("crypto/gimli.zig");
22
23const blake2 = @import("crypto/blake2.zig");
24pub const Blake2s224 = blake2.Blake2s224;
25pub const Blake2s256 = blake2.Blake2s256;
26pub const Blake2b384 = blake2.Blake2b384;
27pub const Blake2b512 = blake2.Blake2b512;
28
29pub const Blake3 = @import("crypto/blake3.zig").Blake3;
30
31const hmac = @import("crypto/hmac.zig");
32pub const HmacMd5 = hmac.HmacMd5;
33pub const HmacSha1 = hmac.HmacSha1;
34pub const HmacSha256 = hmac.HmacSha256;
35pub const HmacBlake2s256 = hmac.HmacBlake2s256;
36
37pub const chacha20 = @import("crypto/chacha20.zig");
38pub const chaCha20IETF = chacha20.chaCha20IETF;
39pub const chaCha20With64BitNonce = chacha20.chaCha20With64BitNonce;
40pub const xChaCha20IETF = chacha20.xChaCha20IETF;
41
42pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;
43
44const import_aes = @import("crypto/aes.zig");
45pub const AES128 = import_aes.AES128;
46pub const AES256 = import_aes.AES256;
47
48pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
49pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519;
50pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;
51pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
52pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
536
7/// Hash functions.
8pub const hash = struct {
9 pub const Md5 = @import("crypto/md5.zig").Md5;
10 pub const Sha1 = @import("crypto/sha1.zig").Sha1;
11 pub const sha2 = @import("crypto/sha2.zig");
12 pub const sha3 = @import("crypto/sha3.zig");
13 pub const blake2 = @import("crypto/blake2.zig");
14 pub const Blake3 = @import("crypto/blake3.zig").Blake3;
15 pub const Gimli = @import("crypto/gimli.zig").Hash;
16};
17
18/// Authentication (MAC) functions.
19pub const auth = struct {
20 pub const hmac = @import("crypto/hmac.zig");
21};
22
23/// Authenticated Encryption with Associated Data
5424pub const aead = struct {
55 pub const Gimli = gimli.Aead;
25 const chacha20 = @import("crypto/chacha20.zig");
26
27 pub const Gimli = @import("crypto/gimli.zig").Aead;
5628 pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305;
5729 pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305;
5830};
5931
32/// MAC functions requiring single-use secret keys.
33pub const onetimeauth = struct {
34 pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;
35};
36
37/// Core functions, that should rarely be used directly by applications.
38pub const core = struct {
39 pub const aes = @import("crypto/aes.zig");
40 pub const Gimli = @import("crypto/gimli.zig").State;
41};
42
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};
49
50/// Diffie-Hellman key exchange functions.
51pub const dh = struct {
52 pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
53};
54
55/// Digital signature functions.
56pub const sign = struct {
57 pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519;
58};
59
60/// Stream ciphers. These do not provide any kind of authentication.
61/// Most applications should be using AEAD constructions instead of stream ciphers directly.
62pub const stream = struct {
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;
66};
67
6068const std = @import("std.zig");
6169pub const randomBytes = std.os.getrandom;
6270
......@@ -83,16 +91,21 @@ test "crypto" {
8391
8492test "issue #4532: no index out of bounds" {
8593 const types = [_]type{
86 Md5,
87 Sha1,
88 Sha224,
89 Sha256,
90 Sha384,
91 Sha512,
92 Blake2s224,
93 Blake2s256,
94 Blake2b384,
95 Blake2b512,
94 hash.Md5,
95 hash.Sha1,
96 hash.sha2.Sha224,
97 hash.sha2.Sha256,
98 hash.sha2.Sha384,
99 hash.sha2.Sha512,
100 hash.sha3.Sha3_224,
101 hash.sha3.Sha3_256,
102 hash.sha3.Sha3_384,
103 hash.sha3.Sha3_512,
104 hash.blake2.Blake2s224,
105 hash.blake2.Blake2s256,
106 hash.blake2.Blake2b384,
107 hash.blake2.Blake2b512,
108 hash.Gimli,
96109 };
97110
98111 inline for (types) |Hasher| {
lib/std/crypto/25519/ed25519.zig+1-1
......@@ -6,7 +6,7 @@
66const std = @import("std");
77const fmt = std.fmt;
88const mem = std.mem;
9const Sha512 = std.crypto.Sha512;
9const Sha512 = std.crypto.hash.sha2.Sha512;
1010
1111/// Ed25519 (EdDSA) signatures.
1212pub const Ed25519 = struct {
lib/std/crypto/benchmark.zig+17-16
......@@ -22,16 +22,16 @@ const Crypto = struct {
2222};
2323
2424const hashes = [_]Crypto{
25 Crypto{ .ty = crypto.Md5, .name = "md5" },
26 Crypto{ .ty = crypto.Sha1, .name = "sha1" },
27 Crypto{ .ty = crypto.Sha256, .name = "sha256" },
28 Crypto{ .ty = crypto.Sha512, .name = "sha512" },
29 Crypto{ .ty = crypto.Sha3_256, .name = "sha3-256" },
30 Crypto{ .ty = crypto.Sha3_512, .name = "sha3-512" },
31 Crypto{ .ty = crypto.gimli.Hash, .name = "gimli-hash" },
32 Crypto{ .ty = crypto.Blake2s256, .name = "blake2s" },
33 Crypto{ .ty = crypto.Blake2b512, .name = "blake2b" },
34 Crypto{ .ty = crypto.Blake3, .name = "blake3" },
25 Crypto{ .ty = crypto.hash.Md5, .name = "md5" },
26 Crypto{ .ty = crypto.hash.Sha1, .name = "sha1" },
27 Crypto{ .ty = crypto.hash.sha2.Sha256, .name = "sha256" },
28 Crypto{ .ty = crypto.hash.sha2.Sha512, .name = "sha512" },
29 Crypto{ .ty = crypto.hash.sha3.Sha3_256, .name = "sha3-256" },
30 Crypto{ .ty = crypto.hash.sha3.Sha3_512, .name = "sha3-512" },
31 Crypto{ .ty = crypto.hash.Gimli, .name = "gimli-hash" },
32 Crypto{ .ty = crypto.hash.blake2.Blake2s256, .name = "blake2s" },
33 Crypto{ .ty = crypto.hash.blake2.Blake2b512, .name = "blake2b" },
34 Crypto{ .ty = crypto.hash.Blake3, .name = "blake3" },
3535};
3636
3737pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 {
......@@ -55,10 +55,11 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64
5555}
5656
5757const macs = [_]Crypto{
58 Crypto{ .ty = crypto.Poly1305, .name = "poly1305" },
59 Crypto{ .ty = crypto.HmacMd5, .name = "hmac-md5" },
60 Crypto{ .ty = crypto.HmacSha1, .name = "hmac-sha1" },
61 Crypto{ .ty = crypto.HmacSha256, .name = "hmac-sha256" },
58 Crypto{ .ty = crypto.onetimeauth.Poly1305, .name = "poly1305" },
59 Crypto{ .ty = crypto.auth.HmacMd5, .name = "hmac-md5" },
60 Crypto{ .ty = crypto.auth.HmacSha1, .name = "hmac-sha1" },
61 Crypto{ .ty = crypto.auth.sha2.HmacSha256, .name = "hmac-sha256" },
62 Crypto{ .ty = crypto.auth.sha2.HmacSha512, .name = "hmac-sha512" },
6263};
6364
6465pub 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 {
8485 return throughput;
8586}
8687
87const exchanges = [_]Crypto{Crypto{ .ty = crypto.X25519, .name = "x25519" }};
88const exchanges = [_]Crypto{Crypto{ .ty = crypto.dh.X25519, .name = "x25519" }};
8889
8990pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_count: comptime_int) !u64 {
9091 std.debug.assert(DhKeyExchange.minimum_key_length >= DhKeyExchange.secret_length);
......@@ -111,7 +112,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c
111112 return throughput;
112113}
113114
114const signatures = [_]Crypto{Crypto{ .ty = crypto.Ed25519, .name = "ed25519" }};
115const signatures = [_]Crypto{Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" }};
115116
116117pub fn benchmarkSignatures(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {
117118 var seed: [Signature.seed_length]u8 = undefined;
lib/std/crypto/chacha20.zig+74-68
......@@ -12,7 +12,7 @@ const assert = std.debug.assert;
1212const testing = std.testing;
1313const builtin = @import("builtin");
1414const maxInt = std.math.maxInt;
15const Poly1305 = std.crypto.Poly1305;
15const Poly1305 = std.crypto.onetimeauth.Poly1305;
1616
1717const QuarterRound = struct {
1818 a: usize,
......@@ -137,56 +137,60 @@ fn keyToWords(key: [32]u8) [8]u32 {
137137///
138138/// ChaCha20 is self-reversing. To decrypt just run the cipher with the same
139139/// counter, nonce, and key.
140pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [12]u8) void {
141 assert(in.len >= out.len);
142 assert((in.len >> 6) + counter <= maxInt(u32));
143
144 var c: [4]u32 = undefined;
145 c[0] = counter;
146 c[1] = mem.readIntLittle(u32, nonce[0..4]);
147 c[2] = mem.readIntLittle(u32, nonce[4..8]);
148 c[3] = mem.readIntLittle(u32, nonce[8..12]);
149 chaCha20_internal(out, in, keyToWords(key), c);
150}
140pub const ChaCha20IETF = struct {
141 pub fn xor(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [12]u8) void {
142 assert(in.len >= out.len);
143 assert((in.len >> 6) + counter <= maxInt(u32));
144
145 var c: [4]u32 = undefined;
146 c[0] = counter;
147 c[1] = mem.readIntLittle(u32, nonce[0..4]);
148 c[2] = mem.readIntLittle(u32, nonce[4..8]);
149 c[3] = mem.readIntLittle(u32, nonce[8..12]);
150 chaCha20_internal(out, in, keyToWords(key), c);
151 }
152};
151153
152154/// This is the original ChaCha20 before RFC 7539, which recommends using the
153155/// orgininal version on applications such as disk or file encryption that might
154156/// 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 {
156 assert(in.len >= out.len);
157 assert(counter +% (in.len >> 6) >= counter);
158
159 var cursor: usize = 0;
160 const k = keyToWords(key);
161 var c: [4]u32 = undefined;
162 c[0] = @truncate(u32, counter);
163 c[1] = @truncate(u32, counter >> 32);
164 c[2] = mem.readIntLittle(u32, nonce[0..4]);
165 c[3] = mem.readIntLittle(u32, nonce[4..8]);
166
167 const block_size = (1 << 6);
168 // The full block size is greater than the address space on a 32bit machine
169 const big_block = if (@sizeOf(usize) > 4) (block_size << 32) else maxInt(usize);
170
171 // first partial big block
172 if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) {
173 chaCha20_internal(out[cursor..big_block], in[cursor..big_block], k, c);
174 cursor = big_block - cursor;
175 c[1] += 1;
176 if (comptime @sizeOf(usize) > 4) {
177 // A big block is giant: 256 GiB, but we can avoid this limitation
178 var remaining_blocks: u32 = @intCast(u32, (in.len / big_block));
179 var i: u32 = 0;
180 while (remaining_blocks > 0) : (remaining_blocks -= 1) {
181 chaCha20_internal(out[cursor .. cursor + big_block], in[cursor .. cursor + big_block], k, c);
182 c[1] += 1; // upper 32-bit of counter, generic chaCha20_internal() doesn't know about this.
183 cursor += big_block;
157pub const ChaCha20With64BitNonce = struct {
158 pub fn xor(out: []u8, in: []const u8, counter: u64, key: [32]u8, nonce: [8]u8) void {
159 assert(in.len >= out.len);
160 assert(counter +% (in.len >> 6) >= counter);
161
162 var cursor: usize = 0;
163 const k = keyToWords(key);
164 var c: [4]u32 = undefined;
165 c[0] = @truncate(u32, counter);
166 c[1] = @truncate(u32, counter >> 32);
167 c[2] = mem.readIntLittle(u32, nonce[0..4]);
168 c[3] = mem.readIntLittle(u32, nonce[4..8]);
169
170 const block_size = (1 << 6);
171 // The full block size is greater than the address space on a 32bit machine
172 const big_block = if (@sizeOf(usize) > 4) (block_size << 32) else maxInt(usize);
173
174 // first partial big block
175 if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) {
176 chaCha20_internal(out[cursor..big_block], in[cursor..big_block], k, c);
177 cursor = big_block - cursor;
178 c[1] += 1;
179 if (comptime @sizeOf(usize) > 4) {
180 // A big block is giant: 256 GiB, but we can avoid this limitation
181 var remaining_blocks: u32 = @intCast(u32, (in.len / big_block));
182 var i: u32 = 0;
183 while (remaining_blocks > 0) : (remaining_blocks -= 1) {
184 chaCha20_internal(out[cursor .. cursor + big_block], in[cursor .. cursor + big_block], k, c);
185 c[1] += 1; // upper 32-bit of counter, generic chaCha20_internal() doesn't know about this.
186 cursor += big_block;
187 }
184188 }
185189 }
186 }
187190
188 chaCha20_internal(out[cursor..], in[cursor..], k, c);
189}
191 chaCha20_internal(out[cursor..], in[cursor..], k, c);
192 }
193};
190194
191195// https://tools.ietf.org/html/rfc7539#section-2.4.2
192196test "crypto.chacha20 test vector sunscreen" {
......@@ -221,12 +225,12 @@ test "crypto.chacha20 test vector sunscreen" {
221225 0, 0, 0, 0,
222226 };
223227
224 chaCha20IETF(result[0..], input[0..], 1, key, nonce);
228 ChaCha20IETF.xor(result[0..], input[0..], 1, key, nonce);
225229 testing.expectEqualSlices(u8, &expected_result, &result);
226230
227231 // Chacha20 is self-reversing.
228232 var plaintext: [114]u8 = undefined;
229 chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce);
233 ChaCha20IETF.xor(plaintext[0..], result[0..], 1, key, nonce);
230234 testing.expect(mem.order(u8, input, &plaintext) == .eq);
231235}
232236
......@@ -261,7 +265,7 @@ test "crypto.chacha20 test vector 1" {
261265 };
262266 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);
265269 testing.expectEqualSlices(u8, &expected_result, &result);
266270}
267271
......@@ -295,7 +299,7 @@ test "crypto.chacha20 test vector 2" {
295299 };
296300 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);
299303 testing.expectEqualSlices(u8, &expected_result, &result);
300304}
301305
......@@ -329,7 +333,7 @@ test "crypto.chacha20 test vector 3" {
329333 };
330334 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);
333337 testing.expectEqualSlices(u8, &expected_result, &result);
334338}
335339
......@@ -363,7 +367,7 @@ test "crypto.chacha20 test vector 4" {
363367 };
364368 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);
367371 testing.expectEqualSlices(u8, &expected_result, &result);
368372}
369373
......@@ -435,21 +439,21 @@ test "crypto.chacha20 test vector 5" {
435439 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
436440 };
437441
438 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
442 ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce);
439443 testing.expectEqualSlices(u8, &expected_result, &result);
440444}
441445
442446pub 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 {
445449 assert(ciphertext.len >= plaintext.len);
446450
447451 // derive poly1305 key
448452 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
451455 // encrypt plaintext
452 chaCha20IETF(ciphertext[0..plaintext.len], plaintext, 1, key, nonce);
456 ChaCha20IETF.xor(ciphertext[0..plaintext.len], plaintext, 1, key, nonce);
453457
454458 // construct mac
455459 var mac = Poly1305.init(polyKey[0..]);
......@@ -472,18 +476,18 @@ pub fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_ta
472476 mac.final(tag);
473477}
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 {
476480 return chacha20poly1305SealDetached(ciphertextAndTag[0..plaintext.len], ciphertextAndTag[plaintext.len..][0..chacha20poly1305_tag_size], plaintext, data, key, nonce);
477481}
478482
479483/// 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 {
481485 // split ciphertext and tag
482486 assert(dst.len >= ciphertext.len);
483487
484488 // derive poly1305 key
485489 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
488492 // construct mac
489493 var mac = Poly1305.init(polyKey[0..]);
......@@ -519,11 +523,11 @@ pub fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *con
519523 }
520524
521525 // decrypt ciphertext
522 chaCha20IETF(dst[0..ciphertext.len], ciphertext, 1, key, nonce);
526 ChaCha20IETF.xor(dst[0..ciphertext.len], ciphertext, 1, key, nonce);
523527}
524528
525529/// 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 {
527531 if (ciphertextAndTag.len < chacha20poly1305_tag_size) {
528532 return error.InvalidMessage;
529533 }
......@@ -562,31 +566,33 @@ fn extend(key: [32]u8, nonce: [24]u8) struct { key: [32]u8, nonce: [12]u8 } {
562566 };
563567}
564568
565pub fn xChaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [24]u8) void {
566 const extended = extend(key, nonce);
567 chaCha20IETF(out, in, counter, extended.key, extended.nonce);
568}
569pub const XChaCha20IETF = struct {
570 pub fn xor(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [24]u8) void {
571 const extended = extend(key, nonce);
572 ChaCha20IETF.xor(out, in, counter, extended.key, extended.nonce);
573 }
574};
569575
570576pub 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 {
573579 const extended = extend(key, nonce);
574580 return chacha20poly1305SealDetached(ciphertext, tag, plaintext, data, extended.key, extended.nonce);
575581}
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 {
578584 const extended = extend(key, nonce);
579585 return chacha20poly1305Seal(ciphertextAndTag, plaintext, data, extended.key, extended.nonce);
580586}
581587
582588/// 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 {
584590 const extended = extend(key, nonce);
585591 return try chacha20poly1305OpenDetached(plaintext, ciphertext, tag, data, extended.key, extended.nonce);
586592}
587593
588594/// 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 {
590596 const extended = extend(key, nonce);
591597 return try chacha20poly1305Open(ciphertextAndTag, msgAndTag, data, extended.key, extended.nonce);
592598}
......@@ -714,7 +720,7 @@ test "crypto.xchacha20" {
714720 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.";
715721 {
716722 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);
718724 var buf: [2 * ciphertext.len]u8 = undefined;
719725 testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{ciphertext}), "E0A1BCF939654AFDBDC1746EC49832647C19D891F0D1A81FC0C1703B4514BDEA584B512F6908C2C5E9DD18D5CBC1805DE5803FE3B9CA5F193FB8359E91FAB0C3BB40309A292EB1CF49685C65C4A3ADF4F11DB0CD2B6B67FBC174BC2E860E8F769FD3565BBFAD1C845E05A0FED9BE167C240D");
720726 }
lib/std/crypto/gimli.zig+7-3
......@@ -109,17 +109,21 @@ pub const Hash = struct {
109109 state: State,
110110 buf_off: usize,
111111
112 pub const block_length = State.RATE;
113
112114 const Self = @This();
113115
114116 pub fn init() Self {
115117 return Self{
116 .state = State{
117 .data = [_]u32{0} ** (State.BLOCKBYTES / 4),
118 },
118 .state = State{ .data = [_]u32{0} ** (State.BLOCKBYTES / 4) },
119119 .buf_off = 0,
120120 };
121121 }
122122
123 pub fn reset(self: *Self) void {
124 self.* = init();
125 }
126
123127 /// Also known as 'absorb'
124128 pub fn update(self: *Self, data: []const u8) void {
125129 const buf = self.state.toSlice();
lib/std/crypto/hmac.zig+16-7
......@@ -8,10 +8,19 @@ const crypto = std.crypto;
88const debug = std.debug;
99const mem = std.mem;
1010
11pub const HmacMd5 = Hmac(crypto.Md5);
12pub const HmacSha1 = Hmac(crypto.Sha1);
13pub const HmacSha256 = Hmac(crypto.Sha256);
14pub const HmacBlake2s256 = Hmac(crypto.Blake2s256);
11pub const HmacMd5 = Hmac(crypto.hash.legacy.Md5);
12pub const HmacSha1 = Hmac(crypto.hash.legacy.Sha1);
13
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
1625pub fn Hmac(comptime Hash: type) type {
1726 return struct {
......@@ -95,10 +104,10 @@ test "hmac sha1" {
95104}
96105
97106test "hmac sha256" {
98 var out: [HmacSha256.mac_length]u8 = undefined;
99 HmacSha256.create(out[0..], "", "");
107 var out: [sha2.HmacSha256.mac_length]u8 = undefined;
108 sha2.HmacSha256.create(out[0..], "", "");
100109 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");
103112 htest.assertEqual("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8", out[0..]);
104113}
lib/std/crypto/md5.zig+16-10
......@@ -32,6 +32,9 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar
3232 };
3333}
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.
3538pub const Md5 = struct {
3639 const Self = @This();
3740 pub const block_length = 64;
......@@ -44,18 +47,21 @@ pub const Md5 = struct {
4447 total_len: u64,
4548
4649 pub fn init() Self {
47 var d: Self = undefined;
48 d.reset();
49 return d;
50 return Self{
51 .s = [_]u32{
52 0x67452301,
53 0xEFCDAB89,
54 0x98BADCFE,
55 0x10325476,
56 },
57 .buf = undefined,
58 .buf_len = 0,
59 .total_len = 0,
60 };
5061 }
5162
52 pub fn reset(d: *Self) void {
53 d.s[0] = 0x67452301;
54 d.s[1] = 0xEFCDAB89;
55 d.s[2] = 0x98BADCFE;
56 d.s[3] = 0x10325476;
57 d.buf_len = 0;
58 d.total_len = 0;
63 pub fn reset(self: *Self) void {
64 self.* = init();
5965 }
6066
6167 pub fn hash(b: []const u8, out: []u8) void {
lib/std/crypto/sha1.zig+17-11
......@@ -29,6 +29,9 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {
2929 };
3030}
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.
3235pub const Sha1 = struct {
3336 const Self = @This();
3437 pub const block_length = 64;
......@@ -41,19 +44,22 @@ pub const Sha1 = struct {
4144 total_len: u64,
4245
4346 pub fn init() Self {
44 var d: Self = undefined;
45 d.reset();
46 return d;
47 return Self{
48 .s = [_]u32{
49 0x67452301,
50 0xEFCDAB89,
51 0x98BADCFE,
52 0x10325476,
53 0xC3D2E1F0,
54 },
55 .buf = undefined,
56 .buf_len = 0,
57 .total_len = 0,
58 };
4759 }
4860
49 pub fn reset(d: *Self) void {
50 d.s[0] = 0x67452301;
51 d.s[1] = 0xEFCDAB89;
52 d.s[2] = 0x98BADCFE;
53 d.s[3] = 0x10325476;
54 d.s[4] = 0xC3D2E1F0;
55 d.buf_len = 0;
56 d.total_len = 0;
61 pub fn reset(self: *Self) void {
62 self.* = init();
5763 }
5864
5965 pub fn hash(b: []const u8, out: []u8) void {
lib/std/crypto/sha2.zig+17-14
......@@ -93,22 +93,25 @@ fn Sha2_32(comptime params: Sha2Params32) type {
9393 total_len: u64,
9494
9595 pub fn init() Self {
96 var d: Self = undefined;
97 d.reset();
98 return d;
96 return Self{
97 .s = [_]u32{
98 params.iv0,
99 params.iv1,
100 params.iv2,
101 params.iv3,
102 params.iv4,
103 params.iv5,
104 params.iv6,
105 params.iv7,
106 },
107 .buf = undefined,
108 .buf_len = 0,
109 .total_len = 0,
110 };
99111 }
100112
101 pub fn reset(d: *Self) void {
102 d.s[0] = params.iv0;
103 d.s[1] = params.iv1;
104 d.s[2] = params.iv2;
105 d.s[3] = params.iv3;
106 d.s[4] = params.iv4;
107 d.s[5] = params.iv5;
108 d.s[6] = params.iv6;
109 d.s[7] = params.iv7;
110 d.buf_len = 0;
111 d.total_len = 0;
113 pub fn reset(self: *Self) void {
114 self.* = init();
112115 }
113116
114117 pub fn hash(b: []const u8, out: []u8) void {
lib/std/crypto/sha3.zig+5-5
......@@ -27,14 +27,14 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {
2727
2828 pub fn init() Self {
2929 var d: Self = undefined;
30 d.reset();
31 return d;
32 }
33
34 pub fn reset(d: *Self) void {
3530 mem.set(u8, d.s[0..], 0);
3631 d.offset = 0;
3732 d.rate = 200 - (bits / 4);
33 return d;
34 }
35
36 pub fn reset(self: *Self) void {
37 self.* = init();
3838 }
3939
4040 pub fn hash(b: []const u8, out: []u8) void {
lib/std/rand.zig+2-2
......@@ -737,12 +737,12 @@ test "xoroshiro sequence" {
737737// CSPRNG
738738pub const Gimli = struct {
739739 random: Random,
740 state: std.crypto.gimli.State,
740 state: std.crypto.core.Gimli,
741741
742742 pub fn init(init_s: u64) Gimli {
743743 var self = Gimli{
744744 .random = Random{ .fillFn = fill },
745 .state = std.crypto.gimli.State{
745 .state = std.crypto.core.Gimli{
746746 .data = [_]u32{0} ** (std.crypto.gimli.State.BLOCKBYTES / 4),
747747 },
748748 };
lib/std/zig.zig+1-1
......@@ -26,7 +26,7 @@ pub fn hashSrc(src: []const u8) SrcHash {
2626 std.mem.copy(u8, &out, src);
2727 std.mem.set(u8, out[src.len..], 0);
2828 } else {
29 std.crypto.Blake3.hash(src, &out);
29 std.crypto.hash.Blake3.hash(src, &out);
3030 }
3131 return out;
3232}
tools/process_headers.zig+1-1
......@@ -313,7 +313,7 @@ pub fn main() !void {
313313 var max_bytes_saved: usize = 0;
314314 var total_bytes: usize = 0;
315315
316 var hasher = std.crypto.Sha256.init();
316 var hasher = std.crypto.hash.sha2.Sha256.init();
317317
318318 for (libc_targets) |libc_target| {
319319 const dest_target = DestTarget{