master
1//! Cryptography.
2
3const std = @import("std.zig");
4
5pub const timing_safe = @import("crypto/timing_safe.zig");
6
7/// Authenticated Encryption with Associated Data
8pub const aead = struct {
9 pub const aegis = struct {
10 const variants = @import("crypto/aegis.zig");
11
12 pub const Aegis128X4 = variants.Aegis128X4;
13 pub const Aegis128X2 = variants.Aegis128X2;
14 pub const Aegis128L = variants.Aegis128L;
15
16 pub const Aegis256X4 = variants.Aegis256X4;
17 pub const Aegis256X2 = variants.Aegis256X2;
18 pub const Aegis256 = variants.Aegis256;
19
20 pub const Aegis128X4_256 = variants.Aegis128X4_256;
21 pub const Aegis128X2_256 = variants.Aegis128X2_256;
22 pub const Aegis128L_256 = variants.Aegis128L_256;
23
24 pub const Aegis256X4_256 = variants.Aegis256X4_256;
25 pub const Aegis256X2_256 = variants.Aegis256X2_256;
26 pub const Aegis256_256 = variants.Aegis256_256;
27 };
28
29 pub const aes_gcm = struct {
30 pub const Aes128Gcm = @import("crypto/aes_gcm.zig").Aes128Gcm;
31 pub const Aes256Gcm = @import("crypto/aes_gcm.zig").Aes256Gcm;
32 };
33
34 pub const aes_gcm_siv = struct {
35 pub const Aes128GcmSiv = @import("crypto/aes_gcm_siv.zig").Aes128GcmSiv;
36 pub const Aes256GcmSiv = @import("crypto/aes_gcm_siv.zig").Aes256GcmSiv;
37 };
38
39 pub const aes_siv = struct {
40 pub const Aes128Siv = @import("crypto/aes_siv.zig").Aes128Siv;
41 pub const Aes256Siv = @import("crypto/aes_siv.zig").Aes256Siv;
42 };
43
44 pub const aes_ocb = struct {
45 pub const Aes128Ocb = @import("crypto/aes_ocb.zig").Aes128Ocb;
46 pub const Aes256Ocb = @import("crypto/aes_ocb.zig").Aes256Ocb;
47 };
48
49 pub const aes_ccm = @import("crypto/aes_ccm.zig");
50
51 pub const ascon = struct {
52 pub const AsconAead128 = @import("crypto/ascon.zig").AsconAead128;
53 };
54
55 pub const chacha_poly = struct {
56 pub const ChaCha20Poly1305 = @import("crypto/chacha20.zig").ChaCha20Poly1305;
57 pub const ChaCha12Poly1305 = @import("crypto/chacha20.zig").ChaCha12Poly1305;
58 pub const ChaCha8Poly1305 = @import("crypto/chacha20.zig").ChaCha8Poly1305;
59 pub const XChaCha20Poly1305 = @import("crypto/chacha20.zig").XChaCha20Poly1305;
60 pub const XChaCha12Poly1305 = @import("crypto/chacha20.zig").XChaCha12Poly1305;
61 pub const XChaCha8Poly1305 = @import("crypto/chacha20.zig").XChaCha8Poly1305;
62 };
63
64 pub const isap = @import("crypto/isap.zig");
65
66 pub const salsa_poly = struct {
67 pub const XSalsa20Poly1305 = @import("crypto/salsa20.zig").XSalsa20Poly1305;
68 };
69};
70
71/// Authentication (MAC) functions.
72pub const auth = struct {
73 pub const hmac = @import("crypto/hmac.zig");
74 pub const siphash = @import("crypto/siphash.zig");
75 pub const aegis = struct {
76 const variants = @import("crypto/aegis.zig");
77 pub const Aegis128X4Mac = variants.Aegis128X4Mac;
78 pub const Aegis128X2Mac = variants.Aegis128X2Mac;
79 pub const Aegis128LMac = variants.Aegis128LMac;
80
81 pub const Aegis256X4Mac = variants.Aegis256X4Mac;
82 pub const Aegis256X2Mac = variants.Aegis256X2Mac;
83 pub const Aegis256Mac = variants.Aegis256Mac;
84
85 pub const Aegis128X4Mac_128 = variants.Aegis128X4Mac_128;
86 pub const Aegis128X2Mac_128 = variants.Aegis128X2Mac_128;
87 pub const Aegis128LMac_128 = variants.Aegis128LMac_128;
88
89 pub const Aegis256X4Mac_128 = variants.Aegis256X4Mac_128;
90 pub const Aegis256X2Mac_128 = variants.Aegis256X2Mac_128;
91 pub const Aegis256Mac_128 = variants.Aegis256Mac_128;
92 };
93 pub const cmac = @import("crypto/cmac.zig");
94 pub const cbc_mac = @import("crypto/cbc_mac.zig");
95};
96
97/// Core functions, that should rarely be used directly by applications.
98pub const core = struct {
99 pub const aes = @import("crypto/aes.zig");
100 pub const keccak = @import("crypto/keccak_p.zig");
101
102 pub const Ascon = @import("crypto/ascon.zig").State;
103
104 /// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations.
105 ///
106 /// These modes are designed to be building blocks for higher-level constructions, and should generally not be used directly by applications, as they may not provide the expected properties and security guarantees.
107 ///
108 /// Most applications may want to use AEADs instead.
109 pub const modes = @import("crypto/modes.zig");
110};
111
112/// Diffie-Hellman key exchange functions.
113pub const dh = struct {
114 pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
115};
116
117/// Key Encapsulation Mechanisms.
118pub const kem = struct {
119 pub const hybrid = @import("crypto/hybrid_kem.zig");
120 pub const kyber_d00 = @import("crypto/ml_kem.zig").d00;
121 pub const ml_kem = @import("crypto/ml_kem.zig").nist;
122};
123
124/// Elliptic-curve arithmetic.
125pub const ecc = struct {
126 pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
127 pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;
128 pub const P256 = @import("crypto/pcurves/p256.zig").P256;
129 pub const P384 = @import("crypto/pcurves/p384.zig").P384;
130 pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
131 pub const Secp256k1 = @import("crypto/pcurves/secp256k1.zig").Secp256k1;
132};
133
134/// Hash functions.
135pub const hash = struct {
136 pub const ascon = struct {
137 const variants = @import("crypto/ascon.zig");
138 pub const AsconHash256 = variants.AsconHash256;
139 pub const AsconXof128 = variants.AsconXof128;
140 pub const AsconCxof128 = variants.AsconCxof128;
141 };
142 pub const blake2 = @import("crypto/blake2.zig");
143 pub const Blake3 = @import("crypto/blake3.zig").Blake3;
144 pub const Md5 = @import("crypto/md5.zig").Md5;
145 pub const Sha1 = @import("crypto/Sha1.zig");
146 pub const sha2 = @import("crypto/sha2.zig");
147 pub const sha3 = @import("crypto/sha3.zig");
148 pub const composition = @import("crypto/hash_composition.zig");
149};
150
151/// Key derivation functions.
152pub const kdf = struct {
153 pub const hkdf = @import("crypto/hkdf.zig");
154};
155
156/// MAC functions requiring single-use secret keys.
157pub const onetimeauth = struct {
158 pub const Ghash = @import("crypto/ghash_polyval.zig").Ghash;
159 pub const Polyval = @import("crypto/ghash_polyval.zig").Polyval;
160 pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;
161};
162
163/// A password hashing function derives a uniform key from low-entropy input material such as passwords.
164/// It is intentionally slow or expensive.
165///
166/// With the standard definition of a key derivation function, if a key space is small, an exhaustive search may be practical.
167/// Password hashing functions make exhaustive searches way slower or way more expensive, even when implemented on GPUs and ASICs, by using different, optionally combined strategies:
168///
169/// - Requiring a lot of computation cycles to complete
170/// - Requiring a lot of memory to complete
171/// - Requiring multiple CPU cores to complete
172/// - Requiring cache-local data to complete in reasonable time
173/// - Requiring large static tables
174/// - Avoiding precomputations and time/memory tradeoffs
175/// - Requiring multi-party computations
176/// - Combining the input material with random per-entry data (salts), application-specific contexts and keys
177///
178/// Password hashing functions must be used whenever sensitive data has to be directly derived from a password.
179pub const pwhash = struct {
180 pub const Encoding = enum {
181 phc,
182 crypt,
183 };
184
185 pub const Error = HasherError || error{AllocatorRequired};
186 pub const HasherError = KdfError || phc_format.Error;
187 pub const KdfError = errors.Error || std.mem.Allocator.Error || std.Thread.SpawnError;
188
189 pub const argon2 = @import("crypto/argon2.zig");
190 pub const bcrypt = @import("crypto/bcrypt.zig");
191 pub const scrypt = @import("crypto/scrypt.zig");
192 pub const pbkdf2 = @import("crypto/pbkdf2.zig").pbkdf2;
193
194 pub const phc_format = @import("crypto/phc_encoding.zig");
195};
196
197/// Digital signature functions.
198pub const sign = struct {
199 pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519;
200 pub const ecdsa = @import("crypto/ecdsa.zig");
201 pub const mldsa = @import("crypto/ml_dsa.zig");
202};
203
204/// Stream ciphers. These do not provide any kind of authentication.
205/// Most applications should be using AEAD constructions instead of stream ciphers directly.
206pub const stream = struct {
207 pub const chacha = struct {
208 pub const ChaCha20IETF = @import("crypto/chacha20.zig").ChaCha20IETF;
209 pub const ChaCha12IETF = @import("crypto/chacha20.zig").ChaCha12IETF;
210 pub const ChaCha8IETF = @import("crypto/chacha20.zig").ChaCha8IETF;
211 pub const ChaCha20With64BitNonce = @import("crypto/chacha20.zig").ChaCha20With64BitNonce;
212 pub const ChaCha12With64BitNonce = @import("crypto/chacha20.zig").ChaCha12With64BitNonce;
213 pub const ChaCha8With64BitNonce = @import("crypto/chacha20.zig").ChaCha8With64BitNonce;
214 pub const XChaCha20IETF = @import("crypto/chacha20.zig").XChaCha20IETF;
215 pub const XChaCha12IETF = @import("crypto/chacha20.zig").XChaCha12IETF;
216 pub const XChaCha8IETF = @import("crypto/chacha20.zig").XChaCha8IETF;
217 };
218
219 pub const salsa = struct {
220 pub const Salsa = @import("crypto/salsa20.zig").Salsa;
221 pub const XSalsa = @import("crypto/salsa20.zig").XSalsa;
222 pub const Salsa20 = @import("crypto/salsa20.zig").Salsa20;
223 pub const XSalsa20 = @import("crypto/salsa20.zig").XSalsa20;
224 };
225};
226
227pub const nacl = struct {
228 const salsa20 = @import("crypto/salsa20.zig");
229
230 pub const Box = salsa20.Box;
231 pub const SecretBox = salsa20.SecretBox;
232 pub const SealedBox = salsa20.SealedBox;
233};
234
235/// Finite-field arithmetic.
236pub const ff = @import("crypto/ff.zig");
237
238/// This is a thread-local, cryptographically secure pseudo random number generator.
239pub const random = @import("crypto/tlcsprng.zig").interface;
240
241/// Encoding and decoding
242pub const codecs = @import("crypto/codecs.zig");
243
244pub const errors = @import("crypto/errors.zig");
245
246pub const tls = @import("crypto/tls.zig");
247pub const Certificate = @import("crypto/Certificate.zig");
248
249/// Side-channels mitigations.
250pub const SideChannelsMitigations = enum {
251 /// No additional side-channel mitigations are applied.
252 /// This is the fastest mode.
253 none,
254 /// The `basic` mode protects against most practical attacks, provided that the
255 /// application or implements proper defenses against brute-force attacks.
256 /// It offers a good balance between performance and security.
257 basic,
258 /// The `medium` mode offers increased resilience against side-channel attacks,
259 /// making most attacks unpractical even on shared/low latency environements.
260 /// This is the default mode.
261 medium,
262 /// The `full` mode offers the highest level of protection against side-channel attacks.
263 /// Note that this doesn't cover all possible attacks (especially power analysis or
264 /// thread-local attacks such as cachebleed), and that the performance impact is significant.
265 full,
266};
267
268pub const default_side_channels_mitigations = .medium;
269
270test {
271 _ = aead.ascon.AsconAead128;
272
273 _ = aead.aegis.Aegis128L;
274 _ = aead.aegis.Aegis256;
275
276 _ = aead.aes_gcm.Aes128Gcm;
277 _ = aead.aes_gcm.Aes256Gcm;
278
279 _ = aead.aes_gcm_siv.Aes128GcmSiv;
280 _ = aead.aes_gcm_siv.Aes256GcmSiv;
281
282 _ = aead.aes_siv.Aes128Siv;
283 _ = aead.aes_siv.Aes256Siv;
284
285 _ = aead.aes_ocb.Aes128Ocb;
286 _ = aead.aes_ocb.Aes256Ocb;
287
288 _ = aead.chacha_poly.ChaCha20Poly1305;
289 _ = aead.chacha_poly.ChaCha12Poly1305;
290 _ = aead.chacha_poly.ChaCha8Poly1305;
291 _ = aead.chacha_poly.XChaCha20Poly1305;
292 _ = aead.chacha_poly.XChaCha12Poly1305;
293 _ = aead.chacha_poly.XChaCha8Poly1305;
294
295 _ = aead.isap;
296 _ = aead.salsa_poly.XSalsa20Poly1305;
297
298 _ = auth.hmac;
299 _ = auth.cmac;
300 _ = auth.siphash;
301
302 _ = core.aes;
303 _ = core.Ascon;
304 _ = core.modes;
305
306 _ = dh.X25519;
307
308 _ = kem.kyber_d00;
309
310 _ = ecc.Curve25519;
311 _ = ecc.Edwards25519;
312 _ = ecc.P256;
313 _ = ecc.P384;
314 _ = ecc.Ristretto255;
315 _ = ecc.Secp256k1;
316
317 _ = hash.ascon;
318 _ = hash.blake2;
319 _ = hash.Blake3;
320 _ = hash.Md5;
321 _ = hash.Sha1;
322 _ = hash.sha2;
323 _ = hash.sha3;
324 _ = hash.composition;
325
326 _ = kdf.hkdf;
327
328 _ = onetimeauth.Ghash;
329 _ = onetimeauth.Poly1305;
330
331 _ = pwhash.Encoding;
332
333 _ = pwhash.Error;
334 _ = pwhash.HasherError;
335 _ = pwhash.KdfError;
336
337 _ = pwhash.argon2;
338 _ = pwhash.bcrypt;
339 _ = pwhash.scrypt;
340 _ = pwhash.pbkdf2;
341
342 _ = pwhash.phc_format;
343
344 _ = sign.Ed25519;
345 _ = sign.ecdsa;
346
347 _ = stream.chacha.ChaCha20IETF;
348 _ = stream.chacha.ChaCha12IETF;
349 _ = stream.chacha.ChaCha8IETF;
350 _ = stream.chacha.ChaCha20With64BitNonce;
351 _ = stream.chacha.ChaCha12With64BitNonce;
352 _ = stream.chacha.ChaCha8With64BitNonce;
353 _ = stream.chacha.XChaCha20IETF;
354 _ = stream.chacha.XChaCha12IETF;
355 _ = stream.chacha.XChaCha8IETF;
356
357 _ = stream.salsa.Salsa20;
358 _ = stream.salsa.XSalsa20;
359
360 _ = nacl.Box;
361 _ = nacl.SecretBox;
362 _ = nacl.SealedBox;
363
364 _ = secureZero;
365 _ = timing_safe;
366 _ = ff;
367 _ = random;
368 _ = errors;
369 _ = tls;
370 _ = Certificate;
371 _ = codecs;
372}
373
374test "CSPRNG" {
375 const a = random.int(u64);
376 const b = random.int(u64);
377 const c = random.int(u64);
378 try std.testing.expect(a ^ b ^ c != 0);
379}
380
381test "issue #4532: no index out of bounds" {
382 const types = [_]type{
383 hash.Md5,
384 hash.Sha1,
385 hash.sha2.Sha224,
386 hash.sha2.Sha256,
387 hash.sha2.Sha384,
388 hash.sha2.Sha512,
389 hash.sha3.Sha3_224,
390 hash.sha3.Sha3_256,
391 hash.sha3.Sha3_384,
392 hash.sha3.Sha3_512,
393 hash.blake2.Blake2s128,
394 hash.blake2.Blake2s224,
395 hash.blake2.Blake2s256,
396 hash.blake2.Blake2b128,
397 hash.blake2.Blake2b256,
398 hash.blake2.Blake2b384,
399 hash.blake2.Blake2b512,
400 };
401
402 inline for (types) |Hasher| {
403 var block = [_]u8{'#'} ** Hasher.block_length;
404 var out1: [Hasher.digest_length]u8 = undefined;
405 var out2: [Hasher.digest_length]u8 = undefined;
406 const h0 = Hasher.init(.{});
407 var h = h0;
408 h.update(block[0..]);
409 h.final(&out1);
410 h = h0;
411 h.update(block[0..1]);
412 h.update(block[1..]);
413 h.final(&out2);
414
415 try std.testing.expectEqual(out1, out2);
416 }
417}
418
419/// Sets a slice to zeroes.
420/// Prevents the store from being optimized out.
421pub fn secureZero(comptime T: type, s: []volatile T) void {
422 @memset(s, 0);
423}
424
425test secureZero {
426 var a = [_]u8{0xfe} ** 8;
427 var b = [_]u8{0xfe} ** 8;
428
429 @memset(&a, 0);
430 secureZero(u8, &b);
431
432 try std.testing.expectEqualSlices(u8, &a, &b);
433}