| author | |
| committer | |
| log | 1f1381a866a110953f9950d8c0c6497a2567daa0 |
| tree | 458e258f1ea98c691ebbd41b353c65b676b4ff8a |
| parent | 81a35a86ea9385016f371213a2b72b14902bb955 |
45 files changed, 514 insertions(+), 336 deletions(-)
lib/compiler/aro/aro/Driver.zig+2-1| ... | @@ -1217,11 +1217,12 @@ pub fn getDepFileName(d: *Driver, source: Source, buf: *[std.fs.max_name_bytes]u | ... | @@ -1217,11 +1217,12 @@ pub fn getDepFileName(d: *Driver, source: Source, buf: *[std.fs.max_name_bytes]u |
| 1217 | } | 1217 | } |
| 1218 | 1218 | ||
| 1219 | fn getRandomFilename(d: *Driver, buf: *[std.fs.max_name_bytes]u8, extension: []const u8) ![]const u8 { | 1219 | fn getRandomFilename(d: *Driver, buf: *[std.fs.max_name_bytes]u8, extension: []const u8) ![]const u8 { |
| 1220 | const io = d.comp.io; | ||
| 1220 | const random_bytes_count = 12; | 1221 | const random_bytes_count = 12; |
| 1221 | const sub_path_len = comptime std.fs.base64_encoder.calcSize(random_bytes_count); | 1222 | const sub_path_len = comptime std.fs.base64_encoder.calcSize(random_bytes_count); |
| 1222 | 1223 | ||
| 1223 | var random_bytes: [random_bytes_count]u8 = undefined; | 1224 | var random_bytes: [random_bytes_count]u8 = undefined; |
| 1224 | std.crypto.random.bytes(&random_bytes); | 1225 | io.random(&random_bytes); |
| 1225 | var random_name: [sub_path_len]u8 = undefined; | 1226 | var random_name: [sub_path_len]u8 = undefined; |
| 1226 | _ = std.fs.base64_encoder.encode(&random_name, &random_bytes); | 1227 | _ = std.fs.base64_encoder.encode(&random_name, &random_bytes); |
| 1227 | 1228 |
lib/std/Io/Threaded.zig+49-16| ... | @@ -78,7 +78,7 @@ pub const Csprng = struct { | ... | @@ -78,7 +78,7 @@ pub const Csprng = struct { |
| 78 | pub const seed_len = std.Random.DefaultCsprng.secret_seed_length; | 78 | pub const seed_len = std.Random.DefaultCsprng.secret_seed_length; |
| 79 | 79 | ||
| 80 | pub fn isInitialized(c: *const Csprng) bool { | 80 | pub fn isInitialized(c: *const Csprng) bool { |
| 81 | return c.rng.offset == std.math.maxInt(usize); | 81 | return c.rng.offset != std.math.maxInt(usize); |
| 82 | } | 82 | } |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| ... | @@ -2395,11 +2395,11 @@ fn dirCreateDirPath( | ... | @@ -2395,11 +2395,11 @@ fn dirCreateDirPath( |
| 2395 | status = .created; | 2395 | status = .created; |
| 2396 | } else |err| switch (err) { | 2396 | } else |err| switch (err) { |
| 2397 | error.PathAlreadyExists => { | 2397 | error.PathAlreadyExists => { |
| 2398 | // stat the file and return an error if it's not a directory | 2398 | // It is important to return an error if it's not a directory |
| 2399 | // this is important because otherwise a dangling symlink | 2399 | // because otherwise a dangling symlink could cause an infinite |
| 2400 | // could cause an infinite loop | 2400 | // loop. |
| 2401 | const fstat = try dirStatFile(t, dir, component.path, .{}); | 2401 | const kind = try filePathKind(t, dir, component.path); |
| 2402 | if (fstat.kind != .directory) return error.NotDir; | 2402 | if (kind != .directory) return error.NotDir; |
| 2403 | }, | 2403 | }, |
| 2404 | error.FileNotFound => |e| { | 2404 | error.FileNotFound => |e| { |
| 2405 | component = it.previous() orelse return e; | 2405 | component = it.previous() orelse return e; |
| ... | @@ -2740,6 +2740,35 @@ fn dirStatFileWasi( | ... | @@ -2740,6 +2740,35 @@ fn dirStatFileWasi( |
| 2740 | } | 2740 | } |
| 2741 | } | 2741 | } |
| 2742 | 2742 | ||
| 2743 | fn filePathKind(t: *Threaded, dir: Dir, sub_path: []const u8) !File.Kind { | ||
| 2744 | if (native_os == .linux) { | ||
| 2745 | var path_buffer: [posix.PATH_MAX]u8 = undefined; | ||
| 2746 | const sub_path_posix = try pathToPosix(sub_path, &path_buffer); | ||
| 2747 | |||
| 2748 | const linux = std.os.linux; | ||
| 2749 | const syscall: Syscall = try .start(); | ||
| 2750 | while (true) { | ||
| 2751 | var statx = std.mem.zeroes(linux.Statx); | ||
| 2752 | switch (linux.errno(linux.statx(dir.handle, sub_path_posix, 0, .{ .TYPE = true }, &statx))) { | ||
| 2753 | .SUCCESS => { | ||
| 2754 | syscall.finish(); | ||
| 2755 | if (!statx.mask.TYPE) return error.Unexpected; | ||
| 2756 | return statxKind(statx.mode); | ||
| 2757 | }, | ||
| 2758 | .INTR => { | ||
| 2759 | try syscall.checkCancel(); | ||
| 2760 | continue; | ||
| 2761 | }, | ||
| 2762 | .NOMEM => return syscall.fail(error.SystemResources), | ||
| 2763 | else => |err| return syscall.unexpectedErrno(err), | ||
| 2764 | } | ||
| 2765 | } | ||
| 2766 | } | ||
| 2767 | |||
| 2768 | const stat = try dirStatFile(t, dir, sub_path, .{}); | ||
| 2769 | return stat.kind; | ||
| 2770 | } | ||
| 2771 | |||
| 2743 | fn fileLength(userdata: ?*anyopaque, file: File) File.LengthError!u64 { | 2772 | fn fileLength(userdata: ?*anyopaque, file: File) File.LengthError!u64 { |
| 2744 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2773 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2745 | 2774 | ||
| ... | @@ -12310,16 +12339,7 @@ fn statFromLinux(stx: *const std.os.linux.Statx) Io.UnexpectedError!File.Stat { | ... | @@ -12310,16 +12339,7 @@ fn statFromLinux(stx: *const std.os.linux.Statx) Io.UnexpectedError!File.Stat { |
| 12310 | .nlink = stx.nlink, | 12339 | .nlink = stx.nlink, |
| 12311 | .size = stx.size, | 12340 | .size = stx.size, |
| 12312 | .permissions = .fromMode(stx.mode), | 12341 | .permissions = .fromMode(stx.mode), |
| 12313 | .kind = switch (stx.mode & std.os.linux.S.IFMT) { | 12342 | .kind = statxKind(stx.mode), |
| 12314 | std.os.linux.S.IFDIR => .directory, | ||
| 12315 | std.os.linux.S.IFCHR => .character_device, | ||
| 12316 | std.os.linux.S.IFBLK => .block_device, | ||
| 12317 | std.os.linux.S.IFREG => .file, | ||
| 12318 | std.os.linux.S.IFIFO => .named_pipe, | ||
| 12319 | std.os.linux.S.IFLNK => .sym_link, | ||
| 12320 | std.os.linux.S.IFSOCK => .unix_domain_socket, | ||
| 12321 | else => .unknown, | ||
| 12322 | }, | ||
| 12323 | .atime = if (!stx.mask.ATIME) null else .{ | 12343 | .atime = if (!stx.mask.ATIME) null else .{ |
| 12324 | .nanoseconds = @intCast(@as(i128, stx.atime.sec) * std.time.ns_per_s + stx.atime.nsec), | 12344 | .nanoseconds = @intCast(@as(i128, stx.atime.sec) * std.time.ns_per_s + stx.atime.nsec), |
| 12325 | }, | 12345 | }, |
| ... | @@ -12328,6 +12348,19 @@ fn statFromLinux(stx: *const std.os.linux.Statx) Io.UnexpectedError!File.Stat { | ... | @@ -12328,6 +12348,19 @@ fn statFromLinux(stx: *const std.os.linux.Statx) Io.UnexpectedError!File.Stat { |
| 12328 | }; | 12348 | }; |
| 12329 | } | 12349 | } |
| 12330 | 12350 | ||
| 12351 | fn statxKind(stx_mode: u16) File.Kind { | ||
| 12352 | return switch (stx_mode & std.os.linux.S.IFMT) { | ||
| 12353 | std.os.linux.S.IFDIR => .directory, | ||
| 12354 | std.os.linux.S.IFCHR => .character_device, | ||
| 12355 | std.os.linux.S.IFBLK => .block_device, | ||
| 12356 | std.os.linux.S.IFREG => .file, | ||
| 12357 | std.os.linux.S.IFIFO => .named_pipe, | ||
| 12358 | std.os.linux.S.IFLNK => .sym_link, | ||
| 12359 | std.os.linux.S.IFSOCK => .unix_domain_socket, | ||
| 12360 | else => .unknown, | ||
| 12361 | }; | ||
| 12362 | } | ||
| 12363 | |||
| 12331 | fn statFromPosix(st: *const posix.Stat) File.Stat { | 12364 | fn statFromPosix(st: *const posix.Stat) File.Stat { |
| 12332 | const atime = st.atime(); | 12365 | const atime = st.atime(); |
| 12333 | const mtime = st.mtime(); | 12366 | const mtime = st.mtime(); |
lib/std/Io/net/test.zig+3-3| ... | @@ -275,7 +275,7 @@ test "listen on a unix socket, send bytes, receive bytes" { | ... | @@ -275,7 +275,7 @@ test "listen on a unix socket, send bytes, receive bytes" { |
| 275 | 275 | ||
| 276 | const io = testing.io; | 276 | const io = testing.io; |
| 277 | 277 | ||
| 278 | const socket_path = try generateFileName("socket.unix"); | 278 | const socket_path = try generateFileName(io, "socket.unix"); |
| 279 | defer testing.allocator.free(socket_path); | 279 | defer testing.allocator.free(socket_path); |
| 280 | 280 | ||
| 281 | const socket_addr = try net.UnixAddress.init(socket_path); | 281 | const socket_addr = try net.UnixAddress.init(socket_path); |
| ... | @@ -308,11 +308,11 @@ test "listen on a unix socket, send bytes, receive bytes" { | ... | @@ -308,11 +308,11 @@ test "listen on a unix socket, send bytes, receive bytes" { |
| 308 | try testing.expectEqualSlices(u8, "Hello world!", buf[0..n]); | 308 | try testing.expectEqualSlices(u8, "Hello world!", buf[0..n]); |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | fn generateFileName(base_name: []const u8) ![]const u8 { | 311 | fn generateFileName(io: Io, base_name: []const u8) ![]const u8 { |
| 312 | const random_bytes_count = 12; | 312 | const random_bytes_count = 12; |
| 313 | const sub_path_len = comptime std.fs.base64_encoder.calcSize(random_bytes_count); | 313 | const sub_path_len = comptime std.fs.base64_encoder.calcSize(random_bytes_count); |
| 314 | var random_bytes: [12]u8 = undefined; | 314 | var random_bytes: [12]u8 = undefined; |
| 315 | std.crypto.random.bytes(&random_bytes); | 315 | io.random(&random_bytes); |
| 316 | var sub_path: [sub_path_len]u8 = undefined; | 316 | var sub_path: [sub_path_len]u8 = undefined; |
| 317 | _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); | 317 | _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); |
| 318 | return std.fmt.allocPrint(testing.allocator, "{s}-{s}", .{ sub_path[0..], base_name }); | 318 | return std.fmt.allocPrint(testing.allocator, "{s}-{s}", .{ sub_path[0..], base_name }); |
lib/std/Io/test.zig+20-5| ... | @@ -565,13 +565,28 @@ test "tasks spawned in group after Group.cancel are canceled" { | ... | @@ -565,13 +565,28 @@ test "tasks spawned in group after Group.cancel are canceled" { |
| 565 | try group.concurrent(io, global.waitThenSpawn, .{ io, &group }); | 565 | try group.concurrent(io, global.waitThenSpawn, .{ io, &group }); |
| 566 | } | 566 | } |
| 567 | 567 | ||
| 568 | test "CSPRNG" { | 568 | test "random" { |
| 569 | const io = testing.io; | 569 | const io = testing.io; |
| 570 | 570 | ||
| 571 | var random = io.random(); | 571 | var a: u64 = undefined; |
| 572 | var b: u64 = undefined; | ||
| 573 | var c: u64 = undefined; | ||
| 574 | |||
| 575 | io.random(@ptrCast(&a)); | ||
| 576 | io.random(@ptrCast(&b)); | ||
| 577 | io.random(@ptrCast(&c)); | ||
| 572 | 578 | ||
| 573 | const a = random.int(u64); | ||
| 574 | const b = random.int(u64); | ||
| 575 | const c = random.int(u64); | ||
| 576 | try std.testing.expect(a ^ b ^ c != 0); | 579 | try std.testing.expect(a ^ b ^ c != 0); |
| 577 | } | 580 | } |
| 581 | |||
| 582 | test "randomSecure" { | ||
| 583 | const io = testing.io; | ||
| 584 | |||
| 585 | var buf_a: [50]u8 = undefined; | ||
| 586 | var buf_b: [50]u8 = undefined; | ||
| 587 | try io.randomSecure(&buf_a); | ||
| 588 | try io.randomSecure(&buf_b); | ||
| 589 | // If this test fails the chance is significantly higher that there is a bug than | ||
| 590 | // that two sets of 50 bytes were equal. | ||
| 591 | try expect(!mem.eql(u8, &buf_a, &buf_b)); | ||
| 592 | } |
lib/std/Random.zig+1-1| ... | @@ -38,7 +38,7 @@ pub const IoSource = struct { | ... | @@ -38,7 +38,7 @@ pub const IoSource = struct { |
| 38 | 38 | ||
| 39 | pub fn interface(this: *const @This()) std.Random { | 39 | pub fn interface(this: *const @This()) std.Random { |
| 40 | return .{ | 40 | return .{ |
| 41 | .ptr = this, | 41 | .ptr = @constCast(this), |
| 42 | .fillFn = fill, | 42 | .fillFn = fill, |
| 43 | }; | 43 | }; |
| 44 | } | 44 | } |
lib/std/Random/test.zig+2-1| ... | @@ -436,8 +436,9 @@ fn testRangeBias(r: Random, start: i8, end: i8, biased: bool) !void { | ... | @@ -436,8 +436,9 @@ fn testRangeBias(r: Random, start: i8, end: i8, biased: bool) !void { |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | test "CSPRNG" { | 438 | test "CSPRNG" { |
| 439 | const io = std.testing.io; | ||
| 439 | var secret_seed: [DefaultCsprng.secret_seed_length]u8 = undefined; | 440 | var secret_seed: [DefaultCsprng.secret_seed_length]u8 = undefined; |
| 440 | std.crypto.random.bytes(&secret_seed); | 441 | io.random(&secret_seed); |
| 441 | var csprng = DefaultCsprng.init(secret_seed); | 442 | var csprng = DefaultCsprng.init(secret_seed); |
| 442 | const random = csprng.random(); | 443 | const random = csprng.random(); |
| 443 | const a = random.int(u64); | 444 | const a = random.int(u64); |
lib/std/crypto.zig+4| ... | @@ -303,6 +303,9 @@ test { | ... | @@ -303,6 +303,9 @@ test { |
| 303 | _ = dh.X25519; | 303 | _ = dh.X25519; |
| 304 | 304 | ||
| 305 | _ = kem.kyber_d00; | 305 | _ = kem.kyber_d00; |
| 306 | _ = kem.hybrid; | ||
| 307 | _ = kem.kyber_d00; | ||
| 308 | _ = kem.ml_kem; | ||
| 306 | 309 | ||
| 307 | _ = ecc.Curve25519; | 310 | _ = ecc.Curve25519; |
| 308 | _ = ecc.Edwards25519; | 311 | _ = ecc.Edwards25519; |
| ... | @@ -340,6 +343,7 @@ test { | ... | @@ -340,6 +343,7 @@ test { |
| 340 | 343 | ||
| 341 | _ = sign.Ed25519; | 344 | _ = sign.Ed25519; |
| 342 | _ = sign.ecdsa; | 345 | _ = sign.ecdsa; |
| 346 | _ = sign.mldsa; | ||
| 343 | 347 | ||
| 344 | _ = stream.chacha.ChaCha20IETF; | 348 | _ = stream.chacha.ChaCha20IETF; |
| 345 | _ = stream.chacha.ChaCha12IETF; | 349 | _ = stream.chacha.ChaCha12IETF; |
lib/std/crypto/25519/ed25519.zig+32-23| ... | @@ -333,12 +333,10 @@ pub const Ed25519 = struct { | ... | @@ -333,12 +333,10 @@ pub const Ed25519 = struct { |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | /// Generate a new, random key pair. | 335 | /// Generate a new, random key pair. |
| 336 | /// | 336 | pub fn generate(io: std.Io) KeyPair { |
| 337 | /// `crypto.random.bytes` must be supported by the target. | ||
| 338 | pub fn generate() KeyPair { | ||
| 339 | var random_seed: [seed_length]u8 = undefined; | 337 | var random_seed: [seed_length]u8 = undefined; |
| 340 | while (true) { | 338 | while (true) { |
| 341 | crypto.random.bytes(&random_seed); | 339 | io.random(&random_seed); |
| 342 | return generateDeterministic(random_seed) catch { | 340 | return generateDeterministic(random_seed) catch { |
| 343 | @branchHint(.unlikely); | 341 | @branchHint(.unlikely); |
| 344 | continue; | 342 | continue; |
| ... | @@ -389,18 +387,21 @@ pub const Ed25519 = struct { | ... | @@ -389,18 +387,21 @@ pub const Ed25519 = struct { |
| 389 | 387 | ||
| 390 | /// Create a Signer, that can be used for incremental signing. | 388 | /// Create a Signer, that can be used for incremental signing. |
| 391 | /// Note that the signature is not deterministic. | 389 | /// Note that the signature is not deterministic. |
| 392 | /// The noise parameter, if set, should be something unique for each message, | 390 | pub fn signer( |
| 393 | /// such as a random nonce, or a counter. | 391 | key_pair: KeyPair, |
| 394 | pub fn signer(key_pair: KeyPair, noise: ?[noise_length]u8) (IdentityElementError || KeyMismatchError || NonCanonicalError || WeakPublicKeyError)!Signer { | 392 | /// If set, should be something unique for each message, such as a |
| 393 | /// random nonce, or a counter. | ||
| 394 | noise: ?[noise_length]u8, | ||
| 395 | /// Filled with cryptographically secure randomness. | ||
| 396 | entropy: *const [noise_length]u8, | ||
| 397 | ) (IdentityElementError || KeyMismatchError || NonCanonicalError || WeakPublicKeyError)!Signer { | ||
| 395 | if (!mem.eql(u8, &key_pair.secret_key.publicKeyBytes(), &key_pair.public_key.toBytes())) { | 398 | if (!mem.eql(u8, &key_pair.secret_key.publicKeyBytes(), &key_pair.public_key.toBytes())) { |
| 396 | return error.KeyMismatch; | 399 | return error.KeyMismatch; |
| 397 | } | 400 | } |
| 398 | const scalar_and_prefix = key_pair.secret_key.scalarAndPrefix(); | 401 | const scalar_and_prefix = key_pair.secret_key.scalarAndPrefix(); |
| 399 | var h = Sha512.init(.{}); | 402 | var h = Sha512.init(.{}); |
| 400 | h.update(&scalar_and_prefix.prefix); | 403 | h.update(&scalar_and_prefix.prefix); |
| 401 | var noise2: [noise_length]u8 = undefined; | 404 | h.update(entropy); |
| 402 | crypto.random.bytes(&noise2); | ||
| 403 | h.update(&noise2); | ||
| 404 | if (noise) |*z| { | 405 | if (noise) |*z| { |
| 405 | h.update(z); | 406 | h.update(z); |
| 406 | } | 407 | } |
| ... | @@ -420,7 +421,7 @@ pub const Ed25519 = struct { | ... | @@ -420,7 +421,7 @@ pub const Ed25519 = struct { |
| 420 | }; | 421 | }; |
| 421 | 422 | ||
| 422 | /// Verify several signatures in a single operation, much faster than verifying signatures one-by-one | 423 | /// Verify several signatures in a single operation, much faster than verifying signatures one-by-one |
| 423 | pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) (SignatureVerificationError || IdentityElementError || WeakPublicKeyError || EncodingError || NonCanonicalError)!void { | 424 | pub fn verifyBatch(io: std.Io, comptime count: usize, signature_batch: [count]BatchElement) (SignatureVerificationError || IdentityElementError || WeakPublicKeyError || EncodingError || NonCanonicalError)!void { |
| 424 | var r_batch: [count]CompressedScalar = undefined; | 425 | var r_batch: [count]CompressedScalar = undefined; |
| 425 | var s_batch: [count]CompressedScalar = undefined; | 426 | var s_batch: [count]CompressedScalar = undefined; |
| 426 | var a_batch: [count]Curve = undefined; | 427 | var a_batch: [count]Curve = undefined; |
| ... | @@ -454,7 +455,7 @@ pub const Ed25519 = struct { | ... | @@ -454,7 +455,7 @@ pub const Ed25519 = struct { |
| 454 | 455 | ||
| 455 | var z_batch: [count]Curve.scalar.CompressedScalar = undefined; | 456 | var z_batch: [count]Curve.scalar.CompressedScalar = undefined; |
| 456 | for (&z_batch) |*z| { | 457 | for (&z_batch) |*z| { |
| 457 | crypto.random.bytes(z[0..16]); | 458 | io.random(z[0..16]); |
| 458 | @memset(z[16..], 0); | 459 | @memset(z[16..], 0); |
| 459 | } | 460 | } |
| 460 | 461 | ||
| ... | @@ -587,12 +588,14 @@ test "signature" { | ... | @@ -587,12 +588,14 @@ test "signature" { |
| 587 | } | 588 | } |
| 588 | 589 | ||
| 589 | test "batch verification" { | 590 | test "batch verification" { |
| 591 | const io = std.testing.io; | ||
| 592 | |||
| 590 | for (0..16) |_| { | 593 | for (0..16) |_| { |
| 591 | const key_pair = Ed25519.KeyPair.generate(); | 594 | const key_pair = Ed25519.KeyPair.generate(io); |
| 592 | var msg1: [32]u8 = undefined; | 595 | var msg1: [32]u8 = undefined; |
| 593 | var msg2: [32]u8 = undefined; | 596 | var msg2: [32]u8 = undefined; |
| 594 | crypto.random.bytes(&msg1); | 597 | io.random(&msg1); |
| 595 | crypto.random.bytes(&msg2); | 598 | io.random(&msg2); |
| 596 | const sig1 = try key_pair.sign(&msg1, null); | 599 | const sig1 = try key_pair.sign(&msg1, null); |
| 597 | const sig2 = try key_pair.sign(&msg2, null); | 600 | const sig2 = try key_pair.sign(&msg2, null); |
| 598 | var signature_batch = [_]Ed25519.BatchElement{ | 601 | var signature_batch = [_]Ed25519.BatchElement{ |
| ... | @@ -607,10 +610,10 @@ test "batch verification" { | ... | @@ -607,10 +610,10 @@ test "batch verification" { |
| 607 | .public_key = key_pair.public_key, | 610 | .public_key = key_pair.public_key, |
| 608 | }, | 611 | }, |
| 609 | }; | 612 | }; |
| 610 | try Ed25519.verifyBatch(2, signature_batch); | 613 | try Ed25519.verifyBatch(io, 2, signature_batch); |
| 611 | 614 | ||
| 612 | signature_batch[1].sig = sig1; | 615 | signature_batch[1].sig = sig1; |
| 613 | try std.testing.expectError(error.SignatureVerificationFailed, Ed25519.verifyBatch(signature_batch.len, signature_batch)); | 616 | try std.testing.expectError(error.SignatureVerificationFailed, Ed25519.verifyBatch(io, signature_batch.len, signature_batch)); |
| 614 | } | 617 | } |
| 615 | } | 618 | } |
| 616 | 619 | ||
| ... | @@ -718,14 +721,15 @@ test "test vectors" { | ... | @@ -718,14 +721,15 @@ test "test vectors" { |
| 718 | } | 721 | } |
| 719 | 722 | ||
| 720 | test "with blind keys" { | 723 | test "with blind keys" { |
| 724 | const io = std.testing.io; | ||
| 721 | const BlindKeyPair = Ed25519.key_blinding.BlindKeyPair; | 725 | const BlindKeyPair = Ed25519.key_blinding.BlindKeyPair; |
| 722 | 726 | ||
| 723 | // Create a standard Ed25519 key pair | 727 | // Create a standard Ed25519 key pair |
| 724 | const kp = Ed25519.KeyPair.generate(); | 728 | const kp = Ed25519.KeyPair.generate(io); |
| 725 | 729 | ||
| 726 | // Create a random blinding seed | 730 | // Create a random blinding seed |
| 727 | var blind: [32]u8 = undefined; | 731 | var blind: [32]u8 = undefined; |
| 728 | crypto.random.bytes(&blind); | 732 | io.random(&blind); |
| 729 | 733 | ||
| 730 | // Blind the key pair | 734 | // Blind the key pair |
| 731 | const blind_kp = try BlindKeyPair.init(kp, blind, "ctx"); | 735 | const blind_kp = try BlindKeyPair.init(kp, blind, "ctx"); |
| ... | @@ -741,9 +745,12 @@ test "with blind keys" { | ... | @@ -741,9 +745,12 @@ test "with blind keys" { |
| 741 | } | 745 | } |
| 742 | 746 | ||
| 743 | test "signatures with streaming" { | 747 | test "signatures with streaming" { |
| 744 | const kp = Ed25519.KeyPair.generate(); | 748 | const io = std.testing.io; |
| 749 | const kp = Ed25519.KeyPair.generate(io); | ||
| 745 | 750 | ||
| 746 | var signer = try kp.signer(null); | 751 | var entropy: [Ed25519.noise_length]u8 = undefined; |
| 752 | io.random(&entropy); | ||
| 753 | var signer = try kp.signer(null, &entropy); | ||
| 747 | signer.update("mes"); | 754 | signer.update("mes"); |
| 748 | signer.update("sage"); | 755 | signer.update("sage"); |
| 749 | const sig = signer.finalize(); | 756 | const sig = signer.finalize(); |
| ... | @@ -757,7 +764,8 @@ test "signatures with streaming" { | ... | @@ -757,7 +764,8 @@ test "signatures with streaming" { |
| 757 | } | 764 | } |
| 758 | 765 | ||
| 759 | test "key pair from secret key" { | 766 | test "key pair from secret key" { |
| 760 | const kp = Ed25519.KeyPair.generate(); | 767 | const io = std.testing.io; |
| 768 | const kp = Ed25519.KeyPair.generate(io); | ||
| 761 | const kp2 = try Ed25519.KeyPair.fromSecretKey(kp.secret_key); | 769 | const kp2 = try Ed25519.KeyPair.fromSecretKey(kp.secret_key); |
| 762 | try std.testing.expectEqualSlices(u8, &kp.secret_key.toBytes(), &kp2.secret_key.toBytes()); | 770 | try std.testing.expectEqualSlices(u8, &kp.secret_key.toBytes(), &kp2.secret_key.toBytes()); |
| 763 | try std.testing.expectEqualSlices(u8, &kp.public_key.toBytes(), &kp2.public_key.toBytes()); | 771 | try std.testing.expectEqualSlices(u8, &kp.public_key.toBytes(), &kp2.public_key.toBytes()); |
| ... | @@ -788,7 +796,8 @@ test "cofactored vs cofactorless verification" { | ... | @@ -788,7 +796,8 @@ test "cofactored vs cofactorless verification" { |
| 788 | } | 796 | } |
| 789 | 797 | ||
| 790 | test "regular signature verifies with both verify and verifyStrict" { | 798 | test "regular signature verifies with both verify and verifyStrict" { |
| 791 | const kp = Ed25519.KeyPair.generate(); | 799 | const io = std.testing.io; |
| 800 | const kp = Ed25519.KeyPair.generate(io); | ||
| 792 | const msg = "test message"; | 801 | const msg = "test message"; |
| 793 | const sig = try kp.sign(msg, null); | 802 | const sig = try kp.sign(msg, null); |
| 794 | try sig.verify(msg, kp.public_key); | 803 | try sig.verify(msg, kp.public_key); |
lib/std/crypto/25519/edwards25519.zig+5-3| ... | @@ -575,10 +575,11 @@ test "packing/unpacking" { | ... | @@ -575,10 +575,11 @@ test "packing/unpacking" { |
| 575 | } | 575 | } |
| 576 | 576 | ||
| 577 | test "point addition/subtraction" { | 577 | test "point addition/subtraction" { |
| 578 | const io = std.testing.io; | ||
| 578 | var s1: [32]u8 = undefined; | 579 | var s1: [32]u8 = undefined; |
| 579 | var s2: [32]u8 = undefined; | 580 | var s2: [32]u8 = undefined; |
| 580 | crypto.random.bytes(&s1); | 581 | io.random(&s1); |
| 581 | crypto.random.bytes(&s2); | 582 | io.random(&s2); |
| 582 | const p = try Edwards25519.basePoint.clampedMul(s1); | 583 | const p = try Edwards25519.basePoint.clampedMul(s1); |
| 583 | const q = try Edwards25519.basePoint.clampedMul(s2); | 584 | const q = try Edwards25519.basePoint.clampedMul(s2); |
| 584 | const r = p.add(q).add(q).sub(q).sub(q); | 585 | const r = p.add(q).add(q).sub(q).sub(q); |
| ... | @@ -622,9 +623,10 @@ test "implicit reduction of invalid scalars" { | ... | @@ -622,9 +623,10 @@ test "implicit reduction of invalid scalars" { |
| 622 | } | 623 | } |
| 623 | 624 | ||
| 624 | test "subgroup check" { | 625 | test "subgroup check" { |
| 626 | const io = std.testing.io; | ||
| 625 | for (0..100) |_| { | 627 | for (0..100) |_| { |
| 626 | var p = Edwards25519.basePoint; | 628 | var p = Edwards25519.basePoint; |
| 627 | const s = Edwards25519.scalar.random(); | 629 | const s = Edwards25519.scalar.random(io); |
| 628 | p = try p.mulPublic(s); | 630 | p = try p.mulPublic(s); |
| 629 | try p.rejectUnexpectedSubgroup(); | 631 | try p.rejectUnexpectedSubgroup(); |
| 630 | } | 632 | } |
lib/std/crypto/25519/scalar.zig+7-6| ... | @@ -101,8 +101,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar) CompressedScalar { | ... | @@ -101,8 +101,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar) CompressedScalar { |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | /// Return a random scalar < L | 103 | /// Return a random scalar < L |
| 104 | pub fn random() CompressedScalar { | 104 | pub fn random(io: std.Io) CompressedScalar { |
| 105 | return Scalar.random().toBytes(); | 105 | return Scalar.random(io).toBytes(); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /// A scalar in unpacked representation | 108 | /// A scalar in unpacked representation |
| ... | @@ -560,10 +560,10 @@ pub const Scalar = struct { | ... | @@ -560,10 +560,10 @@ pub const Scalar = struct { |
| 560 | } | 560 | } |
| 561 | 561 | ||
| 562 | /// Return a random scalar < L. | 562 | /// Return a random scalar < L. |
| 563 | pub fn random() Scalar { | 563 | pub fn random(io: std.Io) Scalar { |
| 564 | var s: [64]u8 = undefined; | 564 | var s: [64]u8 = undefined; |
| 565 | while (true) { | 565 | while (true) { |
| 566 | crypto.random.bytes(&s); | 566 | io.random(&s); |
| 567 | const n = Scalar.fromBytes64(s); | 567 | const n = Scalar.fromBytes64(s); |
| 568 | if (!n.isZero()) { | 568 | if (!n.isZero()) { |
| 569 | return n; | 569 | return n; |
| ... | @@ -879,8 +879,9 @@ test "scalar field inversion" { | ... | @@ -879,8 +879,9 @@ test "scalar field inversion" { |
| 879 | } | 879 | } |
| 880 | 880 | ||
| 881 | test "random scalar" { | 881 | test "random scalar" { |
| 882 | const s1 = random(); | 882 | const io = std.testing.io; |
| 883 | const s2 = random(); | 883 | const s1 = random(io); |
| 884 | const s2 = random(io); | ||
| 884 | try std.testing.expect(!mem.eql(u8, &s1, &s2)); | 885 | try std.testing.expect(!mem.eql(u8, &s1, &s2)); |
| 885 | } | 886 | } |
| 886 | 887 |
lib/std/crypto/25519/x25519.zig+2-2| ... | @@ -41,10 +41,10 @@ pub const X25519 = struct { | ... | @@ -41,10 +41,10 @@ pub const X25519 = struct { |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | /// Generate a new, random key pair. | 43 | /// Generate a new, random key pair. |
| 44 | pub fn generate() KeyPair { | 44 | pub fn generate(io: std.Io) KeyPair { |
| 45 | var random_seed: [seed_length]u8 = undefined; | 45 | var random_seed: [seed_length]u8 = undefined; |
| 46 | while (true) { | 46 | while (true) { |
| 47 | crypto.random.bytes(&random_seed); | 47 | io.random(&random_seed); |
| 48 | return generateDeterministic(random_seed) catch { | 48 | return generateDeterministic(random_seed) catch { |
| 49 | @branchHint(.unlikely); | 49 | @branchHint(.unlikely); |
| 50 | continue; | 50 | continue; |
lib/std/crypto/argon2.zig+1-1| ... | @@ -533,7 +533,7 @@ const PhcFormatHasher = struct { | ... | @@ -533,7 +533,7 @@ const PhcFormatHasher = struct { |
| 533 | if (params.secret != null or params.ad != null) return HasherError.InvalidEncoding; | 533 | if (params.secret != null or params.ad != null) return HasherError.InvalidEncoding; |
| 534 | 534 | ||
| 535 | var salt: [default_salt_len]u8 = undefined; | 535 | var salt: [default_salt_len]u8 = undefined; |
| 536 | crypto.random.bytes(&salt); | 536 | io.random(&salt); |
| 537 | 537 | ||
| 538 | var hash: [default_hash_len]u8 = undefined; | 538 | var hash: [default_hash_len]u8 = undefined; |
| 539 | try kdf(allocator, &hash, password, &salt, params, mode, io); | 539 | try kdf(allocator, &hash, password, &salt, params, mode, io); |
lib/std/crypto/bcrypt.zig+72-39| ... | @@ -17,7 +17,7 @@ const HasherError = pwhash.HasherError; | ... | @@ -17,7 +17,7 @@ const HasherError = pwhash.HasherError; |
| 17 | const EncodingError = phc_format.Error; | 17 | const EncodingError = phc_format.Error; |
| 18 | const Error = pwhash.Error; | 18 | const Error = pwhash.Error; |
| 19 | 19 | ||
| 20 | const salt_length: usize = 16; | 20 | pub const salt_length: usize = 16; |
| 21 | const salt_str_length: usize = 22; | 21 | const salt_str_length: usize = 22; |
| 22 | const ct_str_length: usize = 31; | 22 | const ct_str_length: usize = 31; |
| 23 | const ct_length: usize = 24; | 23 | const ct_length: usize = 24; |
| ... | @@ -426,7 +426,7 @@ pub const Params = struct { | ... | @@ -426,7 +426,7 @@ pub const Params = struct { |
| 426 | 426 | ||
| 427 | fn bcryptWithTruncation( | 427 | fn bcryptWithTruncation( |
| 428 | password: []const u8, | 428 | password: []const u8, |
| 429 | salt: [salt_length]u8, | 429 | salt: *const [salt_length]u8, |
| 430 | params: Params, | 430 | params: Params, |
| 431 | ) [dk_length]u8 { | 431 | ) [dk_length]u8 { |
| 432 | var state = State{}; | 432 | var state = State{}; |
| ... | @@ -435,13 +435,13 @@ fn bcryptWithTruncation( | ... | @@ -435,13 +435,13 @@ fn bcryptWithTruncation( |
| 435 | @memcpy(password_buf[0..trimmed_len], password[0..trimmed_len]); | 435 | @memcpy(password_buf[0..trimmed_len], password[0..trimmed_len]); |
| 436 | password_buf[trimmed_len] = 0; | 436 | password_buf[trimmed_len] = 0; |
| 437 | const passwordZ = password_buf[0 .. trimmed_len + 1]; | 437 | const passwordZ = password_buf[0 .. trimmed_len + 1]; |
| 438 | state.expand(salt[0..], passwordZ); | 438 | state.expand(salt, passwordZ); |
| 439 | 439 | ||
| 440 | const rounds: u64 = @as(u64, 1) << params.rounds_log; | 440 | const rounds: u64 = @as(u64, 1) << params.rounds_log; |
| 441 | var k: u64 = 0; | 441 | var k: u64 = 0; |
| 442 | while (k < rounds) : (k += 1) { | 442 | while (k < rounds) : (k += 1) { |
| 443 | state.expand0(passwordZ); | 443 | state.expand0(passwordZ); |
| 444 | state.expand0(salt[0..]); | 444 | state.expand0(salt); |
| 445 | } | 445 | } |
| 446 | crypto.secureZero(u8, &password_buf); | 446 | crypto.secureZero(u8, &password_buf); |
| 447 | 447 | ||
| ... | @@ -467,7 +467,7 @@ fn bcryptWithTruncation( | ... | @@ -467,7 +467,7 @@ fn bcryptWithTruncation( |
| 467 | /// For key derivation, use `bcrypt.pbkdf()` or `bcrypt.opensshKdf()` instead. | 467 | /// For key derivation, use `bcrypt.pbkdf()` or `bcrypt.opensshKdf()` instead. |
| 468 | pub fn bcrypt( | 468 | pub fn bcrypt( |
| 469 | password: []const u8, | 469 | password: []const u8, |
| 470 | salt: [salt_length]u8, | 470 | salt: *const [salt_length]u8, |
| 471 | params: Params, | 471 | params: Params, |
| 472 | ) [dk_length]u8 { | 472 | ) [dk_length]u8 { |
| 473 | if (password.len <= 72 or params.silently_truncate_password) { | 473 | if (password.len <= 72 or params.silently_truncate_password) { |
| ... | @@ -475,7 +475,7 @@ pub fn bcrypt( | ... | @@ -475,7 +475,7 @@ pub fn bcrypt( |
| 475 | } | 475 | } |
| 476 | 476 | ||
| 477 | var pre_hash: [HmacSha512.mac_length]u8 = undefined; | 477 | var pre_hash: [HmacSha512.mac_length]u8 = undefined; |
| 478 | HmacSha512.create(&pre_hash, password, &salt); | 478 | HmacSha512.create(&pre_hash, password, salt); |
| 479 | 479 | ||
| 480 | const Encoder = crypt_format.Codec.Encoder; | 480 | const Encoder = crypt_format.Codec.Encoder; |
| 481 | var pre_hash_b64: [Encoder.calcSize(pre_hash.len)]u8 = undefined; | 481 | var pre_hash_b64: [Encoder.calcSize(pre_hash.len)]u8 = undefined; |
| ... | @@ -623,16 +623,16 @@ const crypt_format = struct { | ... | @@ -623,16 +623,16 @@ const crypt_format = struct { |
| 623 | 623 | ||
| 624 | fn strHashInternal( | 624 | fn strHashInternal( |
| 625 | password: []const u8, | 625 | password: []const u8, |
| 626 | salt: [salt_length]u8, | 626 | salt: *const [salt_length]u8, |
| 627 | params: Params, | 627 | params: Params, |
| 628 | ) [hash_length]u8 { | 628 | ) [hash_length]u8 { |
| 629 | var dk = bcrypt(password, salt, params); | 629 | var dk = bcrypt(password, salt, params); |
| 630 | 630 | ||
| 631 | var salt_str: [salt_str_length]u8 = undefined; | 631 | var salt_str: [salt_str_length]u8 = undefined; |
| 632 | _ = Codec.Encoder.encode(salt_str[0..], salt[0..]); | 632 | _ = Codec.Encoder.encode(&salt_str, salt); |
| 633 | 633 | ||
| 634 | var ct_str: [ct_str_length]u8 = undefined; | 634 | var ct_str: [ct_str_length]u8 = undefined; |
| 635 | _ = Codec.Encoder.encode(ct_str[0..], dk[0..]); | 635 | _ = Codec.Encoder.encode(&ct_str, dk[0..]); |
| 636 | 636 | ||
| 637 | var s_buf: [hash_length]u8 = undefined; | 637 | var s_buf: [hash_length]u8 = undefined; |
| 638 | const s = fmt.bufPrint( | 638 | const s = fmt.bufPrint( |
| ... | @@ -657,21 +657,20 @@ const PhcFormatHasher = struct { | ... | @@ -657,21 +657,20 @@ const PhcFormatHasher = struct { |
| 657 | hash: BinValue(dk_length), | 657 | hash: BinValue(dk_length), |
| 658 | }; | 658 | }; |
| 659 | 659 | ||
| 660 | /// Return a non-deterministic hash of the password encoded as a PHC-format string | 660 | /// Return a non-deterministic hash of the password encoded as a PHC-format string. |
| 661 | fn create( | 661 | fn create( |
| 662 | password: []const u8, | 662 | password: []const u8, |
| 663 | params: Params, | 663 | params: Params, |
| 664 | buf: []u8, | 664 | buf: []u8, |
| 665 | /// Filled with cryptographically secure entropy. | ||
| 666 | salt: *const [salt_length]u8, | ||
| 665 | ) HasherError![]const u8 { | 667 | ) HasherError![]const u8 { |
| 666 | var salt: [salt_length]u8 = undefined; | ||
| 667 | crypto.random.bytes(&salt); | ||
| 668 | |||
| 669 | const hash = bcrypt(password, salt, params); | 668 | const hash = bcrypt(password, salt, params); |
| 670 | 669 | ||
| 671 | return phc_format.serialize(HashResult{ | 670 | return phc_format.serialize(HashResult{ |
| 672 | .alg_id = alg_id, | 671 | .alg_id = alg_id, |
| 673 | .r = params.rounds_log, | 672 | .r = params.rounds_log, |
| 674 | .salt = try BinValue(salt_length).fromSlice(&salt), | 673 | .salt = try BinValue(salt_length).fromSlice(salt), |
| 675 | .hash = try BinValue(dk_length).fromSlice(&hash), | 674 | .hash = try BinValue(dk_length).fromSlice(&hash), |
| 676 | }, buf); | 675 | }, buf); |
| 677 | } | 676 | } |
| ... | @@ -688,11 +687,11 @@ const PhcFormatHasher = struct { | ... | @@ -688,11 +687,11 @@ const PhcFormatHasher = struct { |
| 688 | if (hash_result.salt.len != salt_length or hash_result.hash.len != dk_length) | 687 | if (hash_result.salt.len != salt_length or hash_result.hash.len != dk_length) |
| 689 | return HasherError.InvalidEncoding; | 688 | return HasherError.InvalidEncoding; |
| 690 | 689 | ||
| 691 | const params = Params{ | 690 | const params: Params = .{ |
| 692 | .rounds_log = hash_result.r, | 691 | .rounds_log = hash_result.r, |
| 693 | .silently_truncate_password = silently_truncate_password, | 692 | .silently_truncate_password = silently_truncate_password, |
| 694 | }; | 693 | }; |
| 695 | const hash = bcrypt(password, hash_result.salt.buf, params); | 694 | const hash = bcrypt(password, &hash_result.salt.buf, params); |
| 696 | const expected_hash = hash_result.hash.constSlice(); | 695 | const expected_hash = hash_result.hash.constSlice(); |
| 697 | 696 | ||
| 698 | if (!mem.eql(u8, &hash, expected_hash)) return HasherError.PasswordVerificationFailed; | 697 | if (!mem.eql(u8, &hash, expected_hash)) return HasherError.PasswordVerificationFailed; |
| ... | @@ -709,12 +708,11 @@ const CryptFormatHasher = struct { | ... | @@ -709,12 +708,11 @@ const CryptFormatHasher = struct { |
| 709 | password: []const u8, | 708 | password: []const u8, |
| 710 | params: Params, | 709 | params: Params, |
| 711 | buf: []u8, | 710 | buf: []u8, |
| 711 | /// Filled with cryptographically secure entropy. | ||
| 712 | salt: *const [salt_length]u8, | ||
| 712 | ) HasherError![]const u8 { | 713 | ) HasherError![]const u8 { |
| 713 | if (buf.len < pwhash_str_length) return HasherError.NoSpaceLeft; | 714 | if (buf.len < pwhash_str_length) return HasherError.NoSpaceLeft; |
| 714 | 715 | ||
| 715 | var salt: [salt_length]u8 = undefined; | ||
| 716 | crypto.random.bytes(&salt); | ||
| 717 | |||
| 718 | const hash = crypt_format.strHashInternal(password, salt, params); | 716 | const hash = crypt_format.strHashInternal(password, salt, params); |
| 719 | @memcpy(buf[0..hash.len], &hash); | 717 | @memcpy(buf[0..hash.len], &hash); |
| 720 | 718 | ||
| ... | @@ -736,9 +734,9 @@ const CryptFormatHasher = struct { | ... | @@ -736,9 +734,9 @@ const CryptFormatHasher = struct { |
| 736 | 734 | ||
| 737 | const salt_str = str[7..][0..salt_str_length]; | 735 | const salt_str = str[7..][0..salt_str_length]; |
| 738 | var salt: [salt_length]u8 = undefined; | 736 | var salt: [salt_length]u8 = undefined; |
| 739 | crypt_format.Codec.Decoder.decode(salt[0..], salt_str[0..]) catch return HasherError.InvalidEncoding; | 737 | crypt_format.Codec.Decoder.decode(&salt, salt_str) catch return HasherError.InvalidEncoding; |
| 740 | 738 | ||
| 741 | const wanted_s = crypt_format.strHashInternal(password, salt, .{ | 739 | const wanted_s = crypt_format.strHashInternal(password, &salt, .{ |
| 742 | .rounds_log = rounds_log, | 740 | .rounds_log = rounds_log, |
| 743 | .silently_truncate_password = silently_truncate_password, | 741 | .silently_truncate_password = silently_truncate_password, |
| 744 | }); | 742 | }); |
| ... | @@ -756,21 +754,28 @@ pub const HashOptions = struct { | ... | @@ -756,21 +754,28 @@ pub const HashOptions = struct { |
| 756 | encoding: pwhash.Encoding, | 754 | encoding: pwhash.Encoding, |
| 757 | }; | 755 | }; |
| 758 | 756 | ||
| 759 | /// Compute a hash of a password using 2^rounds_log rounds of the bcrypt key stretching function. | 757 | /// Compute a hash of a password using 2^rounds_log rounds of the bcrypt key |
| 760 | /// bcrypt is a computationally expensive and cache-hard function, explicitly designed to slow down exhaustive searches. | 758 | /// stretching function. |
| 759 | /// | ||
| 760 | /// bcrypt is a computationally expensive and cache-hard function, explicitly | ||
| 761 | /// designed to slow down exhaustive searches. | ||
| 761 | /// | 762 | /// |
| 762 | /// The function returns a string that includes all the parameters required for verification. | 763 | /// The function returns a string that includes all the parameters required for |
| 764 | /// verification. | ||
| 763 | /// | 765 | /// |
| 764 | /// IMPORTANT: by design, bcrypt silently truncates passwords to 72 bytes. | 766 | /// By design, bcrypt silently truncates passwords to 72 bytes. If this is an |
| 765 | /// If this is an issue for your application, set the `silently_truncate_password` option to `false`. | 767 | /// issue for your application, set the `silently_truncate_password` option to |
| 768 | /// `false`. | ||
| 766 | pub fn strHash( | 769 | pub fn strHash( |
| 767 | password: []const u8, | 770 | password: []const u8, |
| 768 | options: HashOptions, | 771 | options: HashOptions, |
| 769 | out: []u8, | 772 | out: []u8, |
| 773 | /// Filled with cryptographically secure entropy. | ||
| 774 | salt: *const [salt_length]u8, | ||
| 770 | ) Error![]const u8 { | 775 | ) Error![]const u8 { |
| 771 | switch (options.encoding) { | 776 | switch (options.encoding) { |
| 772 | .phc => return PhcFormatHasher.create(password, options.params, out), | 777 | .phc => return PhcFormatHasher.create(password, options.params, out, salt), |
| 773 | .crypt => return CryptFormatHasher.create(password, options.params, out), | 778 | .crypt => return CryptFormatHasher.create(password, options.params, out, salt), |
| 774 | } | 779 | } |
| 775 | } | 780 | } |
| 776 | 781 | ||
| ... | @@ -796,8 +801,9 @@ pub fn strVerify( | ... | @@ -796,8 +801,9 @@ pub fn strVerify( |
| 796 | } | 801 | } |
| 797 | 802 | ||
| 798 | test "bcrypt codec" { | 803 | test "bcrypt codec" { |
| 804 | const io = testing.io; | ||
| 799 | var salt: [salt_length]u8 = undefined; | 805 | var salt: [salt_length]u8 = undefined; |
| 800 | crypto.random.bytes(&salt); | 806 | io.random(&salt); |
| 801 | var salt_str: [salt_str_length]u8 = undefined; | 807 | var salt_str: [salt_str_length]u8 = undefined; |
| 802 | _ = crypt_format.Codec.Encoder.encode(salt_str[0..], salt[0..]); | 808 | _ = crypt_format.Codec.Encoder.encode(salt_str[0..], salt[0..]); |
| 803 | var salt2: [salt_length]u8 = undefined; | 809 | var salt2: [salt_length]u8 = undefined; |
| ... | @@ -806,14 +812,20 @@ test "bcrypt codec" { | ... | @@ -806,14 +812,20 @@ test "bcrypt codec" { |
| 806 | } | 812 | } |
| 807 | 813 | ||
| 808 | test "bcrypt crypt format" { | 814 | test "bcrypt crypt format" { |
| 809 | var hash_options = HashOptions{ | 815 | const io = testing.io; |
| 816 | |||
| 817 | var hash_options: HashOptions = .{ | ||
| 810 | .params = .{ .rounds_log = 5, .silently_truncate_password = false }, | 818 | .params = .{ .rounds_log = 5, .silently_truncate_password = false }, |
| 811 | .encoding = .crypt, | 819 | .encoding = .crypt, |
| 812 | }; | 820 | }; |
| 813 | var verify_options = VerifyOptions{ .silently_truncate_password = false }; | 821 | var verify_options: VerifyOptions = .{ .silently_truncate_password = false }; |
| 814 | 822 | ||
| 815 | var buf: [hash_length]u8 = undefined; | 823 | var buf: [hash_length]u8 = undefined; |
| 816 | const s = try strHash("password", hash_options, &buf); | 824 | const s = s: { |
| 825 | var salt: [salt_length]u8 = undefined; | ||
| 826 | io.random(&salt); | ||
| 827 | break :s try strHash("password", hash_options, &buf, &salt); | ||
| 828 | }; | ||
| 817 | 829 | ||
| 818 | try testing.expect(mem.startsWith(u8, s, crypt_format.prefix)); | 830 | try testing.expect(mem.startsWith(u8, s, crypt_format.prefix)); |
| 819 | try strVerify(s, "password", verify_options); | 831 | try strVerify(s, "password", verify_options); |
| ... | @@ -823,7 +835,11 @@ test "bcrypt crypt format" { | ... | @@ -823,7 +835,11 @@ test "bcrypt crypt format" { |
| 823 | ); | 835 | ); |
| 824 | 836 | ||
| 825 | var long_buf: [hash_length]u8 = undefined; | 837 | var long_buf: [hash_length]u8 = undefined; |
| 826 | var long_s = try strHash("password" ** 100, hash_options, &long_buf); | 838 | var long_s = s: { |
| 839 | var salt: [salt_length]u8 = undefined; | ||
| 840 | io.random(&salt); | ||
| 841 | break :s try strHash("password" ** 100, hash_options, &long_buf, &salt); | ||
| 842 | }; | ||
| 827 | 843 | ||
| 828 | try testing.expect(mem.startsWith(u8, long_s, crypt_format.prefix)); | 844 | try testing.expect(mem.startsWith(u8, long_s, crypt_format.prefix)); |
| 829 | try strVerify(long_s, "password" ** 100, verify_options); | 845 | try strVerify(long_s, "password" ** 100, verify_options); |
| ... | @@ -834,7 +850,11 @@ test "bcrypt crypt format" { | ... | @@ -834,7 +850,11 @@ test "bcrypt crypt format" { |
| 834 | 850 | ||
| 835 | hash_options.params.silently_truncate_password = true; | 851 | hash_options.params.silently_truncate_password = true; |
| 836 | verify_options.silently_truncate_password = true; | 852 | verify_options.silently_truncate_password = true; |
| 837 | long_s = try strHash("password" ** 100, hash_options, &long_buf); | 853 | long_s = s: { |
| 854 | var salt: [salt_length]u8 = undefined; | ||
| 855 | io.random(&salt); | ||
| 856 | break :s try strHash("password" ** 100, hash_options, &long_buf, &salt); | ||
| 857 | }; | ||
| 838 | try strVerify(long_s, "password" ** 101, verify_options); | 858 | try strVerify(long_s, "password" ** 101, verify_options); |
| 839 | 859 | ||
| 840 | try strVerify( | 860 | try strVerify( |
| ... | @@ -845,15 +865,20 @@ test "bcrypt crypt format" { | ... | @@ -845,15 +865,20 @@ test "bcrypt crypt format" { |
| 845 | } | 865 | } |
| 846 | 866 | ||
| 847 | test "bcrypt phc format" { | 867 | test "bcrypt phc format" { |
| 848 | var hash_options = HashOptions{ | 868 | const io = testing.io; |
| 869 | var hash_options: HashOptions = .{ | ||
| 849 | .params = .{ .rounds_log = 5, .silently_truncate_password = false }, | 870 | .params = .{ .rounds_log = 5, .silently_truncate_password = false }, |
| 850 | .encoding = .phc, | 871 | .encoding = .phc, |
| 851 | }; | 872 | }; |
| 852 | var verify_options = VerifyOptions{ .silently_truncate_password = false }; | 873 | var verify_options: VerifyOptions = .{ .silently_truncate_password = false }; |
| 853 | const prefix = "$bcrypt$"; | 874 | const prefix = "$bcrypt$"; |
| 854 | 875 | ||
| 855 | var buf: [hash_length * 2]u8 = undefined; | 876 | var buf: [hash_length * 2]u8 = undefined; |
| 856 | const s = try strHash("password", hash_options, &buf); | 877 | const s = s: { |
| 878 | var salt: [salt_length]u8 = undefined; | ||
| 879 | io.random(&salt); | ||
| 880 | break :s try strHash("password", hash_options, &buf, &salt); | ||
| 881 | }; | ||
| 857 | 882 | ||
| 858 | try testing.expect(mem.startsWith(u8, s, prefix)); | 883 | try testing.expect(mem.startsWith(u8, s, prefix)); |
| 859 | try strVerify(s, "password", verify_options); | 884 | try strVerify(s, "password", verify_options); |
| ... | @@ -863,7 +888,11 @@ test "bcrypt phc format" { | ... | @@ -863,7 +888,11 @@ test "bcrypt phc format" { |
| 863 | ); | 888 | ); |
| 864 | 889 | ||
| 865 | var long_buf: [hash_length * 2]u8 = undefined; | 890 | var long_buf: [hash_length * 2]u8 = undefined; |
| 866 | var long_s = try strHash("password" ** 100, hash_options, &long_buf); | 891 | var long_s = s: { |
| 892 | var salt: [salt_length]u8 = undefined; | ||
| 893 | io.random(&salt); | ||
| 894 | break :s try strHash("password" ** 100, hash_options, &long_buf, &salt); | ||
| 895 | }; | ||
| 867 | 896 | ||
| 868 | try testing.expect(mem.startsWith(u8, long_s, prefix)); | 897 | try testing.expect(mem.startsWith(u8, long_s, prefix)); |
| 869 | try strVerify(long_s, "password" ** 100, verify_options); | 898 | try strVerify(long_s, "password" ** 100, verify_options); |
| ... | @@ -874,7 +903,11 @@ test "bcrypt phc format" { | ... | @@ -874,7 +903,11 @@ test "bcrypt phc format" { |
| 874 | 903 | ||
| 875 | hash_options.params.silently_truncate_password = true; | 904 | hash_options.params.silently_truncate_password = true; |
| 876 | verify_options.silently_truncate_password = true; | 905 | verify_options.silently_truncate_password = true; |
| 877 | long_s = try strHash("password" ** 100, hash_options, &long_buf); | 906 | long_s = s: { |
| 907 | var salt: [salt_length]u8 = undefined; | ||
| 908 | io.random(&salt); | ||
| 909 | break :s try strHash("password" ** 100, hash_options, &long_buf, &salt); | ||
| 910 | }; | ||
| 878 | try strVerify(long_s, "password" ** 101, verify_options); | 911 | try strVerify(long_s, "password" ** 101, verify_options); |
| 879 | 912 | ||
| 880 | try strVerify( | 913 | try strVerify( |
lib/std/crypto/ecdsa.zig+17-11| ... | @@ -323,10 +323,10 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { | ... | @@ -323,10 +323,10 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | /// Generate a new, random key pair. | 325 | /// Generate a new, random key pair. |
| 326 | pub fn generate() KeyPair { | 326 | pub fn generate(io: std.Io) KeyPair { |
| 327 | var random_seed: [seed_length]u8 = undefined; | 327 | var random_seed: [seed_length]u8 = undefined; |
| 328 | while (true) { | 328 | while (true) { |
| 329 | crypto.random.bytes(&random_seed); | 329 | io.random(&random_seed); |
| 330 | return generateDeterministic(random_seed) catch { | 330 | return generateDeterministic(random_seed) catch { |
| 331 | @branchHint(.unlikely); | 331 | @branchHint(.unlikely); |
| 332 | continue; | 332 | continue; |
| ... | @@ -417,12 +417,13 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { | ... | @@ -417,12 +417,13 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { |
| 417 | test "Basic operations over EcdsaP384Sha384" { | 417 | test "Basic operations over EcdsaP384Sha384" { |
| 418 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 418 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 419 | 419 | ||
| 420 | const io = testing.io; | ||
| 420 | const Scheme = EcdsaP384Sha384; | 421 | const Scheme = EcdsaP384Sha384; |
| 421 | const kp = Scheme.KeyPair.generate(); | 422 | const kp = Scheme.KeyPair.generate(io); |
| 422 | const msg = "test"; | 423 | const msg = "test"; |
| 423 | 424 | ||
| 424 | var noise: [Scheme.noise_length]u8 = undefined; | 425 | var noise: [Scheme.noise_length]u8 = undefined; |
| 425 | crypto.random.bytes(&noise); | 426 | io.random(&noise); |
| 426 | const sig = try kp.sign(msg, noise); | 427 | const sig = try kp.sign(msg, noise); |
| 427 | try sig.verify(msg, kp.public_key); | 428 | try sig.verify(msg, kp.public_key); |
| 428 | 429 | ||
| ... | @@ -433,12 +434,13 @@ test "Basic operations over EcdsaP384Sha384" { | ... | @@ -433,12 +434,13 @@ test "Basic operations over EcdsaP384Sha384" { |
| 433 | test "Basic operations over Secp256k1" { | 434 | test "Basic operations over Secp256k1" { |
| 434 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 435 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 435 | 436 | ||
| 437 | const io = testing.io; | ||
| 436 | const Scheme = EcdsaSecp256k1Sha256oSha256; | 438 | const Scheme = EcdsaSecp256k1Sha256oSha256; |
| 437 | const kp = Scheme.KeyPair.generate(); | 439 | const kp = Scheme.KeyPair.generate(io); |
| 438 | const msg = "test"; | 440 | const msg = "test"; |
| 439 | 441 | ||
| 440 | var noise: [Scheme.noise_length]u8 = undefined; | 442 | var noise: [Scheme.noise_length]u8 = undefined; |
| 441 | crypto.random.bytes(&noise); | 443 | io.random(&noise); |
| 442 | const sig = try kp.sign(msg, noise); | 444 | const sig = try kp.sign(msg, noise); |
| 443 | try sig.verify(msg, kp.public_key); | 445 | try sig.verify(msg, kp.public_key); |
| 444 | 446 | ||
| ... | @@ -449,12 +451,13 @@ test "Basic operations over Secp256k1" { | ... | @@ -449,12 +451,13 @@ test "Basic operations over Secp256k1" { |
| 449 | test "Basic operations over EcdsaP384Sha256" { | 451 | test "Basic operations over EcdsaP384Sha256" { |
| 450 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 452 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 451 | 453 | ||
| 454 | const io = testing.io; | ||
| 452 | const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256); | 455 | const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256); |
| 453 | const kp = Scheme.KeyPair.generate(); | 456 | const kp = Scheme.KeyPair.generate(io); |
| 454 | const msg = "test"; | 457 | const msg = "test"; |
| 455 | 458 | ||
| 456 | var noise: [Scheme.noise_length]u8 = undefined; | 459 | var noise: [Scheme.noise_length]u8 = undefined; |
| 457 | crypto.random.bytes(&noise); | 460 | io.random(&noise); |
| 458 | const sig = try kp.sign(msg, noise); | 461 | const sig = try kp.sign(msg, noise); |
| 459 | try sig.verify(msg, kp.public_key); | 462 | try sig.verify(msg, kp.public_key); |
| 460 | 463 | ||
| ... | @@ -502,8 +505,10 @@ test "Verifying a existing signature with EcdsaP384Sha256" { | ... | @@ -502,8 +505,10 @@ test "Verifying a existing signature with EcdsaP384Sha256" { |
| 502 | test "Prehashed message operations" { | 505 | test "Prehashed message operations" { |
| 503 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 506 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 504 | 507 | ||
| 508 | const io = testing.io; | ||
| 509 | |||
| 505 | const Scheme = EcdsaP256Sha256; | 510 | const Scheme = EcdsaP256Sha256; |
| 506 | const kp = Scheme.KeyPair.generate(); | 511 | const kp = Scheme.KeyPair.generate(io); |
| 507 | const msg = "test message for prehashed signing"; | 512 | const msg = "test message for prehashed signing"; |
| 508 | 513 | ||
| 509 | const Hash = crypto.hash.sha2.Sha256; | 514 | const Hash = crypto.hash.sha2.Sha256; |
| ... | @@ -518,7 +523,7 @@ test "Prehashed message operations" { | ... | @@ -518,7 +523,7 @@ test "Prehashed message operations" { |
| 518 | try testing.expectError(error.SignatureVerificationFailed, sig.verifyPrehashed(bad_hash, kp.public_key)); | 523 | try testing.expectError(error.SignatureVerificationFailed, sig.verifyPrehashed(bad_hash, kp.public_key)); |
| 519 | 524 | ||
| 520 | var noise: [Scheme.noise_length]u8 = undefined; | 525 | var noise: [Scheme.noise_length]u8 = undefined; |
| 521 | crypto.random.bytes(&noise); | 526 | io.random(&noise); |
| 522 | const sig_with_noise = try kp.signPrehashed(msg_hash, noise); | 527 | const sig_with_noise = try kp.signPrehashed(msg_hash, noise); |
| 523 | try sig_with_noise.verifyPrehashed(msg_hash, kp.public_key); | 528 | try sig_with_noise.verifyPrehashed(msg_hash, kp.public_key); |
| 524 | 529 | ||
| ... | @@ -1628,8 +1633,9 @@ fn tvTry(comptime Scheme: type, vector: TestVector) !void { | ... | @@ -1628,8 +1633,9 @@ fn tvTry(comptime Scheme: type, vector: TestVector) !void { |
| 1628 | test "Sec1 encoding/decoding" { | 1633 | test "Sec1 encoding/decoding" { |
| 1629 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 1634 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 1630 | 1635 | ||
| 1636 | const io = testing.io; | ||
| 1631 | const Scheme = EcdsaP384Sha384; | 1637 | const Scheme = EcdsaP384Sha384; |
| 1632 | const kp = Scheme.KeyPair.generate(); | 1638 | const kp = Scheme.KeyPair.generate(io); |
| 1633 | const pk = kp.public_key; | 1639 | const pk = kp.public_key; |
| 1634 | const pk_compressed_sec1 = pk.toCompressedSec1(); | 1640 | const pk_compressed_sec1 = pk.toCompressedSec1(); |
| 1635 | const pk_recovered1 = try Scheme.PublicKey.fromSec1(&pk_compressed_sec1); | 1641 | const pk_recovered1 = try Scheme.PublicKey.fromSec1(&pk_compressed_sec1); |
lib/std/crypto/hybrid_kem.zig+74-61| ... | @@ -174,43 +174,56 @@ pub fn HybridKem(comptime params: Params) type { | ... | @@ -174,43 +174,56 @@ pub fn HybridKem(comptime params: Params) type { |
| 174 | return .{ .bytes = buf.* }; | 174 | return .{ .bytes = buf.* }; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | /// Generates a shared secret and encapsulates it for the public key. | 177 | /// Generates a shared secret, encapsulated for the public key, |
| 178 | /// If `seed` is `null`, uses random bytes from `std.crypto.random`. | 178 | /// using random bytes. |
| 179 | /// If `seed` is set, encapsulation is deterministic (for testing only). | 179 | /// |
| 180 | pub fn encaps(self: PublicKey, seed: ?[]const u8) !EncapsulatedSecret { | 180 | /// This is recommended over `encapsDeterministic`. |
| 181 | const pq_nek = params.PqKem.PublicKey.encoded_length; | 181 | pub fn encaps(pk: PublicKey, io: std.Io) !EncapsulatedSecret { |
| 182 | const ek_pq = try params.PqKem.PublicKey.fromBytes(self.bytes[0..pq_nek]); | ||
| 183 | const ek_t = self.bytes[pq_nek..][0..params.Group.element_length]; | ||
| 184 | |||
| 185 | var seed_pq: [32]u8 = undefined; | 182 | var seed_pq: [32]u8 = undefined; |
| 186 | var seed_t_expanded: [params.Group.seed_length]u8 = undefined; | 183 | io.random(&seed_pq); |
| 184 | var seed_t: [32]u8 = undefined; | ||
| 185 | io.random(&seed_t); | ||
| 186 | var seed_t_expanded: [params.Group.seed_length]u8 = try expandRandomnessSeed(seed_t); | ||
| 187 | return encapsInner(pk, &seed_pq, &seed_t_expanded); | ||
| 188 | } | ||
| 187 | 189 | ||
| 188 | if (seed) |r| { | 190 | /// Generates a shared secret, encapsulated for the public key, |
| 189 | if (r.len < 32) return error.InsufficientRandomness; | 191 | /// using the provided seed. |
| 190 | seed_pq = r[0..32].*; | 192 | /// |
| 193 | /// Calling `encaps` instead is recommended. | ||
| 194 | pub fn encapsDeterministic(pk: PublicKey, seed: []const u8) !EncapsulatedSecret { | ||
| 195 | if (seed.len < 32) return error.InsufficientRandomness; | ||
| 196 | var seed_pq: [32]u8 = seed[0..32].*; | ||
| 197 | var seed_t_expanded: [params.Group.seed_length]u8 = undefined; | ||
| 191 | 198 | ||
| 192 | const t_randomness = r[32..]; | 199 | const t_randomness = seed[32..]; |
| 200 | if (t_randomness.len < params.Group.seed_length) { | ||
| 201 | // Provided randomness is shorter than seed_length, use it directly | ||
| 202 | // (test vectors provide just enough for randomScalar) | ||
| 203 | @memcpy(seed_t_expanded[0..t_randomness.len], t_randomness); | ||
| 204 | // Pad the rest with zeros if needed (shouldn't be used by randomScalar) | ||
| 193 | if (t_randomness.len < params.Group.seed_length) { | 205 | if (t_randomness.len < params.Group.seed_length) { |
| 194 | // Provided randomness is shorter than seed_length, use it directly | 206 | @memset(seed_t_expanded[t_randomness.len..], 0); |
| 195 | // (test vectors provide just enough for randomScalar) | ||
| 196 | @memcpy(seed_t_expanded[0..t_randomness.len], t_randomness); | ||
| 197 | // Pad the rest with zeros if needed (shouldn't be used by randomScalar) | ||
| 198 | if (t_randomness.len < params.Group.seed_length) { | ||
| 199 | @memset(seed_t_expanded[t_randomness.len..], 0); | ||
| 200 | } | ||
| 201 | } else { | ||
| 202 | // Full randomness provided | ||
| 203 | @memcpy(&seed_t_expanded, t_randomness[0..params.Group.seed_length]); | ||
| 204 | } | 207 | } |
| 205 | } else { | 208 | } else { |
| 206 | crypto.random.bytes(&seed_pq); | 209 | // Full randomness provided |
| 207 | var seed_t: [32]u8 = undefined; | 210 | @memcpy(&seed_t_expanded, t_randomness[0..params.Group.seed_length]); |
| 208 | crypto.random.bytes(&seed_t); | ||
| 209 | seed_t_expanded = try expandRandomnessSeed(seed_t); | ||
| 210 | } | 211 | } |
| 211 | 212 | ||
| 212 | const pq_encap = ek_pq.encaps(seed_pq); | 213 | return encapsInner(pk, &seed_pq, &seed_t_expanded); |
| 213 | const sk_e = try params.Group.randomScalar(&seed_t_expanded); | 214 | } |
| 215 | |||
| 216 | fn encapsInner( | ||
| 217 | pk: PublicKey, | ||
| 218 | seed_pq: *[32]u8, | ||
| 219 | seed_t_expanded: *[params.Group.seed_length]u8, | ||
| 220 | ) !EncapsulatedSecret { | ||
| 221 | const pq_nek = params.PqKem.PublicKey.encoded_length; | ||
| 222 | const ek_pq = try params.PqKem.PublicKey.fromBytes(pk.bytes[0..pq_nek]); | ||
| 223 | const ek_t = pk.bytes[pq_nek..][0..params.Group.element_length]; | ||
| 224 | |||
| 225 | const pq_encap = ek_pq.encapsDeterministic(seed_pq); | ||
| 226 | const sk_e = try params.Group.randomScalar(seed_t_expanded); | ||
| 214 | const ct_t_point = try params.Group.mulBase(sk_e); | 227 | const ct_t_point = try params.Group.mulBase(sk_e); |
| 215 | const ct_t = if (is_nist_curve) params.Group.encodePoint(ct_t_point) else ct_t_point; | 228 | const ct_t = if (is_nist_curve) params.Group.encodePoint(ct_t_point) else ct_t_point; |
| 216 | 229 | ||
| ... | @@ -280,9 +293,9 @@ pub fn HybridKem(comptime params: Params) type { | ... | @@ -280,9 +293,9 @@ pub fn HybridKem(comptime params: Params) type { |
| 280 | } | 293 | } |
| 281 | 294 | ||
| 282 | /// Generates a new random key pair. | 295 | /// Generates a new random key pair. |
| 283 | pub fn generate() !KeyPair { | 296 | pub fn generate(io: std.Io) !KeyPair { |
| 284 | var seed: [params.Nseed]u8 = undefined; | 297 | var seed: [params.Nseed]u8 = undefined; |
| 285 | crypto.random.bytes(&seed); | 298 | io.random(&seed); |
| 286 | return generateDeterministic(seed); | 299 | return generateDeterministic(seed); |
| 287 | } | 300 | } |
| 288 | }; | 301 | }; |
| ... | @@ -386,7 +399,7 @@ test "MLKEM768-X25519 basic round trip" { | ... | @@ -386,7 +399,7 @@ test "MLKEM768-X25519 basic round trip" { |
| 386 | var enc_seed: [64]u8 = undefined; | 399 | var enc_seed: [64]u8 = undefined; |
| 387 | @memset(&enc_seed, 0x43); | 400 | @memset(&enc_seed, 0x43); |
| 388 | 401 | ||
| 389 | const encap_result = try kp.public_key.encaps(&enc_seed); | 402 | const encap_result = try kp.public_key.encapsDeterministic(&enc_seed); |
| 390 | const ss_decap = try kp.secret_key.decaps(&encap_result.ciphertext); | 403 | const ss_decap = try kp.secret_key.decaps(&encap_result.ciphertext); |
| 391 | 404 | ||
| 392 | try testing.expectEqualSlices(u8, &encap_result.shared_secret, &ss_decap); | 405 | try testing.expectEqualSlices(u8, &encap_result.shared_secret, &ss_decap); |
| ... | @@ -408,7 +421,7 @@ test "MLKEM768-X25519 test vector 0" { | ... | @@ -408,7 +421,7 @@ test "MLKEM768-X25519 test vector 0" { |
| 408 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); | 421 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); |
| 409 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 422 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 410 | 423 | ||
| 411 | const enc_result = try kp.public_key.encaps(&randomness); | 424 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 412 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 425 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 413 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 426 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 414 | 427 | ||
| ... | @@ -432,7 +445,7 @@ test "MLKEM768-X25519 test vector 1" { | ... | @@ -432,7 +445,7 @@ test "MLKEM768-X25519 test vector 1" { |
| 432 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); | 445 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); |
| 433 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 446 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 434 | 447 | ||
| 435 | const enc_result = try kp.public_key.encaps(&randomness); | 448 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 436 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 449 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 437 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 450 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 438 | 451 | ||
| ... | @@ -456,7 +469,7 @@ test "MLKEM768-X25519 test vector 2" { | ... | @@ -456,7 +469,7 @@ test "MLKEM768-X25519 test vector 2" { |
| 456 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); | 469 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); |
| 457 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 470 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 458 | 471 | ||
| 459 | const enc_result = try kp.public_key.encaps(&randomness); | 472 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 460 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 473 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 461 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 474 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 462 | 475 | ||
| ... | @@ -480,7 +493,7 @@ test "MLKEM768-X25519 test vector 3" { | ... | @@ -480,7 +493,7 @@ test "MLKEM768-X25519 test vector 3" { |
| 480 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); | 493 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); |
| 481 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 494 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 482 | 495 | ||
| 483 | const enc_result = try kp.public_key.encaps(&randomness); | 496 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 484 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 497 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 485 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 498 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 486 | 499 | ||
| ... | @@ -504,7 +517,7 @@ test "MLKEM768-X25519 test vector 4" { | ... | @@ -504,7 +517,7 @@ test "MLKEM768-X25519 test vector 4" { |
| 504 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); | 517 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); |
| 505 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 518 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 506 | 519 | ||
| 507 | const enc_result = try kp.public_key.encaps(&randomness); | 520 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 508 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 521 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 509 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 522 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 510 | 523 | ||
| ... | @@ -528,7 +541,7 @@ test "MLKEM768-X25519 test vector 5" { | ... | @@ -528,7 +541,7 @@ test "MLKEM768-X25519 test vector 5" { |
| 528 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); | 541 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); |
| 529 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 542 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 530 | 543 | ||
| 531 | const enc_result = try kp.public_key.encaps(&randomness); | 544 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 532 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 545 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 533 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 546 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 534 | 547 | ||
| ... | @@ -552,7 +565,7 @@ test "MLKEM768-X25519 test vector 6" { | ... | @@ -552,7 +565,7 @@ test "MLKEM768-X25519 test vector 6" { |
| 552 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); | 565 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); |
| 553 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 566 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 554 | 567 | ||
| 555 | const enc_result = try kp.public_key.encaps(&randomness); | 568 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 556 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 569 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 557 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 570 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 558 | 571 | ||
| ... | @@ -576,7 +589,7 @@ test "MLKEM768-X25519 test vector 7" { | ... | @@ -576,7 +589,7 @@ test "MLKEM768-X25519 test vector 7" { |
| 576 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); | 589 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); |
| 577 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 590 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 578 | 591 | ||
| 579 | const enc_result = try kp.public_key.encaps(&randomness); | 592 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 580 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 593 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 581 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 594 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 582 | 595 | ||
| ... | @@ -600,7 +613,7 @@ test "MLKEM768-X25519 test vector 8" { | ... | @@ -600,7 +613,7 @@ test "MLKEM768-X25519 test vector 8" { |
| 600 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); | 613 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); |
| 601 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 614 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 602 | 615 | ||
| 603 | const enc_result = try kp.public_key.encaps(&randomness); | 616 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 604 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 617 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 605 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 618 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 606 | 619 | ||
| ... | @@ -624,7 +637,7 @@ test "MLKEM768-X25519 test vector 9" { | ... | @@ -624,7 +637,7 @@ test "MLKEM768-X25519 test vector 9" { |
| 624 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); | 637 | const kp = try MlKem768X25519.KeyPair.generateDeterministic(seed); |
| 625 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 638 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 626 | 639 | ||
| 627 | const enc_result = try kp.public_key.encaps(&randomness); | 640 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 628 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 641 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 629 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 642 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 630 | 643 | ||
| ... | @@ -648,7 +661,7 @@ test "MLKEM768-P256 test vector 0" { | ... | @@ -648,7 +661,7 @@ test "MLKEM768-P256 test vector 0" { |
| 648 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); | 661 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); |
| 649 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 662 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 650 | 663 | ||
| 651 | const enc_result = try kp.public_key.encaps(&randomness); | 664 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 652 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 665 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 653 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 666 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 654 | 667 | ||
| ... | @@ -672,7 +685,7 @@ test "MLKEM768-P256 test vector 1" { | ... | @@ -672,7 +685,7 @@ test "MLKEM768-P256 test vector 1" { |
| 672 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); | 685 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); |
| 673 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 686 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 674 | 687 | ||
| 675 | const enc_result = try kp.public_key.encaps(&randomness); | 688 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 676 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 689 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 677 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 690 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 678 | 691 | ||
| ... | @@ -696,7 +709,7 @@ test "MLKEM768-P256 test vector 2" { | ... | @@ -696,7 +709,7 @@ test "MLKEM768-P256 test vector 2" { |
| 696 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); | 709 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); |
| 697 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 710 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 698 | 711 | ||
| 699 | const enc_result = try kp.public_key.encaps(&randomness); | 712 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 700 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 713 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 701 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 714 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 702 | 715 | ||
| ... | @@ -720,7 +733,7 @@ test "MLKEM768-P256 test vector 3" { | ... | @@ -720,7 +733,7 @@ test "MLKEM768-P256 test vector 3" { |
| 720 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); | 733 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); |
| 721 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 734 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 722 | 735 | ||
| 723 | const enc_result = try kp.public_key.encaps(&randomness); | 736 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 724 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 737 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 725 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 738 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 726 | 739 | ||
| ... | @@ -744,7 +757,7 @@ test "MLKEM768-P256 test vector 4" { | ... | @@ -744,7 +757,7 @@ test "MLKEM768-P256 test vector 4" { |
| 744 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); | 757 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); |
| 745 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 758 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 746 | 759 | ||
| 747 | const enc_result = try kp.public_key.encaps(&randomness); | 760 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 748 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 761 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 749 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 762 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 750 | 763 | ||
| ... | @@ -768,7 +781,7 @@ test "MLKEM768-P256 test vector 5" { | ... | @@ -768,7 +781,7 @@ test "MLKEM768-P256 test vector 5" { |
| 768 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); | 781 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); |
| 769 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 782 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 770 | 783 | ||
| 771 | const enc_result = try kp.public_key.encaps(&randomness); | 784 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 772 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 785 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 773 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 786 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 774 | 787 | ||
| ... | @@ -792,7 +805,7 @@ test "MLKEM768-P256 test vector 6" { | ... | @@ -792,7 +805,7 @@ test "MLKEM768-P256 test vector 6" { |
| 792 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); | 805 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); |
| 793 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 806 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 794 | 807 | ||
| 795 | const enc_result = try kp.public_key.encaps(&randomness); | 808 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 796 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 809 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 797 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 810 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 798 | 811 | ||
| ... | @@ -816,7 +829,7 @@ test "MLKEM768-P256 test vector 7" { | ... | @@ -816,7 +829,7 @@ test "MLKEM768-P256 test vector 7" { |
| 816 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); | 829 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); |
| 817 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 830 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 818 | 831 | ||
| 819 | const enc_result = try kp.public_key.encaps(&randomness); | 832 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 820 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 833 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 821 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 834 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 822 | 835 | ||
| ... | @@ -840,7 +853,7 @@ test "MLKEM768-P256 test vector 8" { | ... | @@ -840,7 +853,7 @@ test "MLKEM768-P256 test vector 8" { |
| 840 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); | 853 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); |
| 841 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 854 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 842 | 855 | ||
| 843 | const enc_result = try kp.public_key.encaps(&randomness); | 856 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 844 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 857 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 845 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 858 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 846 | 859 | ||
| ... | @@ -864,7 +877,7 @@ test "MLKEM768-P256 test vector 9" { | ... | @@ -864,7 +877,7 @@ test "MLKEM768-P256 test vector 9" { |
| 864 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); | 877 | const kp = try MlKem768P256.KeyPair.generateDeterministic(seed); |
| 865 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 878 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 866 | 879 | ||
| 867 | const enc_result = try kp.public_key.encaps(&randomness); | 880 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 868 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 881 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 869 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 882 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 870 | 883 | ||
| ... | @@ -888,7 +901,7 @@ test "MLKEM1024-P384 test vector 0" { | ... | @@ -888,7 +901,7 @@ test "MLKEM1024-P384 test vector 0" { |
| 888 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); | 901 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); |
| 889 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 902 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 890 | 903 | ||
| 891 | const enc_result = try kp.public_key.encaps(&randomness); | 904 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 892 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 905 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 893 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 906 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 894 | 907 | ||
| ... | @@ -912,7 +925,7 @@ test "MLKEM1024-P384 test vector 1" { | ... | @@ -912,7 +925,7 @@ test "MLKEM1024-P384 test vector 1" { |
| 912 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); | 925 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); |
| 913 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 926 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 914 | 927 | ||
| 915 | const enc_result = try kp.public_key.encaps(&randomness); | 928 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 916 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 929 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 917 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 930 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 918 | 931 | ||
| ... | @@ -936,7 +949,7 @@ test "MLKEM1024-P384 test vector 2" { | ... | @@ -936,7 +949,7 @@ test "MLKEM1024-P384 test vector 2" { |
| 936 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); | 949 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); |
| 937 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 950 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 938 | 951 | ||
| 939 | const enc_result = try kp.public_key.encaps(&randomness); | 952 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 940 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 953 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 941 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 954 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 942 | 955 | ||
| ... | @@ -960,7 +973,7 @@ test "MLKEM1024-P384 test vector 3" { | ... | @@ -960,7 +973,7 @@ test "MLKEM1024-P384 test vector 3" { |
| 960 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); | 973 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); |
| 961 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 974 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 962 | 975 | ||
| 963 | const enc_result = try kp.public_key.encaps(&randomness); | 976 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 964 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 977 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 965 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 978 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 966 | 979 | ||
| ... | @@ -984,7 +997,7 @@ test "MLKEM1024-P384 test vector 4" { | ... | @@ -984,7 +997,7 @@ test "MLKEM1024-P384 test vector 4" { |
| 984 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); | 997 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); |
| 985 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 998 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 986 | 999 | ||
| 987 | const enc_result = try kp.public_key.encaps(&randomness); | 1000 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 988 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 1001 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 989 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 1002 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 990 | 1003 | ||
| ... | @@ -1008,7 +1021,7 @@ test "MLKEM1024-P384 test vector 5" { | ... | @@ -1008,7 +1021,7 @@ test "MLKEM1024-P384 test vector 5" { |
| 1008 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); | 1021 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); |
| 1009 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 1022 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 1010 | 1023 | ||
| 1011 | const enc_result = try kp.public_key.encaps(&randomness); | 1024 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 1012 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 1025 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 1013 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 1026 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 1014 | 1027 | ||
| ... | @@ -1032,7 +1045,7 @@ test "MLKEM1024-P384 test vector 6" { | ... | @@ -1032,7 +1045,7 @@ test "MLKEM1024-P384 test vector 6" { |
| 1032 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); | 1045 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); |
| 1033 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 1046 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 1034 | 1047 | ||
| 1035 | const enc_result = try kp.public_key.encaps(&randomness); | 1048 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 1036 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 1049 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 1037 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 1050 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 1038 | 1051 | ||
| ... | @@ -1056,7 +1069,7 @@ test "MLKEM1024-P384 test vector 7" { | ... | @@ -1056,7 +1069,7 @@ test "MLKEM1024-P384 test vector 7" { |
| 1056 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); | 1069 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); |
| 1057 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 1070 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 1058 | 1071 | ||
| 1059 | const enc_result = try kp.public_key.encaps(&randomness); | 1072 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 1060 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 1073 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 1061 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 1074 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 1062 | 1075 | ||
| ... | @@ -1080,7 +1093,7 @@ test "MLKEM1024-P384 test vector 8" { | ... | @@ -1080,7 +1093,7 @@ test "MLKEM1024-P384 test vector 8" { |
| 1080 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); | 1093 | const kp = try MlKem1024P384.KeyPair.generateDeterministic(seed); |
| 1081 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); | 1094 | try testing.expectEqualSlices(u8, &expected_ek, &kp.public_key.toBytes()); |
| 1082 | 1095 | ||
| 1083 | const enc_result = try kp.public_key.encaps(&randomness); | 1096 | const enc_result = try kp.public_key.encapsDeterministic(&randomness); |
| 1084 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); | 1097 | try testing.expectEqualSlices(u8, &expected_ct, &enc_result.ciphertext); |
| 1085 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); | 1098 | try testing.expectEqualSlices(u8, &expected_ss, &enc_result.shared_secret); |
| 1086 | 1099 |
lib/std/crypto/ml_dsa.zig+10-9| ... | @@ -2019,12 +2019,9 @@ fn MLDSAImpl(comptime p: Params) type { | ... | @@ -2019,12 +2019,9 @@ fn MLDSAImpl(comptime p: Params) type { |
| 2019 | secret_key: SecretKey, | 2019 | secret_key: SecretKey, |
| 2020 | 2020 | ||
| 2021 | /// Generate a new random key pair. | 2021 | /// Generate a new random key pair. |
| 2022 | /// This uses the system's cryptographically secure random number generator. | 2022 | pub fn generate(io: std.Io) KeyPair { |
| 2023 | /// | ||
| 2024 | /// `crypto.random.bytes` must be supported by the target. | ||
| 2025 | pub fn generate() KeyPair { | ||
| 2026 | var seed: [Self.seed_length]u8 = undefined; | 2023 | var seed: [Self.seed_length]u8 = undefined; |
| 2027 | crypto.random.bytes(&seed); | 2024 | io.random(&seed); |
| 2028 | return generateDeterministic(seed) catch unreachable; | 2025 | return generateDeterministic(seed) catch unreachable; |
| 2029 | } | 2026 | } |
| 2030 | 2027 | ||
| ... | @@ -3198,8 +3195,9 @@ test "ML-DSA-87 KAT test vector 0" { | ... | @@ -3198,8 +3195,9 @@ test "ML-DSA-87 KAT test vector 0" { |
| 3198 | } | 3195 | } |
| 3199 | 3196 | ||
| 3200 | test "KeyPair API - generate and sign" { | 3197 | test "KeyPair API - generate and sign" { |
| 3198 | const io = std.testing.io; | ||
| 3201 | // Test the new KeyPair API with random generation | 3199 | // Test the new KeyPair API with random generation |
| 3202 | const kp = MLDSA44.KeyPair.generate(); | 3200 | const kp = MLDSA44.KeyPair.generate(io); |
| 3203 | const msg = "Test message for KeyPair API"; | 3201 | const msg = "Test message for KeyPair API"; |
| 3204 | 3202 | ||
| 3205 | // Sign with deterministic mode (no noise) | 3203 | // Sign with deterministic mode (no noise) |
| ... | @@ -3222,8 +3220,9 @@ test "KeyPair API - generateDeterministic" { | ... | @@ -3222,8 +3220,9 @@ test "KeyPair API - generateDeterministic" { |
| 3222 | } | 3220 | } |
| 3223 | 3221 | ||
| 3224 | test "KeyPair API - fromSecretKey" { | 3222 | test "KeyPair API - fromSecretKey" { |
| 3223 | const io = std.testing.io; | ||
| 3225 | // Generate a key pair | 3224 | // Generate a key pair |
| 3226 | const kp1 = MLDSA44.KeyPair.generate(); | 3225 | const kp1 = MLDSA44.KeyPair.generate(io); |
| 3227 | 3226 | ||
| 3228 | // Derive public key from secret key | 3227 | // Derive public key from secret key |
| 3229 | const kp2 = try MLDSA44.KeyPair.fromSecretKey(kp1.secret_key); | 3228 | const kp2 = try MLDSA44.KeyPair.fromSecretKey(kp1.secret_key); |
| ... | @@ -3235,8 +3234,9 @@ test "KeyPair API - fromSecretKey" { | ... | @@ -3235,8 +3234,9 @@ test "KeyPair API - fromSecretKey" { |
| 3235 | } | 3234 | } |
| 3236 | 3235 | ||
| 3237 | test "Signature verification with noise" { | 3236 | test "Signature verification with noise" { |
| 3237 | const io = std.testing.io; | ||
| 3238 | // Test signing with randomness (hedged signatures) | 3238 | // Test signing with randomness (hedged signatures) |
| 3239 | const kp = MLDSA65.KeyPair.generate(); | 3239 | const kp = MLDSA65.KeyPair.generate(io); |
| 3240 | const msg = "Message to be signed with randomness"; | 3240 | const msg = "Message to be signed with randomness"; |
| 3241 | 3241 | ||
| 3242 | // Create some noise | 3242 | // Create some noise |
| ... | @@ -3250,8 +3250,9 @@ test "Signature verification with noise" { | ... | @@ -3250,8 +3250,9 @@ test "Signature verification with noise" { |
| 3250 | } | 3250 | } |
| 3251 | 3251 | ||
| 3252 | test "Signature verification failure" { | 3252 | test "Signature verification failure" { |
| 3253 | const io = std.testing.io; | ||
| 3253 | // Test that invalid signatures are rejected | 3254 | // Test that invalid signatures are rejected |
| 3254 | const kp = MLDSA44.KeyPair.generate(); | 3255 | const kp = MLDSA44.KeyPair.generate(io); |
| 3255 | const msg = "Original message"; | 3256 | const msg = "Original message"; |
| 3256 | const sig = try kp.sign(msg, null); | 3257 | const sig = try kp.sign(msg, null); |
| 3257 | 3258 |
lib/std/crypto/ml_kem.zig+29-20| ... | @@ -244,32 +244,41 @@ fn Kyber(comptime p: Params) type { | ... | @@ -244,32 +244,41 @@ fn Kyber(comptime p: Params) type { |
| 244 | /// Size of a serialized representation of the key, in bytes. | 244 | /// Size of a serialized representation of the key, in bytes. |
| 245 | pub const encoded_length = InnerPk.encoded_length; | 245 | pub const encoded_length = InnerPk.encoded_length; |
| 246 | 246 | ||
| 247 | /// Generates a shared secret, and encapsulates it for the public key. | 247 | /// Generates a shared secret, encapsulated for the public key, |
| 248 | /// If `seed` is `null`, a random seed is used. This is recommended. | 248 | /// using random bytes. |
| 249 | /// If `seed` is set, encapsulation is deterministic. | 249 | /// |
| 250 | pub fn encaps(pk: PublicKey, seed_: ?[encaps_seed_length]u8) EncapsulatedSecret { | 250 | /// This is recommended over `encapsDeterministic`. |
| 251 | pub fn encaps(pk: PublicKey, io: std.Io) EncapsulatedSecret { | ||
| 251 | var m: [inner_plaintext_length]u8 = undefined; | 252 | var m: [inner_plaintext_length]u8 = undefined; |
| 253 | io.random(&m); | ||
| 254 | return encapsInner(pk, &m); | ||
| 255 | } | ||
| 252 | 256 | ||
| 253 | if (seed_) |seed| { | 257 | /// Generates a shared secret, encapsulated for the public key, |
| 254 | if (p.ml_kem) { | 258 | /// using the provided seed. |
| 255 | @memcpy(&m, &seed); | 259 | /// |
| 256 | } else { | 260 | /// Calling `encaps` instead is recommended. |
| 257 | // m = H(seed) | 261 | pub fn encapsDeterministic(pk: PublicKey, seed: *const [encaps_seed_length]u8) EncapsulatedSecret { |
| 258 | sha3.Sha3_256.hash(&seed, &m, .{}); | 262 | var m: [inner_plaintext_length]u8 = undefined; |
| 259 | } | 263 | if (p.ml_kem) { |
| 264 | @memcpy(&m, seed); | ||
| 260 | } else { | 265 | } else { |
| 261 | crypto.random.bytes(&m); | 266 | // m = H(seed) |
| 267 | sha3.Sha3_256.hash(seed, &m, .{}); | ||
| 262 | } | 268 | } |
| 269 | return encapsInner(pk, &m); | ||
| 270 | } | ||
| 263 | 271 | ||
| 272 | fn encapsInner(pk: PublicKey, m: *[inner_plaintext_length]u8) EncapsulatedSecret { | ||
| 264 | // (K', r) = G(m ‖ H(pk)) | 273 | // (K', r) = G(m ‖ H(pk)) |
| 265 | var kr: [inner_plaintext_length + h_length]u8 = undefined; | 274 | var kr: [inner_plaintext_length + h_length]u8 = undefined; |
| 266 | var g = sha3.Sha3_512.init(.{}); | 275 | var g = sha3.Sha3_512.init(.{}); |
| 267 | g.update(&m); | 276 | g.update(m); |
| 268 | g.update(&pk.hpk); | 277 | g.update(&pk.hpk); |
| 269 | g.final(&kr); | 278 | g.final(&kr); |
| 270 | 279 | ||
| 271 | // c = innerEncrypt(pk, m, r) | 280 | // c = innerEncrypt(pk, m, r) |
| 272 | const ct = pk.pk.encrypt(&m, kr[32..64]); | 281 | const ct = pk.pk.encrypt(m, kr[32..64]); |
| 273 | 282 | ||
| 274 | if (p.ml_kem) { | 283 | if (p.ml_kem) { |
| 275 | return EncapsulatedSecret{ | 284 | return EncapsulatedSecret{ |
| ... | @@ -398,10 +407,10 @@ fn Kyber(comptime p: Params) type { | ... | @@ -398,10 +407,10 @@ fn Kyber(comptime p: Params) type { |
| 398 | } | 407 | } |
| 399 | 408 | ||
| 400 | /// Generate a new, random key pair. | 409 | /// Generate a new, random key pair. |
| 401 | pub fn generate() KeyPair { | 410 | pub fn generate(io: std.Io) KeyPair { |
| 402 | var random_seed: [seed_length]u8 = undefined; | 411 | var random_seed: [seed_length]u8 = undefined; |
| 403 | while (true) { | 412 | while (true) { |
| 404 | crypto.random.bytes(&random_seed); | 413 | io.random(&random_seed); |
| 405 | return generateDeterministic(random_seed) catch { | 414 | return generateDeterministic(random_seed) catch { |
| 406 | @branchHint(.unlikely); | 415 | @branchHint(.unlikely); |
| 407 | continue; | 416 | continue; |
| ... | @@ -1634,15 +1643,15 @@ test "Test happy flow" { | ... | @@ -1634,15 +1643,15 @@ test "Test happy flow" { |
| 1634 | } | 1643 | } |
| 1635 | inline for (modes) |mode| { | 1644 | inline for (modes) |mode| { |
| 1636 | for (0..10) |i| { | 1645 | for (0..10) |i| { |
| 1637 | seed[0] = @as(u8, @intCast(i)); | 1646 | seed[0] = @intCast(i); |
| 1638 | const kp = try mode.KeyPair.generateDeterministic(seed); | 1647 | const kp = try mode.KeyPair.generateDeterministic(seed); |
| 1639 | const sk = try mode.SecretKey.fromBytes(&kp.secret_key.toBytes()); | 1648 | const sk = try mode.SecretKey.fromBytes(&kp.secret_key.toBytes()); |
| 1640 | try testing.expectEqual(sk, kp.secret_key); | 1649 | try testing.expectEqual(sk, kp.secret_key); |
| 1641 | const pk = try mode.PublicKey.fromBytes(&kp.public_key.toBytes()); | 1650 | const pk = try mode.PublicKey.fromBytes(&kp.public_key.toBytes()); |
| 1642 | try testing.expectEqual(pk, kp.public_key); | 1651 | try testing.expectEqual(pk, kp.public_key); |
| 1643 | for (0..10) |j| { | 1652 | for (0..10) |j| { |
| 1644 | seed[1] = @as(u8, @intCast(j)); | 1653 | seed[1] = @intCast(j); |
| 1645 | const e = pk.encaps(seed[0..32].*); | 1654 | const e = pk.encapsDeterministic(seed[0..32]); |
| 1646 | try testing.expectEqual(e.shared_secret, try sk.decaps(&e.ciphertext)); | 1655 | try testing.expectEqual(e.shared_secret, try sk.decaps(&e.ciphertext)); |
| 1647 | } | 1656 | } |
| 1648 | } | 1657 | } |
| ... | @@ -1695,7 +1704,7 @@ fn testNistKat(mode: type, hash: []const u8) !void { | ... | @@ -1695,7 +1704,7 @@ fn testNistKat(mode: type, hash: []const u8) !void { |
| 1695 | g2.fill(kseed[32..64]); | 1704 | g2.fill(kseed[32..64]); |
| 1696 | g2.fill(&eseed); | 1705 | g2.fill(&eseed); |
| 1697 | const kp = try mode.KeyPair.generateDeterministic(kseed); | 1706 | const kp = try mode.KeyPair.generateDeterministic(kseed); |
| 1698 | const e = kp.public_key.encaps(eseed); | 1707 | const e = kp.public_key.encapsDeterministic(&eseed); |
| 1699 | const ss2 = try kp.secret_key.decaps(&e.ciphertext); | 1708 | const ss2 = try kp.secret_key.decaps(&e.ciphertext); |
| 1700 | try testing.expectEqual(ss2, e.shared_secret); | 1709 | try testing.expectEqual(ss2, e.shared_secret); |
| 1701 | try fw.writer.print("pk = {X}\n", .{&kp.public_key.toBytes()}); | 1710 | try fw.writer.print("pk = {X}\n", .{&kp.public_key.toBytes()}); |
lib/std/crypto/pcurves/p256.zig+2-2| ... | @@ -122,8 +122,8 @@ pub const P256 = struct { | ... | @@ -122,8 +122,8 @@ pub const P256 = struct { |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | /// Return a random point. | 124 | /// Return a random point. |
| 125 | pub fn random() P256 { | 125 | pub fn random(io: std.Io) P256 { |
| 126 | const n = scalar.random(.little); | 126 | const n = scalar.random(io, .little); |
| 127 | return basePoint.mul(n, .little) catch unreachable; | 127 | return basePoint.mul(n, .little) catch unreachable; |
| 128 | } | 128 | } |
| 129 | 129 |
lib/std/crypto/pcurves/p256/scalar.zig+4-4| ... | @@ -68,8 +68,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) | ... | @@ -68,8 +68,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | /// Return a random scalar | 70 | /// Return a random scalar |
| 71 | pub fn random(endian: std.builtin.Endian) CompressedScalar { | 71 | pub fn random(io: std.Io, endian: std.builtin.Endian) CompressedScalar { |
| 72 | return Scalar.random().toBytes(endian); | 72 | return Scalar.random(io).toBytes(endian); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | /// A scalar in unpacked representation. | 75 | /// A scalar in unpacked representation. |
| ... | @@ -170,10 +170,10 @@ pub const Scalar = struct { | ... | @@ -170,10 +170,10 @@ pub const Scalar = struct { |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | /// Return a random scalar < L. | 172 | /// Return a random scalar < L. |
| 173 | pub fn random() Scalar { | 173 | pub fn random(io: std.Io) Scalar { |
| 174 | var s: [48]u8 = undefined; | 174 | var s: [48]u8 = undefined; |
| 175 | while (true) { | 175 | while (true) { |
| 176 | crypto.random.bytes(&s); | 176 | io.random(&s); |
| 177 | const n = Scalar.fromBytes48(s, .little); | 177 | const n = Scalar.fromBytes48(s, .little); |
| 178 | if (!n.isZero()) { | 178 | if (!n.isZero()) { |
| 179 | return n; | 179 | return n; |
lib/std/crypto/pcurves/p384.zig+2-2| ... | @@ -122,8 +122,8 @@ pub const P384 = struct { | ... | @@ -122,8 +122,8 @@ pub const P384 = struct { |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | /// Return a random point. | 124 | /// Return a random point. |
| 125 | pub fn random() P384 { | 125 | pub fn random(io: std.Io) P384 { |
| 126 | const n = scalar.random(.little); | 126 | const n = scalar.random(io, .little); |
| 127 | return basePoint.mul(n, .little) catch unreachable; | 127 | return basePoint.mul(n, .little) catch unreachable; |
| 128 | } | 128 | } |
| 129 | 129 |
lib/std/crypto/pcurves/p384/scalar.zig+4-4| ... | @@ -63,8 +63,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) | ... | @@ -63,8 +63,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | /// Return a random scalar | 65 | /// Return a random scalar |
| 66 | pub fn random(endian: std.builtin.Endian) CompressedScalar { | 66 | pub fn random(io: std.Io, endian: std.builtin.Endian) CompressedScalar { |
| 67 | return Scalar.random().toBytes(endian); | 67 | return Scalar.random(io).toBytes(endian); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | /// A scalar in unpacked representation. | 70 | /// A scalar in unpacked representation. |
| ... | @@ -159,10 +159,10 @@ pub const Scalar = struct { | ... | @@ -159,10 +159,10 @@ pub const Scalar = struct { |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | /// Return a random scalar < L. | 161 | /// Return a random scalar < L. |
| 162 | pub fn random() Scalar { | 162 | pub fn random(io: std.Io) Scalar { |
| 163 | var s: [64]u8 = undefined; | 163 | var s: [64]u8 = undefined; |
| 164 | while (true) { | 164 | while (true) { |
| 165 | crypto.random.bytes(&s); | 165 | io.random(&s); |
| 166 | const n = Scalar.fromBytes64(s, .little); | 166 | const n = Scalar.fromBytes64(s, .little); |
| 167 | if (!n.isZero()) { | 167 | if (!n.isZero()) { |
| 168 | return n; | 168 | return n; |
lib/std/crypto/pcurves/secp256k1.zig+2-2| ... | @@ -175,8 +175,8 @@ pub const Secp256k1 = struct { | ... | @@ -175,8 +175,8 @@ pub const Secp256k1 = struct { |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | /// Return a random point. | 177 | /// Return a random point. |
| 178 | pub fn random() Secp256k1 { | 178 | pub fn random(io: std.Io) Secp256k1 { |
| 179 | const n = scalar.random(.little); | 179 | const n = scalar.random(io, .little); |
| 180 | return basePoint.mul(n, .little) catch unreachable; | 180 | return basePoint.mul(n, .little) catch unreachable; |
| 181 | } | 181 | } |
| 182 | 182 |
lib/std/crypto/pcurves/secp256k1/scalar.zig+4-4| ... | @@ -68,8 +68,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) | ... | @@ -68,8 +68,8 @@ pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: std.builtin.Endian) |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | /// Return a random scalar | 70 | /// Return a random scalar |
| 71 | pub fn random(endian: std.builtin.Endian) CompressedScalar { | 71 | pub fn random(io: std.Io, endian: std.builtin.Endian) CompressedScalar { |
| 72 | return Scalar.random().toBytes(endian); | 72 | return Scalar.random(io).toBytes(endian); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | /// A scalar in unpacked representation. | 75 | /// A scalar in unpacked representation. |
| ... | @@ -170,10 +170,10 @@ pub const Scalar = struct { | ... | @@ -170,10 +170,10 @@ pub const Scalar = struct { |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | /// Return a random scalar < L. | 172 | /// Return a random scalar < L. |
| 173 | pub fn random() Scalar { | 173 | pub fn random(io: std.Io) Scalar { |
| 174 | var s: [48]u8 = undefined; | 174 | var s: [48]u8 = undefined; |
| 175 | while (true) { | 175 | while (true) { |
| 176 | crypto.random.bytes(&s); | 176 | io.random(&s); |
| 177 | const n = Scalar.fromBytes48(s, .little); | 177 | const n = Scalar.fromBytes48(s, .little); |
| 178 | if (!n.isZero()) { | 178 | if (!n.isZero()) { |
| 179 | return n; | 179 | return n; |
lib/std/crypto/pcurves/tests/p256.zig+11-6| ... | @@ -5,8 +5,9 @@ const testing = std.testing; | ... | @@ -5,8 +5,9 @@ const testing = std.testing; |
| 5 | const P256 = @import("../p256.zig").P256; | 5 | const P256 = @import("../p256.zig").P256; |
| 6 | 6 | ||
| 7 | test "p256 ECDH key exchange" { | 7 | test "p256 ECDH key exchange" { |
| 8 | const dha = P256.scalar.random(.little); | 8 | const io = testing.io; |
| 9 | const dhb = P256.scalar.random(.little); | 9 | const dha = P256.scalar.random(io, .little); |
| 10 | const dhb = P256.scalar.random(io, .little); | ||
| 10 | const dhA = try P256.basePoint.mul(dha, .little); | 11 | const dhA = try P256.basePoint.mul(dha, .little); |
| 11 | const dhB = try P256.basePoint.mul(dhb, .little); | 12 | const dhB = try P256.basePoint.mul(dhb, .little); |
| 12 | const shareda = try dhA.mul(dhb, .little); | 13 | const shareda = try dhA.mul(dhb, .little); |
| ... | @@ -66,28 +67,32 @@ test "p256 test vectors - doubling" { | ... | @@ -66,28 +67,32 @@ test "p256 test vectors - doubling" { |
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | test "p256 compressed sec1 encoding/decoding" { | 69 | test "p256 compressed sec1 encoding/decoding" { |
| 69 | const p = P256.random(); | 70 | const io = testing.io; |
| 71 | const p = P256.random(io); | ||
| 70 | const s = p.toCompressedSec1(); | 72 | const s = p.toCompressedSec1(); |
| 71 | const q = try P256.fromSec1(&s); | 73 | const q = try P256.fromSec1(&s); |
| 72 | try testing.expect(p.equivalent(q)); | 74 | try testing.expect(p.equivalent(q)); |
| 73 | } | 75 | } |
| 74 | 76 | ||
| 75 | test "p256 uncompressed sec1 encoding/decoding" { | 77 | test "p256 uncompressed sec1 encoding/decoding" { |
| 76 | const p = P256.random(); | 78 | const io = testing.io; |
| 79 | const p = P256.random(io); | ||
| 77 | const s = p.toUncompressedSec1(); | 80 | const s = p.toUncompressedSec1(); |
| 78 | const q = try P256.fromSec1(&s); | 81 | const q = try P256.fromSec1(&s); |
| 79 | try testing.expect(p.equivalent(q)); | 82 | try testing.expect(p.equivalent(q)); |
| 80 | } | 83 | } |
| 81 | 84 | ||
| 82 | test "p256 public key is the neutral element" { | 85 | test "p256 public key is the neutral element" { |
| 86 | const io = testing.io; | ||
| 83 | const n = P256.scalar.Scalar.zero.toBytes(.little); | 87 | const n = P256.scalar.Scalar.zero.toBytes(.little); |
| 84 | const p = P256.random(); | 88 | const p = P256.random(io); |
| 85 | try testing.expectError(error.IdentityElement, p.mul(n, .little)); | 89 | try testing.expectError(error.IdentityElement, p.mul(n, .little)); |
| 86 | } | 90 | } |
| 87 | 91 | ||
| 88 | test "p256 public key is the neutral element (public verification)" { | 92 | test "p256 public key is the neutral element (public verification)" { |
| 93 | const io = testing.io; | ||
| 89 | const n = P256.scalar.Scalar.zero.toBytes(.little); | 94 | const n = P256.scalar.Scalar.zero.toBytes(.little); |
| 90 | const p = P256.random(); | 95 | const p = P256.random(io); |
| 91 | try testing.expectError(error.IdentityElement, p.mulPublic(n, .little)); | 96 | try testing.expectError(error.IdentityElement, p.mulPublic(n, .little)); |
| 92 | } | 97 | } |
| 93 | 98 |
lib/std/crypto/pcurves/tests/p384.zig+11-6| ... | @@ -5,8 +5,9 @@ const testing = std.testing; | ... | @@ -5,8 +5,9 @@ const testing = std.testing; |
| 5 | const P384 = @import("../p384.zig").P384; | 5 | const P384 = @import("../p384.zig").P384; |
| 6 | 6 | ||
| 7 | test "p384 ECDH key exchange" { | 7 | test "p384 ECDH key exchange" { |
| 8 | const dha = P384.scalar.random(.little); | 8 | const io = testing.io; |
| 9 | const dhb = P384.scalar.random(.little); | 9 | const dha = P384.scalar.random(io, .little); |
| 10 | const dhb = P384.scalar.random(io, .little); | ||
| 10 | const dhA = try P384.basePoint.mul(dha, .little); | 11 | const dhA = try P384.basePoint.mul(dha, .little); |
| 11 | const dhB = try P384.basePoint.mul(dhb, .little); | 12 | const dhB = try P384.basePoint.mul(dhb, .little); |
| 12 | const shareda = try dhA.mul(dhb, .little); | 13 | const shareda = try dhA.mul(dhb, .little); |
| ... | @@ -67,7 +68,8 @@ test "p384 test vectors - doubling" { | ... | @@ -67,7 +68,8 @@ test "p384 test vectors - doubling" { |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 69 | test "p384 compressed sec1 encoding/decoding" { | 70 | test "p384 compressed sec1 encoding/decoding" { |
| 70 | const p = P384.random(); | 71 | const io = testing.io; |
| 72 | const p = P384.random(io); | ||
| 71 | const s0 = p.toUncompressedSec1(); | 73 | const s0 = p.toUncompressedSec1(); |
| 72 | const s = p.toCompressedSec1(); | 74 | const s = p.toCompressedSec1(); |
| 73 | try testing.expectEqualSlices(u8, s0[1..49], s[1..49]); | 75 | try testing.expectEqualSlices(u8, s0[1..49], s[1..49]); |
| ... | @@ -76,21 +78,24 @@ test "p384 compressed sec1 encoding/decoding" { | ... | @@ -76,21 +78,24 @@ test "p384 compressed sec1 encoding/decoding" { |
| 76 | } | 78 | } |
| 77 | 79 | ||
| 78 | test "p384 uncompressed sec1 encoding/decoding" { | 80 | test "p384 uncompressed sec1 encoding/decoding" { |
| 79 | const p = P384.random(); | 81 | const io = testing.io; |
| 82 | const p = P384.random(io); | ||
| 80 | const s = p.toUncompressedSec1(); | 83 | const s = p.toUncompressedSec1(); |
| 81 | const q = try P384.fromSec1(&s); | 84 | const q = try P384.fromSec1(&s); |
| 82 | try testing.expect(p.equivalent(q)); | 85 | try testing.expect(p.equivalent(q)); |
| 83 | } | 86 | } |
| 84 | 87 | ||
| 85 | test "p384 public key is the neutral element" { | 88 | test "p384 public key is the neutral element" { |
| 89 | const io = testing.io; | ||
| 86 | const n = P384.scalar.Scalar.zero.toBytes(.little); | 90 | const n = P384.scalar.Scalar.zero.toBytes(.little); |
| 87 | const p = P384.random(); | 91 | const p = P384.random(io); |
| 88 | try testing.expectError(error.IdentityElement, p.mul(n, .little)); | 92 | try testing.expectError(error.IdentityElement, p.mul(n, .little)); |
| 89 | } | 93 | } |
| 90 | 94 | ||
| 91 | test "p384 public key is the neutral element (public verification)" { | 95 | test "p384 public key is the neutral element (public verification)" { |
| 96 | const io = testing.io; | ||
| 92 | const n = P384.scalar.Scalar.zero.toBytes(.little); | 97 | const n = P384.scalar.Scalar.zero.toBytes(.little); |
| 93 | const p = P384.random(); | 98 | const p = P384.random(io); |
| 94 | try testing.expectError(error.IdentityElement, p.mulPublic(n, .little)); | 99 | try testing.expectError(error.IdentityElement, p.mulPublic(n, .little)); |
| 95 | } | 100 | } |
| 96 | 101 |
lib/std/crypto/pcurves/tests/secp256k1.zig+14-8| ... | @@ -5,8 +5,9 @@ const testing = std.testing; | ... | @@ -5,8 +5,9 @@ const testing = std.testing; |
| 5 | const Secp256k1 = @import("../secp256k1.zig").Secp256k1; | 5 | const Secp256k1 = @import("../secp256k1.zig").Secp256k1; |
| 6 | 6 | ||
| 7 | test "secp256k1 ECDH key exchange" { | 7 | test "secp256k1 ECDH key exchange" { |
| 8 | const dha = Secp256k1.scalar.random(.little); | 8 | const io = testing.io; |
| 9 | const dhb = Secp256k1.scalar.random(.little); | 9 | const dha = Secp256k1.scalar.random(io, .little); |
| 10 | const dhb = Secp256k1.scalar.random(io, .little); | ||
| 10 | const dhA = try Secp256k1.basePoint.mul(dha, .little); | 11 | const dhA = try Secp256k1.basePoint.mul(dha, .little); |
| 11 | const dhB = try Secp256k1.basePoint.mul(dhb, .little); | 12 | const dhB = try Secp256k1.basePoint.mul(dhb, .little); |
| 12 | const shareda = try dhA.mul(dhb, .little); | 13 | const shareda = try dhA.mul(dhb, .little); |
| ... | @@ -15,8 +16,9 @@ test "secp256k1 ECDH key exchange" { | ... | @@ -15,8 +16,9 @@ test "secp256k1 ECDH key exchange" { |
| 15 | } | 16 | } |
| 16 | 17 | ||
| 17 | test "secp256k1 ECDH key exchange including public multiplication" { | 18 | test "secp256k1 ECDH key exchange including public multiplication" { |
| 18 | const dha = Secp256k1.scalar.random(.little); | 19 | const io = testing.io; |
| 19 | const dhb = Secp256k1.scalar.random(.little); | 20 | const dha = Secp256k1.scalar.random(io, .little); |
| 21 | const dhb = Secp256k1.scalar.random(io, .little); | ||
| 20 | const dhA = try Secp256k1.basePoint.mul(dha, .little); | 22 | const dhA = try Secp256k1.basePoint.mul(dha, .little); |
| 21 | const dhB = try Secp256k1.basePoint.mulPublic(dhb, .little); | 23 | const dhB = try Secp256k1.basePoint.mulPublic(dhb, .little); |
| 22 | const shareda = try dhA.mul(dhb, .little); | 24 | const shareda = try dhA.mul(dhb, .little); |
| ... | @@ -77,28 +79,32 @@ test "secp256k1 test vectors - doubling" { | ... | @@ -77,28 +79,32 @@ test "secp256k1 test vectors - doubling" { |
| 77 | } | 79 | } |
| 78 | 80 | ||
| 79 | test "secp256k1 compressed sec1 encoding/decoding" { | 81 | test "secp256k1 compressed sec1 encoding/decoding" { |
| 80 | const p = Secp256k1.random(); | 82 | const io = testing.io; |
| 83 | const p = Secp256k1.random(io); | ||
| 81 | const s = p.toCompressedSec1(); | 84 | const s = p.toCompressedSec1(); |
| 82 | const q = try Secp256k1.fromSec1(&s); | 85 | const q = try Secp256k1.fromSec1(&s); |
| 83 | try testing.expect(p.equivalent(q)); | 86 | try testing.expect(p.equivalent(q)); |
| 84 | } | 87 | } |
| 85 | 88 | ||
| 86 | test "secp256k1 uncompressed sec1 encoding/decoding" { | 89 | test "secp256k1 uncompressed sec1 encoding/decoding" { |
| 87 | const p = Secp256k1.random(); | 90 | const io = testing.io; |
| 91 | const p = Secp256k1.random(io); | ||
| 88 | const s = p.toUncompressedSec1(); | 92 | const s = p.toUncompressedSec1(); |
| 89 | const q = try Secp256k1.fromSec1(&s); | 93 | const q = try Secp256k1.fromSec1(&s); |
| 90 | try testing.expect(p.equivalent(q)); | 94 | try testing.expect(p.equivalent(q)); |
| 91 | } | 95 | } |
| 92 | 96 | ||
| 93 | test "secp256k1 public key is the neutral element" { | 97 | test "secp256k1 public key is the neutral element" { |
| 98 | const io = testing.io; | ||
| 94 | const n = Secp256k1.scalar.Scalar.zero.toBytes(.little); | 99 | const n = Secp256k1.scalar.Scalar.zero.toBytes(.little); |
| 95 | const p = Secp256k1.random(); | 100 | const p = Secp256k1.random(io); |
| 96 | try testing.expectError(error.IdentityElement, p.mul(n, .little)); | 101 | try testing.expectError(error.IdentityElement, p.mul(n, .little)); |
| 97 | } | 102 | } |
| 98 | 103 | ||
| 99 | test "secp256k1 public key is the neutral element (public verification)" { | 104 | test "secp256k1 public key is the neutral element (public verification)" { |
| 105 | const io = testing.io; | ||
| 100 | const n = Secp256k1.scalar.Scalar.zero.toBytes(.little); | 106 | const n = Secp256k1.scalar.Scalar.zero.toBytes(.little); |
| 101 | const p = Secp256k1.random(); | 107 | const p = Secp256k1.random(io); |
| 102 | try testing.expectError(error.IdentityElement, p.mulPublic(n, .little)); | 108 | try testing.expectError(error.IdentityElement, p.mulPublic(n, .little)); |
| 103 | } | 109 | } |
| 104 | 110 |
lib/std/crypto/salsa20.zig+19-15| ... | @@ -533,9 +533,9 @@ pub const SealedBox = struct { | ... | @@ -533,9 +533,9 @@ pub const SealedBox = struct { |
| 533 | 533 | ||
| 534 | /// Encrypt a message `m` for a recipient whose public key is `public_key`. | 534 | /// Encrypt a message `m` for a recipient whose public key is `public_key`. |
| 535 | /// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added. | 535 | /// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added. |
| 536 | pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) (WeakPublicKeyError || IdentityElementError)!void { | 536 | pub fn seal(io: std.Io, c: []u8, m: []const u8, public_key: [public_length]u8) (WeakPublicKeyError || IdentityElementError)!void { |
| 537 | debug.assert(c.len == m.len + seal_length); | 537 | debug.assert(c.len == m.len + seal_length); |
| 538 | var ekp = KeyPair.generate(); | 538 | var ekp = KeyPair.generate(io); |
| 539 | const nonce = createNonce(ekp.public_key, public_key); | 539 | const nonce = createNonce(ekp.public_key, public_key); |
| 540 | c[0..public_length].* = ekp.public_key; | 540 | c[0..public_length].* = ekp.public_key; |
| 541 | try Box.seal(c[Box.public_length..], m, nonce, public_key, ekp.secret_key); | 541 | try Box.seal(c[Box.public_length..], m, nonce, public_key, ekp.secret_key); |
| ... | @@ -573,29 +573,31 @@ test "(x)salsa20" { | ... | @@ -573,29 +573,31 @@ test "(x)salsa20" { |
| 573 | } | 573 | } |
| 574 | 574 | ||
| 575 | test "xsalsa20poly1305" { | 575 | test "xsalsa20poly1305" { |
| 576 | const io = std.testing.io; | ||
| 576 | var msg: [100]u8 = undefined; | 577 | var msg: [100]u8 = undefined; |
| 577 | var msg2: [msg.len]u8 = undefined; | 578 | var msg2: [msg.len]u8 = undefined; |
| 578 | var c: [msg.len]u8 = undefined; | 579 | var c: [msg.len]u8 = undefined; |
| 579 | var key: [XSalsa20Poly1305.key_length]u8 = undefined; | 580 | var key: [XSalsa20Poly1305.key_length]u8 = undefined; |
| 580 | var nonce: [XSalsa20Poly1305.nonce_length]u8 = undefined; | 581 | var nonce: [XSalsa20Poly1305.nonce_length]u8 = undefined; |
| 581 | var tag: [XSalsa20Poly1305.tag_length]u8 = undefined; | 582 | var tag: [XSalsa20Poly1305.tag_length]u8 = undefined; |
| 582 | crypto.random.bytes(&msg); | 583 | io.random(&msg); |
| 583 | crypto.random.bytes(&key); | 584 | io.random(&key); |
| 584 | crypto.random.bytes(&nonce); | 585 | io.random(&nonce); |
| 585 | 586 | ||
| 586 | XSalsa20Poly1305.encrypt(c[0..], &tag, msg[0..], "ad", nonce, key); | 587 | XSalsa20Poly1305.encrypt(c[0..], &tag, msg[0..], "ad", nonce, key); |
| 587 | try XSalsa20Poly1305.decrypt(msg2[0..], c[0..], tag, "ad", nonce, key); | 588 | try XSalsa20Poly1305.decrypt(msg2[0..], c[0..], tag, "ad", nonce, key); |
| 588 | } | 589 | } |
| 589 | 590 | ||
| 590 | test "xsalsa20poly1305 secretbox" { | 591 | test "xsalsa20poly1305 secretbox" { |
| 592 | const io = std.testing.io; | ||
| 591 | var msg: [100]u8 = undefined; | 593 | var msg: [100]u8 = undefined; |
| 592 | var msg2: [msg.len]u8 = undefined; | 594 | var msg2: [msg.len]u8 = undefined; |
| 593 | var key: [XSalsa20Poly1305.key_length]u8 = undefined; | 595 | var key: [XSalsa20Poly1305.key_length]u8 = undefined; |
| 594 | var nonce: [Box.nonce_length]u8 = undefined; | 596 | var nonce: [Box.nonce_length]u8 = undefined; |
| 595 | var boxed: [msg.len + Box.tag_length]u8 = undefined; | 597 | var boxed: [msg.len + Box.tag_length]u8 = undefined; |
| 596 | crypto.random.bytes(&msg); | 598 | io.random(&msg); |
| 597 | crypto.random.bytes(&key); | 599 | io.random(&key); |
| 598 | crypto.random.bytes(&nonce); | 600 | io.random(&nonce); |
| 599 | 601 | ||
| 600 | SecretBox.seal(boxed[0..], msg[0..], nonce, key); | 602 | SecretBox.seal(boxed[0..], msg[0..], nonce, key); |
| 601 | try SecretBox.open(msg2[0..], boxed[0..], nonce, key); | 603 | try SecretBox.open(msg2[0..], boxed[0..], nonce, key); |
| ... | @@ -604,15 +606,16 @@ test "xsalsa20poly1305 secretbox" { | ... | @@ -604,15 +606,16 @@ test "xsalsa20poly1305 secretbox" { |
| 604 | test "xsalsa20poly1305 box" { | 606 | test "xsalsa20poly1305 box" { |
| 605 | if (builtin.cpu.has(.riscv, .v) and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/24299 | 607 | if (builtin.cpu.has(.riscv, .v) and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/24299 |
| 606 | 608 | ||
| 609 | const io = std.testing.io; | ||
| 607 | var msg: [100]u8 = undefined; | 610 | var msg: [100]u8 = undefined; |
| 608 | var msg2: [msg.len]u8 = undefined; | 611 | var msg2: [msg.len]u8 = undefined; |
| 609 | var nonce: [Box.nonce_length]u8 = undefined; | 612 | var nonce: [Box.nonce_length]u8 = undefined; |
| 610 | var boxed: [msg.len + Box.tag_length]u8 = undefined; | 613 | var boxed: [msg.len + Box.tag_length]u8 = undefined; |
| 611 | crypto.random.bytes(&msg); | 614 | io.random(&msg); |
| 612 | crypto.random.bytes(&nonce); | 615 | io.random(&nonce); |
| 613 | 616 | ||
| 614 | const kp1 = Box.KeyPair.generate(); | 617 | const kp1 = Box.KeyPair.generate(io); |
| 615 | const kp2 = Box.KeyPair.generate(); | 618 | const kp2 = Box.KeyPair.generate(io); |
| 616 | try Box.seal(boxed[0..], msg[0..], nonce, kp1.public_key, kp2.secret_key); | 619 | try Box.seal(boxed[0..], msg[0..], nonce, kp1.public_key, kp2.secret_key); |
| 617 | try Box.open(msg2[0..], boxed[0..], nonce, kp2.public_key, kp1.secret_key); | 620 | try Box.open(msg2[0..], boxed[0..], nonce, kp2.public_key, kp1.secret_key); |
| 618 | } | 621 | } |
| ... | @@ -620,13 +623,14 @@ test "xsalsa20poly1305 box" { | ... | @@ -620,13 +623,14 @@ test "xsalsa20poly1305 box" { |
| 620 | test "xsalsa20poly1305 sealedbox" { | 623 | test "xsalsa20poly1305 sealedbox" { |
| 621 | if (builtin.cpu.has(.riscv, .v) and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/24299 | 624 | if (builtin.cpu.has(.riscv, .v) and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/24299 |
| 622 | 625 | ||
| 626 | const io = std.testing.io; | ||
| 623 | var msg: [100]u8 = undefined; | 627 | var msg: [100]u8 = undefined; |
| 624 | var msg2: [msg.len]u8 = undefined; | 628 | var msg2: [msg.len]u8 = undefined; |
| 625 | var boxed: [msg.len + SealedBox.seal_length]u8 = undefined; | 629 | var boxed: [msg.len + SealedBox.seal_length]u8 = undefined; |
| 626 | crypto.random.bytes(&msg); | 630 | io.random(&msg); |
| 627 | 631 | ||
| 628 | const kp = Box.KeyPair.generate(); | 632 | const kp = Box.KeyPair.generate(io); |
| 629 | try SealedBox.seal(boxed[0..], msg[0..], kp.public_key); | 633 | try SealedBox.seal(io, boxed[0..], msg[0..], kp.public_key); |
| 630 | try SealedBox.open(msg2[0..], boxed[0..], kp); | 634 | try SealedBox.open(msg2[0..], boxed[0..], kp); |
| 631 | } | 635 | } |
| 632 | 636 |
lib/std/crypto/scrypt.zig+5-6| ... | @@ -20,7 +20,7 @@ const Error = pwhash.Error; | ... | @@ -20,7 +20,7 @@ const Error = pwhash.Error; |
| 20 | 20 | ||
| 21 | const max_size = math.maxInt(usize); | 21 | const max_size = math.maxInt(usize); |
| 22 | const max_int = max_size >> 1; | 22 | const max_int = max_size >> 1; |
| 23 | const default_salt_len = 32; | 23 | pub const default_salt_len = 32; |
| 24 | const default_hash_len = 32; | 24 | const default_hash_len = 32; |
| 25 | const max_salt_len = 64; | 25 | const max_salt_len = 64; |
| 26 | const max_hash_len = 64; | 26 | const max_hash_len = 64; |
| ... | @@ -417,10 +417,9 @@ const PhcFormatHasher = struct { | ... | @@ -417,10 +417,9 @@ const PhcFormatHasher = struct { |
| 417 | password: []const u8, | 417 | password: []const u8, |
| 418 | params: Params, | 418 | params: Params, |
| 419 | buf: []u8, | 419 | buf: []u8, |
| 420 | /// Filled with cryptographically secure entropy. | ||
| 421 | salt: []const u8, | ||
| 420 | ) HasherError![]const u8 { | 422 | ) HasherError![]const u8 { |
| 421 | var salt: [default_salt_len]u8 = undefined; | ||
| 422 | crypto.random.bytes(&salt); | ||
| 423 | |||
| 424 | var hash: [default_hash_len]u8 = undefined; | 423 | var hash: [default_hash_len]u8 = undefined; |
| 425 | try kdf(allocator, &hash, password, &salt, params); | 424 | try kdf(allocator, &hash, password, &salt, params); |
| 426 | 425 | ||
| ... | @@ -466,9 +465,9 @@ const CryptFormatHasher = struct { | ... | @@ -466,9 +465,9 @@ const CryptFormatHasher = struct { |
| 466 | password: []const u8, | 465 | password: []const u8, |
| 467 | params: Params, | 466 | params: Params, |
| 468 | buf: []u8, | 467 | buf: []u8, |
| 468 | /// Filled with cryptographically secure entropy. | ||
| 469 | salt_bin: []const u8, | ||
| 469 | ) HasherError![]const u8 { | 470 | ) HasherError![]const u8 { |
| 470 | var salt_bin: [default_salt_len]u8 = undefined; | ||
| 471 | crypto.random.bytes(&salt_bin); | ||
| 472 | const salt = crypt_format.saltFromBin(salt_bin.len, salt_bin); | 471 | const salt = crypt_format.saltFromBin(salt_bin.len, salt_bin); |
| 473 | 472 | ||
| 474 | var hash: [default_hash_len]u8 = undefined; | 473 | var hash: [default_hash_len]u8 = undefined; |
lib/std/crypto/timing_safe.zig+12-11| ... | @@ -180,24 +180,24 @@ pub fn declassify(ptr: anytype) void { | ... | @@ -180,24 +180,24 @@ pub fn declassify(ptr: anytype) void { |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | test eql { | 182 | test eql { |
| 183 | const random = std.crypto.random; | 183 | const io = std.testing.io; |
| 184 | const expect = std.testing.expect; | 184 | const expect = std.testing.expect; |
| 185 | var a: [100]u8 = undefined; | 185 | var a: [100]u8 = undefined; |
| 186 | var b: [100]u8 = undefined; | 186 | var b: [100]u8 = undefined; |
| 187 | random.bytes(a[0..]); | 187 | io.random(&a); |
| 188 | random.bytes(b[0..]); | 188 | io.random(&b); |
| 189 | try expect(!eql([100]u8, a, b)); | 189 | try expect(!eql([100]u8, a, b)); |
| 190 | a = b; | 190 | a = b; |
| 191 | try expect(eql([100]u8, a, b)); | 191 | try expect(eql([100]u8, a, b)); |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | test "eql (vectors)" { | 194 | test "eql (vectors)" { |
| 195 | const random = std.crypto.random; | 195 | const io = std.testing.io; |
| 196 | const expect = std.testing.expect; | 196 | const expect = std.testing.expect; |
| 197 | var a: [100]u8 = undefined; | 197 | var a: [100]u8 = undefined; |
| 198 | var b: [100]u8 = undefined; | 198 | var b: [100]u8 = undefined; |
| 199 | random.bytes(a[0..]); | 199 | io.random(&a); |
| 200 | random.bytes(b[0..]); | 200 | io.random(&b); |
| 201 | const v1: @Vector(100, u8) = a; | 201 | const v1: @Vector(100, u8) = a; |
| 202 | const v2: @Vector(100, u8) = b; | 202 | const v2: @Vector(100, u8) = b; |
| 203 | try expect(!eql(@Vector(100, u8), v1, v2)); | 203 | try expect(!eql(@Vector(100, u8), v1, v2)); |
| ... | @@ -220,9 +220,10 @@ test compare { | ... | @@ -220,9 +220,10 @@ test compare { |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | test "add and sub" { | 222 | test "add and sub" { |
| 223 | const io = std.testing.io; | ||
| 224 | |||
| 223 | const expectEqual = std.testing.expectEqual; | 225 | const expectEqual = std.testing.expectEqual; |
| 224 | const expectEqualSlices = std.testing.expectEqualSlices; | 226 | const expectEqualSlices = std.testing.expectEqualSlices; |
| 225 | const random = std.crypto.random; | ||
| 226 | const len = 32; | 227 | const len = 32; |
| 227 | var a: [len]u8 = undefined; | 228 | var a: [len]u8 = undefined; |
| 228 | var b: [len]u8 = undefined; | 229 | var b: [len]u8 = undefined; |
| ... | @@ -230,8 +231,8 @@ test "add and sub" { | ... | @@ -230,8 +231,8 @@ test "add and sub" { |
| 230 | const zero = [_]u8{0} ** len; | 231 | const zero = [_]u8{0} ** len; |
| 231 | var iterations: usize = 100; | 232 | var iterations: usize = 100; |
| 232 | while (iterations != 0) : (iterations -= 1) { | 233 | while (iterations != 0) : (iterations -= 1) { |
| 233 | random.bytes(&a); | 234 | io.random(&a); |
| 234 | random.bytes(&b); | 235 | io.random(&b); |
| 235 | const endian = if (iterations % 2 == 0) Endian.big else Endian.little; | 236 | const endian = if (iterations % 2 == 0) Endian.big else Endian.little; |
| 236 | _ = sub(u8, &a, &b, &c, endian); // a-b | 237 | _ = sub(u8, &a, &b, &c, endian); // a-b |
| 237 | _ = add(u8, &c, &b, &c, endian); // (a-b)+b | 238 | _ = add(u8, &c, &b, &c, endian); // (a-b)+b |
| ... | @@ -243,11 +244,11 @@ test "add and sub" { | ... | @@ -243,11 +244,11 @@ test "add and sub" { |
| 243 | } | 244 | } |
| 244 | 245 | ||
| 245 | test classify { | 246 | test classify { |
| 246 | const random = std.crypto.random; | 247 | const io = std.testing.io; |
| 247 | const expect = std.testing.expect; | 248 | const expect = std.testing.expect; |
| 248 | 249 | ||
| 249 | var secret: [32]u8 = undefined; | 250 | var secret: [32]u8 = undefined; |
| 250 | random.bytes(&secret); | 251 | io.random(&secret); |
| 251 | 252 | ||
| 252 | // Input of the hash function is marked as secret | 253 | // Input of the hash function is marked as secret |
| 253 | classify(&secret); | 254 | classify(&secret); |
lib/std/crypto/tls/Client.zig+7-7| ... | @@ -109,7 +109,7 @@ pub const Options = struct { | ... | @@ -109,7 +109,7 @@ pub const Options = struct { |
| 109 | read_buffer: []u8, | 109 | read_buffer: []u8, |
| 110 | /// Cryptographically secure random bytes. The pointer is not captured; data is only | 110 | /// Cryptographically secure random bytes. The pointer is not captured; data is only |
| 111 | /// read during `init`. | 111 | /// read during `init`. |
| 112 | entropy: *const [176]u8, | 112 | entropy: *const [240]u8, |
| 113 | /// Current time according to the wall clock / calendar, in seconds. | 113 | /// Current time according to the wall clock / calendar, in seconds. |
| 114 | realtime_now_seconds: i64, | 114 | realtime_now_seconds: i64, |
| 115 | 115 | ||
| ... | @@ -200,7 +200,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client | ... | @@ -200,7 +200,7 @@ pub fn init(input: *Reader, output: *Writer, options: Options) InitError!Client |
| 200 | var server_hello_rand: [32]u8 = undefined; | 200 | var server_hello_rand: [32]u8 = undefined; |
| 201 | const legacy_session_id = options.entropy[32..64].*; | 201 | const legacy_session_id = options.entropy[32..64].*; |
| 202 | 202 | ||
| 203 | var key_share = KeyShare.init(options.entropy[64..176].*) catch |err| switch (err) { | 203 | var key_share = KeyShare.init(options.entropy[64..240]) catch |err| switch (err) { |
| 204 | // Only possible to happen if the seed is all zeroes. | 204 | // Only possible to happen if the seed is all zeroes. |
| 205 | error.IdentityElement => return error.InsufficientEntropy, | 205 | error.IdentityElement => return error.InsufficientEntropy, |
| 206 | }; | 206 | }; |
| ... | @@ -1330,12 +1330,12 @@ const KeyShare = struct { | ... | @@ -1330,12 +1330,12 @@ const KeyShare = struct { |
| 1330 | crypto.dh.X25519.shared_length, | 1330 | crypto.dh.X25519.shared_length, |
| 1331 | ); | 1331 | ); |
| 1332 | 1332 | ||
| 1333 | fn init(seed: [112]u8) error{IdentityElement}!KeyShare { | 1333 | fn init(seed: *const [176]u8) error{IdentityElement}!KeyShare { |
| 1334 | return .{ | 1334 | return .{ |
| 1335 | .ml_kem768_kp = .generate(), | 1335 | .ml_kem768_kp = try .generateDeterministic(seed[0..64].*), |
| 1336 | .secp256r1_kp = try .generateDeterministic(seed[0..32].*), | 1336 | .secp256r1_kp = try .generateDeterministic(seed[64..96].*), |
| 1337 | .secp384r1_kp = try .generateDeterministic(seed[32..80].*), | 1337 | .secp384r1_kp = try .generateDeterministic(seed[96..144].*), |
| 1338 | .x25519_kp = try .generateDeterministic(seed[80..112].*), | 1338 | .x25519_kp = try .generateDeterministic(seed[144..176].*), |
| 1339 | .sk_buf = undefined, | 1339 | .sk_buf = undefined, |
| 1340 | .sk_len = 0, | 1340 | .sk_len = 0, |
| 1341 | }; | 1341 | }; |
lib/std/fs/test.zig+1-1| ... | @@ -1761,7 +1761,7 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { | ... | @@ -1761,7 +1761,7 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { |
| 1761 | const io = testing.io; | 1761 | const io = testing.io; |
| 1762 | 1762 | ||
| 1763 | var random_bytes: [12]u8 = undefined; | 1763 | var random_bytes: [12]u8 = undefined; |
| 1764 | std.crypto.random.bytes(&random_bytes); | 1764 | io.random(&random_bytes); |
| 1765 | 1765 | ||
| 1766 | var random_b64: [std.fs.base64_encoder.calcSize(random_bytes.len)]u8 = undefined; | 1766 | var random_b64: [std.fs.base64_encoder.calcSize(random_bytes.len)]u8 = undefined; |
| 1767 | _ = std.fs.base64_encoder.encode(&random_b64, &random_bytes); | 1767 | _ = std.fs.base64_encoder.encode(&random_b64, &random_bytes); |
lib/std/http/Client.zig+2-2| ... | @@ -321,8 +321,8 @@ pub const Connection = struct { | ... | @@ -321,8 +321,8 @@ pub const Connection = struct { |
| 321 | assert(base.ptr + alloc_len == socket_read_buffer.ptr + socket_read_buffer.len); | 321 | assert(base.ptr + alloc_len == socket_read_buffer.ptr + socket_read_buffer.len); |
| 322 | @memcpy(host_buffer, remote_host.bytes); | 322 | @memcpy(host_buffer, remote_host.bytes); |
| 323 | const tls: *Tls = @ptrCast(base); | 323 | const tls: *Tls = @ptrCast(base); |
| 324 | var random_buffer: [176]u8 = undefined; | 324 | var random_buffer: [240]u8 = undefined; |
| 325 | std.crypto.random.bytes(&random_buffer); | 325 | io.random(&random_buffer); |
| 326 | tls.* = .{ | 326 | tls.* = .{ |
| 327 | .connection = .{ | 327 | .connection = .{ |
| 328 | .client = client, | 328 | .client = client, |
lib/std/os/linux/tls.zig+5-7| ... | @@ -531,13 +531,11 @@ pub fn prepareArea(area: []u8) usize { | ... | @@ -531,13 +531,11 @@ pub fn prepareArea(area: []u8) usize { |
| 531 | }; | 531 | }; |
| 532 | } | 532 | } |
| 533 | 533 | ||
| 534 | /// The main motivation for the size chosen here is that this is how much ends up being requested for | 534 | /// The main motivation for the size chosen here is to be larger than total |
| 535 | /// the thread-local variables of the `std.crypto.random` implementation. I'm not sure why it ends up | 535 | /// amount of thread-local variables for most programs. Putting this allocation |
| 536 | /// being so much; the struct itself is only 64 bytes. I think it has to do with being page-aligned | 536 | /// in the ELF like this is equivalent to moving the `mmap` call below into the |
| 537 | /// and LLVM or LLD is not smart enough to lay out the TLS data in a space-conserving way. Anyway, I | 537 | /// kernel, avoiding syscall overhead. |
| 538 | /// think it's fine because it's less than 3 pages of memory, and putting it in the ELF like this is | 538 | var main_thread_area_buffer: [0x1000]u8 align(page_size_min) = undefined; |
| 539 | /// equivalent to moving the `mmap` call below into the kernel, avoiding syscall overhead. | ||
| 540 | var main_thread_area_buffer: [0x2100]u8 align(page_size_min) = undefined; | ||
| 541 | 539 | ||
| 542 | /// Computes the layout of the static TLS area, allocates the area, initializes all of its fields, | 540 | /// Computes the layout of the static TLS area, allocates the area, initializes all of its fields, |
| 543 | /// and assigns the architecture-specific value to the TP register. | 541 | /// and assigns the architecture-specific value to the TP register. |
lib/std/posix/test.zig-10| ... | @@ -33,16 +33,6 @@ test "check WASI CWD" { | ... | @@ -33,16 +33,6 @@ test "check WASI CWD" { |
| 33 | } | 33 | } |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | test "getrandom" { | ||
| 37 | var buf_a: [50]u8 = undefined; | ||
| 38 | var buf_b: [50]u8 = undefined; | ||
| 39 | try posix.getrandom(&buf_a); | ||
| 40 | try posix.getrandom(&buf_b); | ||
| 41 | // If this test fails the chance is significantly higher that there is a bug than | ||
| 42 | // that two sets of 50 bytes were equal. | ||
| 43 | try expect(!mem.eql(u8, &buf_a, &buf_b)); | ||
| 44 | } | ||
| 45 | |||
| 46 | test "getuid" { | 36 | test "getuid" { |
| 47 | if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; | 37 | if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; |
| 48 | _ = posix.getuid(); | 38 | _ = posix.getuid(); |
lib/std/testing.zig+1-1| ... | @@ -631,7 +631,7 @@ pub const TmpDir = struct { | ... | @@ -631,7 +631,7 @@ pub const TmpDir = struct { |
| 631 | pub fn tmpDir(opts: Io.Dir.OpenOptions) TmpDir { | 631 | pub fn tmpDir(opts: Io.Dir.OpenOptions) TmpDir { |
| 632 | comptime assert(builtin.is_test); | 632 | comptime assert(builtin.is_test); |
| 633 | var random_bytes: [TmpDir.random_bytes_count]u8 = undefined; | 633 | var random_bytes: [TmpDir.random_bytes_count]u8 = undefined; |
| 634 | std.crypto.random.bytes(&random_bytes); | 634 | io.random(&random_bytes); |
| 635 | var sub_path: [TmpDir.sub_path_len]u8 = undefined; | 635 | var sub_path: [TmpDir.sub_path_len]u8 = undefined; |
| 636 | _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); | 636 | _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); |
| 637 | 637 |
src/Compilation.zig+13-4| ... | @@ -2942,7 +2942,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE | ... | @@ -2942,7 +2942,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 2942 | .none => |none| { | 2942 | .none => |none| { |
| 2943 | assert(none.tmp_artifact_directory == null); | 2943 | assert(none.tmp_artifact_directory == null); |
| 2944 | none.tmp_artifact_directory = d: { | 2944 | none.tmp_artifact_directory = d: { |
| 2945 | tmp_dir_rand_int = std.crypto.random.int(u64); | 2945 | io.random(@ptrCast(&tmp_dir_rand_int)); |
| 2946 | const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int); | 2946 | const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int); |
| 2947 | const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path}); | 2947 | const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path}); |
| 2948 | const handle = comp.dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}) catch |err| { | 2948 | const handle = comp.dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}) catch |err| { |
| ... | @@ -3023,7 +3023,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE | ... | @@ -3023,7 +3023,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 3023 | 3023 | ||
| 3024 | // Compile the artifacts to a temporary directory. | 3024 | // Compile the artifacts to a temporary directory. |
| 3025 | whole.tmp_artifact_directory = d: { | 3025 | whole.tmp_artifact_directory = d: { |
| 3026 | tmp_dir_rand_int = std.crypto.random.int(u64); | 3026 | io.random(@ptrCast(&tmp_dir_rand_int)); |
| 3027 | const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int); | 3027 | const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int); |
| 3028 | const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path}); | 3028 | const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path}); |
| 3029 | const handle = comp.dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}) catch |err| { | 3029 | const handle = comp.dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}) catch |err| { |
| ... | @@ -5759,7 +5759,11 @@ pub fn translateC( | ... | @@ -5759,7 +5759,11 @@ pub fn translateC( |
| 5759 | 5759 | ||
| 5760 | const gpa = comp.gpa; | 5760 | const gpa = comp.gpa; |
| 5761 | const io = comp.io; | 5761 | const io = comp.io; |
| 5762 | const tmp_basename = std.fmt.hex(std.crypto.random.int(u64)); | 5762 | const tmp_basename = r: { |
| 5763 | var x: u64 = undefined; | ||
| 5764 | io.random(@ptrCast(&x)); | ||
| 5765 | break :r std.fmt.hex(x); | ||
| 5766 | }; | ||
| 5763 | const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename; | 5767 | const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename; |
| 5764 | const cache_dir = comp.dirs.local_cache.handle; | 5768 | const cache_dir = comp.dirs.local_cache.handle; |
| 5765 | var cache_tmp_dir = try cache_dir.createDirPathOpen(io, tmp_sub_path, .{}); | 5769 | var cache_tmp_dir = try cache_dir.createDirPathOpen(io, tmp_sub_path, .{}); |
| ... | @@ -6889,8 +6893,13 @@ fn spawnZigRc( | ... | @@ -6889,8 +6893,13 @@ fn spawnZigRc( |
| 6889 | } | 6893 | } |
| 6890 | 6894 | ||
| 6891 | pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 { | 6895 | pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 { |
| 6896 | const io = comp.io; | ||
| 6897 | const rand_int = r: { | ||
| 6898 | var x: u64 = undefined; | ||
| 6899 | io.random(@ptrCast(&x)); | ||
| 6900 | break :r x; | ||
| 6901 | }; | ||
| 6892 | const s = fs.path.sep_str; | 6902 | const s = fs.path.sep_str; |
| 6893 | const rand_int = std.crypto.random.int(u64); | ||
| 6894 | if (comp.dirs.local_cache.path) |p| { | 6903 | if (comp.dirs.local_cache.path) |p| { |
| 6895 | return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix }); | 6904 | return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix }); |
| 6896 | } else { | 6905 | } else { |
src/Package.zig+2-2| ... | @@ -14,9 +14,9 @@ pub const Fingerprint = packed struct(u64) { | ... | @@ -14,9 +14,9 @@ pub const Fingerprint = packed struct(u64) { |
| 14 | id: u32, | 14 | id: u32, |
| 15 | checksum: u32, | 15 | checksum: u32, |
| 16 | 16 | ||
| 17 | pub fn generate(name: []const u8) Fingerprint { | 17 | pub fn generate(rng: std.Random, name: []const u8) Fingerprint { |
| 18 | return .{ | 18 | return .{ |
| 19 | .id = std.crypto.random.intRangeLessThan(u32, 1, 0xffffffff), | 19 | .id = rng.intRangeLessThan(u32, 1, 0xffffffff), |
| 20 | .checksum = std.hash.Crc32.hash(name), | 20 | .checksum = std.hash.Crc32.hash(name), |
| 21 | }; | 21 | }; |
| 22 | } | 22 | } |
src/Package/Fetch.zig+13-3| ... | @@ -494,7 +494,11 @@ fn runResource( | ... | @@ -494,7 +494,11 @@ fn runResource( |
| 494 | const eb = &f.error_bundle; | 494 | const eb = &f.error_bundle; |
| 495 | const s = fs.path.sep_str; | 495 | const s = fs.path.sep_str; |
| 496 | const cache_root = f.job_queue.global_cache; | 496 | const cache_root = f.job_queue.global_cache; |
| 497 | const rand_int = std.crypto.random.int(u64); | 497 | const rand_int = r: { |
| 498 | var x: u64 = undefined; | ||
| 499 | io.random(@ptrCast(&x)); | ||
| 500 | break :r x; | ||
| 501 | }; | ||
| 498 | const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(rand_int); | 502 | const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(rand_int); |
| 499 | 503 | ||
| 500 | const package_sub_path = blk: { | 504 | const package_sub_path = blk: { |
| ... | @@ -690,7 +694,9 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { | ... | @@ -690,7 +694,9 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { |
| 690 | return error.FetchFailed; | 694 | return error.FetchFailed; |
| 691 | } | 695 | } |
| 692 | 696 | ||
| 693 | f.manifest = try Manifest.parse(arena, ast.*, .{ | 697 | const rng: std.Random.IoSource = .{ .io = io }; |
| 698 | |||
| 699 | f.manifest = try Manifest.parse(arena, ast.*, rng.interface(), .{ | ||
| 694 | .allow_missing_paths_field = f.allow_missing_paths_field, | 700 | .allow_missing_paths_field = f.allow_missing_paths_field, |
| 695 | .allow_missing_fingerprint = f.allow_missing_fingerprint, | 701 | .allow_missing_fingerprint = f.allow_missing_fingerprint, |
| 696 | .allow_name_string = f.allow_name_string, | 702 | .allow_name_string = f.allow_name_string, |
| ... | @@ -1305,7 +1311,11 @@ fn unzip( | ... | @@ -1305,7 +1311,11 @@ fn unzip( |
| 1305 | zip_path[prefix.len + random_len ..].* = suffix.*; | 1311 | zip_path[prefix.len + random_len ..].* = suffix.*; |
| 1306 | 1312 | ||
| 1307 | var zip_file = while (true) { | 1313 | var zip_file = while (true) { |
| 1308 | const random_integer = std.crypto.random.int(u64); | 1314 | const random_integer = r: { |
| 1315 | var x: u64 = undefined; | ||
| 1316 | io.random(@ptrCast(&x)); | ||
| 1317 | break :r x; | ||
| 1318 | }; | ||
| 1309 | zip_path[prefix.len..][0..random_len].* = std.fmt.hex(random_integer); | 1319 | zip_path[prefix.len..][0..random_len].* = std.fmt.hex(random_integer); |
| 1310 | 1320 | ||
| 1311 | break cache_root.handle.createFile(io, &zip_path, .{ | 1321 | break cache_root.handle.createFile(io, &zip_path, .{ |
src/Package/Manifest.zig+5-5| ... | @@ -57,7 +57,7 @@ pub const ParseOptions = struct { | ... | @@ -57,7 +57,7 @@ pub const ParseOptions = struct { |
| 57 | 57 | ||
| 58 | pub const Error = Allocator.Error; | 58 | pub const Error = Allocator.Error; |
| 59 | 59 | ||
| 60 | pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest { | 60 | pub fn parse(gpa: Allocator, ast: Ast, rng: std.Random, options: ParseOptions) Error!Manifest { |
| 61 | const main_node_index = ast.nodeData(.root).node; | 61 | const main_node_index = ast.nodeData(.root).node; |
| 62 | 62 | ||
| 63 | var arena_instance = std.heap.ArenaAllocator.init(gpa); | 63 | var arena_instance = std.heap.ArenaAllocator.init(gpa); |
| ... | @@ -87,7 +87,7 @@ pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest { | ... | @@ -87,7 +87,7 @@ pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest { |
| 87 | defer p.dependencies.deinit(gpa); | 87 | defer p.dependencies.deinit(gpa); |
| 88 | defer p.paths.deinit(gpa); | 88 | defer p.paths.deinit(gpa); |
| 89 | 89 | ||
| 90 | p.parseRoot(main_node_index) catch |err| switch (err) { | 90 | p.parseRoot(main_node_index, rng) catch |err| switch (err) { |
| 91 | error.ParseFailure => assert(p.errors.items.len > 0), | 91 | error.ParseFailure => assert(p.errors.items.len > 0), |
| 92 | else => |e| return e, | 92 | else => |e| return e, |
| 93 | }; | 93 | }; |
| ... | @@ -157,7 +157,7 @@ const Parse = struct { | ... | @@ -157,7 +157,7 @@ const Parse = struct { |
| 157 | 157 | ||
| 158 | const InnerError = error{ ParseFailure, OutOfMemory }; | 158 | const InnerError = error{ ParseFailure, OutOfMemory }; |
| 159 | 159 | ||
| 160 | fn parseRoot(p: *Parse, node: Ast.Node.Index) !void { | 160 | fn parseRoot(p: *Parse, node: Ast.Node.Index, rng: std.Random) !void { |
| 161 | const ast = p.ast; | 161 | const ast = p.ast; |
| 162 | const main_token = ast.nodeMainToken(node); | 162 | const main_token = ast.nodeMainToken(node); |
| 163 | 163 | ||
| ... | @@ -217,13 +217,13 @@ const Parse = struct { | ... | @@ -217,13 +217,13 @@ const Parse = struct { |
| 217 | if (fingerprint) |n| { | 217 | if (fingerprint) |n| { |
| 218 | if (!n.validate(p.name)) { | 218 | if (!n.validate(p.name)) { |
| 219 | return fail(p, main_token, "invalid fingerprint: 0x{x}; if this is a new or forked package, use this value: 0x{x}", .{ | 219 | return fail(p, main_token, "invalid fingerprint: 0x{x}; if this is a new or forked package, use this value: 0x{x}", .{ |
| 220 | n.int(), Package.Fingerprint.generate(p.name).int(), | 220 | n.int(), Package.Fingerprint.generate(rng, p.name).int(), |
| 221 | }); | 221 | }); |
| 222 | } | 222 | } |
| 223 | p.id = n.id; | 223 | p.id = n.id; |
| 224 | } else if (!p.allow_missing_fingerprint) { | 224 | } else if (!p.allow_missing_fingerprint) { |
| 225 | try appendError(p, main_token, "missing top-level 'fingerprint' field; suggested value: 0x{x}", .{ | 225 | try appendError(p, main_token, "missing top-level 'fingerprint' field; suggested value: 0x{x}", .{ |
| 226 | Package.Fingerprint.generate(p.name).int(), | 226 | Package.Fingerprint.generate(rng, p.name).int(), |
| 227 | }); | 227 | }); |
| 228 | } else { | 228 | } else { |
| 229 | p.id = 0; | 229 | p.id = 0; |
src/link.zig+6-1| ... | @@ -616,8 +616,13 @@ pub const File = struct { | ... | @@ -616,8 +616,13 @@ pub const File = struct { |
| 616 | // it will return ETXTBSY. So instead, we copy the file, atomically rename it | 616 | // it will return ETXTBSY. So instead, we copy the file, atomically rename it |
| 617 | // over top of the exe path, and then proceed normally. This changes the inode, | 617 | // over top of the exe path, and then proceed normally. This changes the inode, |
| 618 | // avoiding the error. | 618 | // avoiding the error. |
| 619 | const random_integer = r: { | ||
| 620 | var x: u32 = undefined; | ||
| 621 | io.random(@ptrCast(&x)); | ||
| 622 | break :r x; | ||
| 623 | }; | ||
| 619 | const tmp_sub_path = try std.fmt.allocPrint(gpa, "{s}-{x}", .{ | 624 | const tmp_sub_path = try std.fmt.allocPrint(gpa, "{s}-{x}", .{ |
| 620 | emit.sub_path, std.crypto.random.int(u32), | 625 | emit.sub_path, random_integer, |
| 621 | }); | 626 | }); |
| 622 | defer gpa.free(tmp_sub_path); | 627 | defer gpa.free(tmp_sub_path); |
| 623 | try emit.root_dir.handle.copyFile(emit.sub_path, emit.root_dir.handle, tmp_sub_path, io, .{}); | 628 | try emit.root_dir.handle.copyFile(emit.sub_path, emit.root_dir.handle, tmp_sub_path, io, .{}); |
src/link/Lld.zig+5-1| ... | @@ -1636,7 +1636,11 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi | ... | @@ -1636,7 +1636,11 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi |
| 1636 | const err = switch (first_err) { | 1636 | const err = switch (first_err) { |
| 1637 | error.NameTooLong => err: { | 1637 | error.NameTooLong => err: { |
| 1638 | const s = fs.path.sep_str; | 1638 | const s = fs.path.sep_str; |
| 1639 | const rand_int = std.crypto.random.int(u64); | 1639 | const rand_int = r: { |
| 1640 | var x: u64 = undefined; | ||
| 1641 | io.random(@ptrCast(&x)); | ||
| 1642 | break :r x; | ||
| 1643 | }; | ||
| 1640 | const rsp_path = "tmp" ++ s ++ std.fmt.hex(rand_int) ++ ".rsp"; | 1644 | const rsp_path = "tmp" ++ s ++ std.fmt.hex(rand_int) ++ ".rsp"; |
| 1641 | 1645 | ||
| 1642 | const rsp_file = try comp.dirs.local_cache.handle.createFile(io, rsp_path, .{}); | 1646 | const rsp_file = try comp.dirs.local_cache.handle.createFile(io, rsp_path, .{}); |
src/main.zig+19-12| ... | @@ -3395,7 +3395,7 @@ fn buildOutputType( | ... | @@ -3395,7 +3395,7 @@ fn buildOutputType( |
| 3395 | // "-" is stdin. Dump it to a real file. | 3395 | // "-" is stdin. Dump it to a real file. |
| 3396 | const sep = fs.path.sep_str; | 3396 | const sep = fs.path.sep_str; |
| 3397 | const dump_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-dump-stdin{s}", .{ | 3397 | const dump_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-dump-stdin{s}", .{ |
| 3398 | std.crypto.random.int(u64), ext.canonicalName(target), | 3398 | randInt(io, u64), ext.canonicalName(target), |
| 3399 | }); | 3399 | }); |
| 3400 | try dirs.local_cache.handle.createDirPath(io, "tmp"); | 3400 | try dirs.local_cache.handle.createDirPath(io, "tmp"); |
| 3401 | 3401 | ||
| ... | @@ -4433,7 +4433,7 @@ fn runOrTest( | ... | @@ -4433,7 +4433,7 @@ fn runOrTest( |
| 4433 | try argv.append(exe_path); | 4433 | try argv.append(exe_path); |
| 4434 | if (arg_mode == .zig_test) { | 4434 | if (arg_mode == .zig_test) { |
| 4435 | try argv.append( | 4435 | try argv.append( |
| 4436 | try std.fmt.allocPrint(arena, "--seed=0x{x}", .{std.crypto.random.int(u32)}), | 4436 | try std.fmt.allocPrint(arena, "--seed=0x{x}", .{randInt(io, u32)}), |
| 4437 | ); | 4437 | ); |
| 4438 | } | 4438 | } |
| 4439 | } else { | 4439 | } else { |
| ... | @@ -4763,7 +4763,8 @@ fn cmdInit(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! | ... | @@ -4763,7 +4763,8 @@ fn cmdInit(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! |
| 4763 | const cwd_basename = fs.path.basename(cwd_path); | 4763 | const cwd_basename = fs.path.basename(cwd_path); |
| 4764 | const sanitized_root_name = try sanitizeExampleName(arena, cwd_basename); | 4764 | const sanitized_root_name = try sanitizeExampleName(arena, cwd_basename); |
| 4765 | 4765 | ||
| 4766 | const fingerprint: Package.Fingerprint = .generate(sanitized_root_name); | 4766 | const rng: std.Random.IoSource = .{ .io = io }; |
| 4767 | const fingerprint: Package.Fingerprint = .generate(rng.interface(), sanitized_root_name); | ||
| 4767 | 4768 | ||
| 4768 | switch (template) { | 4769 | switch (template) { |
| 4769 | .example => { | 4770 | .example => { |
| ... | @@ -4919,7 +4920,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -4919,7 +4920,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 4919 | 4920 | ||
| 4920 | try child_argv.appendSlice(&.{ | 4921 | try child_argv.appendSlice(&.{ |
| 4921 | "--seed", | 4922 | "--seed", |
| 4922 | try std.fmt.allocPrint(arena, "0x{x}", .{std.crypto.random.int(u32)}), | 4923 | try std.fmt.allocPrint(arena, "0x{x}", .{randInt(io, u32)}), |
| 4923 | }); | 4924 | }); |
| 4924 | const argv_index_seed = child_argv.items.len - 1; | 4925 | const argv_index_seed = child_argv.items.len - 1; |
| 4925 | 4926 | ||
| ... | @@ -4937,7 +4938,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -4937,7 +4938,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 4937 | // the strategy is to choose a temporary file name ahead of time, and then | 4938 | // the strategy is to choose a temporary file name ahead of time, and then |
| 4938 | // read this file in the parent to obtain the results, in the case the child | 4939 | // read this file in the parent to obtain the results, in the case the child |
| 4939 | // exits with code 3. | 4940 | // exits with code 3. |
| 4940 | const results_tmp_file_nonce = std.fmt.hex(std.crypto.random.int(u64)); | 4941 | const results_tmp_file_nonce = std.fmt.hex(randInt(io, u64)); |
| 4941 | try child_argv.append("-Z" ++ results_tmp_file_nonce); | 4942 | try child_argv.append("-Z" ++ results_tmp_file_nonce); |
| 4942 | 4943 | ||
| 4943 | var color: Color = .auto; | 4944 | var color: Color = .auto; |
| ... | @@ -7223,7 +7224,7 @@ fn createDependenciesModule( | ... | @@ -7223,7 +7224,7 @@ fn createDependenciesModule( |
| 7223 | ) !*Package.Module { | 7224 | ) !*Package.Module { |
| 7224 | // Atomically create the file in a directory named after the hash of its contents. | 7225 | // Atomically create the file in a directory named after the hash of its contents. |
| 7225 | const basename = "dependencies.zig"; | 7226 | const basename = "dependencies.zig"; |
| 7226 | const rand_int = std.crypto.random.int(u64); | 7227 | const rand_int = randInt(io, u64); |
| 7227 | const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); | 7228 | const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); |
| 7228 | { | 7229 | { |
| 7229 | var tmp_dir = try dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}); | 7230 | var tmp_dir = try dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}); |
| ... | @@ -7339,6 +7340,8 @@ fn loadManifest( | ... | @@ -7339,6 +7340,8 @@ fn loadManifest( |
| 7339 | io: Io, | 7340 | io: Io, |
| 7340 | options: LoadManifestOptions, | 7341 | options: LoadManifestOptions, |
| 7341 | ) !struct { Package.Manifest, Ast } { | 7342 | ) !struct { Package.Manifest, Ast } { |
| 7343 | const rng: std.Random.IoSource = .{ .io = io }; | ||
| 7344 | |||
| 7342 | const manifest_bytes = while (true) { | 7345 | const manifest_bytes = while (true) { |
| 7343 | break options.dir.readFileAllocOptions( | 7346 | break options.dir.readFileAllocOptions( |
| 7344 | io, | 7347 | io, |
| ... | @@ -7360,15 +7363,13 @@ fn loadManifest( | ... | @@ -7360,15 +7363,13 @@ fn loadManifest( |
| 7360 | , .{ | 7363 | , .{ |
| 7361 | options.root_name, | 7364 | options.root_name, |
| 7362 | build_options.version, | 7365 | build_options.version, |
| 7363 | Package.Fingerprint.generate(options.root_name).int(), | 7366 | Package.Fingerprint.generate(rng.interface(), options.root_name).int(), |
| 7364 | }) catch |e| { | 7367 | }) catch |e| { |
| 7365 | fatal("unable to write {s}: {s}", .{ Package.Manifest.basename, @errorName(e) }); | 7368 | fatal("unable to write {s}: {t}", .{ Package.Manifest.basename, e }); |
| 7366 | }; | 7369 | }; |
| 7367 | continue; | 7370 | continue; |
| 7368 | }, | 7371 | }, |
| 7369 | else => |e| fatal("unable to load {s}: {s}", .{ | 7372 | else => |e| fatal("unable to load {s}: {t}", .{ Package.Manifest.basename, e }), |
| 7370 | Package.Manifest.basename, @errorName(e), | ||
| 7371 | }), | ||
| 7372 | }; | 7373 | }; |
| 7373 | }; | 7374 | }; |
| 7374 | var ast = try Ast.parse(gpa, manifest_bytes, .zon); | 7375 | var ast = try Ast.parse(gpa, manifest_bytes, .zon); |
| ... | @@ -7379,7 +7380,7 @@ fn loadManifest( | ... | @@ -7379,7 +7380,7 @@ fn loadManifest( |
| 7379 | process.exit(2); | 7380 | process.exit(2); |
| 7380 | } | 7381 | } |
| 7381 | 7382 | ||
| 7382 | var manifest = try Package.Manifest.parse(gpa, ast, .{}); | 7383 | var manifest = try Package.Manifest.parse(gpa, ast, rng.interface(), .{}); |
| 7383 | errdefer manifest.deinit(gpa); | 7384 | errdefer manifest.deinit(gpa); |
| 7384 | 7385 | ||
| 7385 | if (manifest.errors.len > 0) { | 7386 | if (manifest.errors.len > 0) { |
| ... | @@ -7632,3 +7633,9 @@ fn setThreadLimit(n: usize) void { | ... | @@ -7632,3 +7633,9 @@ fn setThreadLimit(n: usize) void { |
| 7632 | threaded_impl_ptr.setAsyncLimit(limit); | 7633 | threaded_impl_ptr.setAsyncLimit(limit); |
| 7633 | threaded_impl_ptr.concurrent_limit = limit; | 7634 | threaded_impl_ptr.concurrent_limit = limit; |
| 7634 | } | 7635 | } |
| 7636 | |||
| 7637 | fn randInt(io: Io, comptime T: type) T { | ||
| 7638 | var x: T = undefined; | ||
| 7639 | io.random(@ptrCast(&x)); | ||
| 7640 | return x; | ||
| 7641 | } |
test/standalone/simple/guess_number/main.zig+2-1| ... | @@ -10,7 +10,8 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -10,7 +10,8 @@ pub fn main(init: std.process.Init) !void { |
| 10 | 10 | ||
| 11 | try out.writeAll("Welcome to the Guess Number Game in Zig.\n"); | 11 | try out.writeAll("Welcome to the Guess Number Game in Zig.\n"); |
| 12 | 12 | ||
| 13 | const answer = std.crypto.random.intRangeLessThan(u8, 0, 100) + 1; | 13 | var rng: std.Random.IoSource = .{ .io = init.io }; |
| 14 | const answer = rng.interface().intRangeLessThan(u8, 0, 100) + 1; | ||
| 14 | 15 | ||
| 15 | while (true) { | 16 | while (true) { |
| 16 | try out.writeAll("\nGuess a number between 1 and 100: "); | 17 | try out.writeAll("\nGuess a number between 1 and 100: "); |
tools/doctest.zig+4-3| ... | @@ -78,9 +78,10 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -78,9 +78,10 @@ pub fn main(init: std.process.Init) !void { |
| 78 | const code = try parseManifest(arena, source_bytes); | 78 | const code = try parseManifest(arena, source_bytes); |
| 79 | const source = stripManifest(source_bytes); | 79 | const source = stripManifest(source_bytes); |
| 80 | 80 | ||
| 81 | const tmp_dir_path = try std.fmt.allocPrint(arena, "{s}/tmp/{x}", .{ | 81 | var random_integer: u64 = undefined; |
| 82 | cache_root, std.crypto.random.int(u64), | 82 | io.random(@ptrCast(&random_integer)); |
| 83 | }); | 83 | |
| 84 | const tmp_dir_path = try std.fmt.allocPrint(arena, "{s}/tmp/{x}", .{ cache_root, random_integer }); | ||
| 84 | Dir.cwd().createDirPath(io, tmp_dir_path) catch |err| | 85 | Dir.cwd().createDirPath(io, tmp_dir_path) catch |err| |
| 85 | fatal("unable to create tmp dir '{s}': {t}", .{ tmp_dir_path, err }); | 86 | fatal("unable to create tmp dir '{s}': {t}", .{ tmp_dir_path, err }); |
| 86 | defer Dir.cwd().deleteTree(io, tmp_dir_path) catch |err| std.log.err("unable to delete '{s}': {t}", .{ | 87 | defer Dir.cwd().deleteTree(io, tmp_dir_path) catch |err| std.log.err("unable to delete '{s}': {t}", .{ |
tools/incr-check.zig+9-4| ... | @@ -100,7 +100,7 @@ pub fn main(init: std.process.Init) !void { | ... | @@ -100,7 +100,7 @@ pub fn main(init: std.process.Init) !void { |
| 100 | const prog_node = std.Progress.start(io, .{}); | 100 | const prog_node = std.Progress.start(io, .{}); |
| 101 | defer prog_node.end(); | 101 | defer prog_node.end(); |
| 102 | 102 | ||
| 103 | const rand_int = std.crypto.random.int(u64); | 103 | const rand_int = rand64(io); |
| 104 | const tmp_dir_path = "tmp_" ++ std.fmt.hex(rand_int); | 104 | const tmp_dir_path = "tmp_" ++ std.fmt.hex(rand_int); |
| 105 | var tmp_dir = try Dir.cwd().createDirPathOpen(io, tmp_dir_path, .{}); | 105 | var tmp_dir = try Dir.cwd().createDirPathOpen(io, tmp_dir_path, .{}); |
| 106 | defer { | 106 | defer { |
| ... | @@ -452,20 +452,19 @@ const Eval = struct { | ... | @@ -452,20 +452,19 @@ const Eval = struct { |
| 452 | std.debug.assert(eval.target.backend == .sema); | 452 | std.debug.assert(eval.target.backend == .sema); |
| 453 | return; | 453 | return; |
| 454 | }; | 454 | }; |
| 455 | const io = eval.io; | ||
| 455 | 456 | ||
| 456 | const binary_path = switch (eval.target.backend) { | 457 | const binary_path = switch (eval.target.backend) { |
| 457 | .sema => unreachable, | 458 | .sema => unreachable, |
| 458 | .selfhosted, .llvm => emitted_path, | 459 | .selfhosted, .llvm => emitted_path, |
| 459 | .cbe => bin: { | 460 | .cbe => bin: { |
| 460 | const rand_int = std.crypto.random.int(u64); | 461 | const rand_int = rand64(io); |
| 461 | const out_bin_name = "./out_" ++ std.fmt.hex(rand_int); | 462 | const out_bin_name = "./out_" ++ std.fmt.hex(rand_int); |
| 462 | try eval.buildCOutput(emitted_path, out_bin_name, prog_node); | 463 | try eval.buildCOutput(emitted_path, out_bin_name, prog_node); |
| 463 | break :bin out_bin_name; | 464 | break :bin out_bin_name; |
| 464 | }, | 465 | }, |
| 465 | }; | 466 | }; |
| 466 | 467 | ||
| 467 | const io = eval.io; | ||
| 468 | |||
| 469 | var argv_buf: [2][]const u8 = undefined; | 468 | var argv_buf: [2][]const u8 = undefined; |
| 470 | const argv: []const []const u8, const is_foreign: bool = sw: switch (std.zig.system.getExternalExecutor( | 469 | const argv: []const []const u8, const is_foreign: bool = sw: switch (std.zig.system.getExternalExecutor( |
| 471 | io, | 470 | io, |
| ... | @@ -957,3 +956,9 @@ fn parseExpectedError(str: []const u8, l: usize) Case.ExpectedError { | ... | @@ -957,3 +956,9 @@ fn parseExpectedError(str: []const u8, l: usize) Case.ExpectedError { |
| 957 | .msg = message, | 956 | .msg = message, |
| 958 | }; | 957 | }; |
| 959 | } | 958 | } |
| 959 | |||
| 960 | fn rand64(io: Io) u64 { | ||
| 961 | var x: u64 = undefined; | ||
| 962 | io.random(@ptrCast(&x)); | ||
| 963 | return x; | ||
| 964 | } |