diff options
| author | Rutger Broekhoff | 2022-03-17 22:04:44 +0100 | 
|---|---|---|
| committer | Rutger Broekhoff | 2022-03-17 22:04:44 +0100 | 
| commit | 885a21d0f3226d1acc93aa16a6fe8ea37235c7e0 (patch) | |
| tree | 59e520339b4837bd03d5343c3fbf2c50b2b070fb /tool | |
| parent | e91bfbd118172804a98280bb5b0b48d15ee76531 (diff) | |
| download | zig-nkeys-885a21d0f3226d1acc93aa16a6fe8ea37235c7e0.tar.gz zig-nkeys-885a21d0f3226d1acc93aa16a6fe8ea37235c7e0.zip | |
Update for Zig dev
Diffstat (limited to 'tool')
| -rw-r--r-- | tool/znk.zig | 76 | 
1 files changed, 47 insertions, 29 deletions
| diff --git a/tool/znk.zig b/tool/znk.zig index 269e176..e086879 100644 --- a/tool/znk.zig +++ b/tool/znk.zig | |||
| @@ -2,7 +2,7 @@ const std = @import("std"); | |||
| 2 | const Allocator = mem.Allocator; | 2 | const Allocator = mem.Allocator; | 
| 3 | const ascii = std.ascii; | 3 | const ascii = std.ascii; | 
| 4 | const build_options = @import("build_options"); | 4 | const build_options = @import("build_options"); | 
| 5 | const builtin = std.builtin; | 5 | const builtin = @import("builtin"); | 
| 6 | const fs = std.fs; | 6 | const fs = std.fs; | 
| 7 | const io = std.io; | 7 | const io = std.io; | 
| 8 | const mem = std.mem; | 8 | const mem = std.mem; | 
| @@ -39,17 +39,17 @@ const usage = | |||
| 39 | pub fn main() anyerror!void { | 39 | pub fn main() anyerror!void { | 
| 40 | var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; | 40 | var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; | 
| 41 | defer std.debug.assert(!general_purpose_allocator.deinit()); | 41 | defer std.debug.assert(!general_purpose_allocator.deinit()); | 
| 42 | const gpa = &general_purpose_allocator.allocator; | 42 | const gpa = general_purpose_allocator.allocator(); | 
| 43 | 43 | ||
| 44 | var arena_instance = std.heap.ArenaAllocator.init(gpa); | 44 | var arena_instance = std.heap.ArenaAllocator.init(gpa); | 
| 45 | defer arena_instance.deinit(); | 45 | defer arena_instance.deinit(); | 
| 46 | const arena = &arena_instance.allocator; | 46 | const arena = arena_instance.allocator(); | 
| 47 | 47 | ||
| 48 | const args = try process.argsAlloc(arena); | 48 | const args = try process.argsAlloc(arena); | 
| 49 | return mainArgs(arena, args); | 49 | return mainArgs(arena, args); | 
| 50 | } | 50 | } | 
| 51 | 51 | ||
| 52 | pub fn mainArgs(arena: *Allocator, args: []const []const u8) !void { | 52 | pub fn mainArgs(arena: Allocator, args: []const []const u8) !void { | 
| 53 | if (args.len <= 1) { | 53 | if (args.len <= 1) { | 
| 54 | info("{s}", .{usage}); | 54 | info("{s}", .{usage}); | 
| 55 | fatal("expected command argument", .{}); | 55 | fatal("expected command argument", .{}); | 
| @@ -96,7 +96,7 @@ const usage_gen = | |||
| 96 | \\ | 96 | \\ | 
| 97 | ; | 97 | ; | 
| 98 | 98 | ||
| 99 | pub fn cmdGen(arena: *Allocator, args: []const []const u8) !void { | 99 | pub fn cmdGen(arena: Allocator, args: []const []const u8) !void { | 
| 100 | const stdin = io.getStdIn(); | 100 | const stdin = io.getStdIn(); | 
| 101 | const stdout = io.getStdOut(); | 101 | const stdout = io.getStdOut(); | 
| 102 | 102 | ||
| @@ -200,7 +200,7 @@ const usage_sign = | |||
| 200 | \\ | 200 | \\ | 
| 201 | ; | 201 | ; | 
| 202 | 202 | ||
| 203 | pub fn cmdSign(arena: *Allocator, args: []const []const u8) !void { | 203 | pub fn cmdSign(arena: Allocator, args: []const []const u8) !void { | 
| 204 | const stdin = io.getStdIn(); | 204 | const stdin = io.getStdIn(); | 
| 205 | const stdout = io.getStdOut(); | 205 | const stdout = io.getStdOut(); | 
| 206 | 206 | ||
| @@ -286,7 +286,7 @@ const usage_verify = | |||
| 286 | \\ | 286 | \\ | 
| 287 | ; | 287 | ; | 
| 288 | 288 | ||
| 289 | pub fn cmdVerify(arena: *Allocator, args: []const []const u8) !void { | 289 | pub fn cmdVerify(arena: Allocator, args: []const []const u8) !void { | 
| 290 | const stdin = io.getStdIn(); | 290 | const stdin = io.getStdIn(); | 
| 291 | const stdout = io.getStdOut(); | 291 | const stdout = io.getStdOut(); | 
| 292 | 292 | ||
| @@ -391,17 +391,39 @@ pub fn cmdVerify(arena: *Allocator, args: []const []const u8) !void { | |||
| 391 | try stdout.writeAll("good signature\n"); | 391 | try stdout.writeAll("good signature\n"); | 
| 392 | } | 392 | } | 
| 393 | 393 | ||
| 394 | const RandomReader = struct { | ||
| 395 | rand: *const std.rand.Random, | ||
| 396 | |||
| 397 | pub const Error = error{}; | ||
| 398 | pub const Reader = io.Reader(*Self, Error, read); | ||
| 399 | |||
| 400 | const Self = @This(); | ||
| 401 | |||
| 402 | pub fn init(rand: *const std.rand.Random) Self { | ||
| 403 | return .{ .rand = rand }; | ||
| 404 | } | ||
| 405 | |||
| 406 | pub fn read(self: *Self, dest: []u8) Error!usize { | ||
| 407 | self.rand.bytes(dest); | ||
| 408 | return dest.len; | ||
| 409 | } | ||
| 410 | |||
| 411 | pub fn reader(self: *Self) Reader { | ||
| 412 | return .{ .context = self }; | ||
| 413 | } | ||
| 414 | }; | ||
| 415 | |||
| 394 | fn PrefixKeyGenerator(comptime EntropyReaderType: type) type { | 416 | fn PrefixKeyGenerator(comptime EntropyReaderType: type) type { | 
| 395 | return struct { | 417 | return struct { | 
| 396 | role: nkeys.Role, | 418 | role: nkeys.Role, | 
| 397 | prefix: []const u8, | 419 | prefix: []const u8, | 
| 398 | allocator: *Allocator, | 420 | allocator: Allocator, | 
| 399 | done: std.atomic.Atomic(bool), | 421 | done: std.atomic.Atomic(bool), | 
| 400 | entropy: ?EntropyReaderType, | 422 | entropy: ?EntropyReaderType, | 
| 401 | 423 | ||
| 402 | const Self = @This(); | 424 | const Self = @This(); | 
| 403 | 425 | ||
| 404 | pub fn init(allocator: *Allocator, role: nkeys.Role, prefix: []const u8, entropy: ?EntropyReaderType) Self { | 426 | pub fn init(allocator: Allocator, role: nkeys.Role, prefix: []const u8, entropy: ?EntropyReaderType) Self { | 
| 405 | return .{ | 427 | return .{ | 
| 406 | .role = role, | 428 | .role = role, | 
| 407 | .prefix = prefix, | 429 | .prefix = prefix, | 
| @@ -412,28 +434,24 @@ fn PrefixKeyGenerator(comptime EntropyReaderType: type) type { | |||
| 412 | } | 434 | } | 
| 413 | 435 | ||
| 414 | fn generatePrivate(self: *Self) !void { | 436 | fn generatePrivate(self: *Self) !void { | 
| 415 | while (true) { | 437 | var rr = RandomReader.init(&std.crypto.random); | 
| 416 | if (self.done.load(.SeqCst)) return; | 438 | var brr = io.BufferedReader(1024 * 4096, @TypeOf(rr.reader())){ .unbuffered_reader = rr.reader() }; | 
| 417 | 439 | while (!self.done.load(.SeqCst)) { | |
| 418 | var gen_result = res: { | 440 | var gen_result = if (self.entropy) |entropy| | 
| 419 | if (self.entropy) |entropy| { | 441 | nkeys.SeedKeyPair.generateWithCustomEntropy(self.role, entropy) | 
| 420 | break :res nkeys.SeedKeyPair.generateWithCustomEntropy(self.role, entropy); | 442 | else | 
| 421 | } else { | 443 | nkeys.SeedKeyPair.generateWithCustomEntropy(self.role, brr.reader()); | 
| 422 | break :res nkeys.SeedKeyPair.generate(self.role); | ||
| 423 | } | ||
| 424 | }; | ||
| 425 | var kp = gen_result catch fatal("could not generate seed", .{}); | 444 | var kp = gen_result catch fatal("could not generate seed", .{}); | 
| 426 | 445 | ||
| 427 | defer kp.wipe(); | ||
| 428 | var public_key = kp.publicKeyText(); | 446 | var public_key = kp.publicKeyText(); | 
| 429 | if (!mem.startsWith(u8, public_key[1..], self.prefix)) continue; | 447 | if (mem.startsWith(u8, public_key[1..], self.prefix)) { | 
| 430 | 448 | if (self.done.swap(true, .SeqCst)) return; // another thread is already done | |
| 431 | if (self.done.swap(true, .SeqCst)) return; // another thread is already done | ||
| 432 | 449 | ||
| 433 | info("{s}", .{kp.seedText()}); | 450 | info("{s}", .{kp.seedText()}); | 
| 434 | info("{s}", .{public_key}); | 451 | info("{s}", .{public_key}); | 
| 435 | 452 | ||
| 436 | return; | 453 | return; | 
| 454 | } | ||
| 437 | } | 455 | } | 
| 438 | } | 456 | } | 
| 439 | 457 | ||
| @@ -444,7 +462,7 @@ fn PrefixKeyGenerator(comptime EntropyReaderType: type) type { | |||
| 444 | } else struct { | 462 | } else struct { | 
| 445 | pub fn generate(self: *Self) !void { | 463 | pub fn generate(self: *Self) !void { | 
| 446 | var cpu_count = try std.Thread.getCpuCount(); | 464 | var cpu_count = try std.Thread.getCpuCount(); | 
| 447 | var threads = try self.allocator.alloc(std.Thread, cpu_count); | 465 | var threads = try self.allocator.alloc(std.Thread, cpu_count*4); | 
| 448 | defer self.allocator.free(threads); | 466 | defer self.allocator.free(threads); | 
| 449 | for (threads) |*thread| thread.* = try std.Thread.spawn(.{}, Self.generatePrivate, .{self}); | 467 | for (threads) |*thread| thread.* = try std.Thread.spawn(.{}, Self.generatePrivate, .{self}); | 
| 450 | for (threads) |thread| thread.join(); | 468 | for (threads) |thread| thread.join(); | 
| @@ -453,7 +471,7 @@ fn PrefixKeyGenerator(comptime EntropyReaderType: type) type { | |||
| 453 | }; | 471 | }; | 
| 454 | } | 472 | } | 
| 455 | 473 | ||
| 456 | fn toUpper(allocator: *Allocator, slice: []const u8) ![]u8 { | 474 | fn toUpper(allocator: Allocator, slice: []const u8) ![]u8 { | 
| 457 | const result = try allocator.alloc(u8, slice.len); | 475 | const result = try allocator.alloc(u8, slice.len); | 
| 458 | for (slice) |c, i| result[i] = ascii.toUpper(c); | 476 | for (slice) |c, i| result[i] = ascii.toUpper(c); | 
| 459 | return result; | 477 | return result; | 
| @@ -519,7 +537,7 @@ pub const Nkey = union(enum) { | |||
| 519 | } | 537 | } | 
| 520 | }; | 538 | }; | 
| 521 | 539 | ||
| 522 | pub fn readKeyFile(allocator: *Allocator, file: fs.File) ?Nkey { | 540 | pub fn readKeyFile(allocator: Allocator, file: fs.File) ?Nkey { | 
| 523 | var bytes = file.readToEndAlloc(allocator, std.math.maxInt(usize)) catch fatal("could not read key file", .{}); | 541 | var bytes = file.readToEndAlloc(allocator, std.math.maxInt(usize)) catch fatal("could not read key file", .{}); | 
| 524 | defer { | 542 | defer { | 
| 525 | for (bytes) |*b| b.* = 0; | 543 | for (bytes) |*b| b.* = 0; |