diff options
Diffstat (limited to 'src/znk.zig')
-rw-r--r-- | src/znk.zig | 93 |
1 files changed, 75 insertions, 18 deletions
diff --git a/src/znk.zig b/src/znk.zig index ab36c96..fe66cb5 100644 --- a/src/znk.zig +++ b/src/znk.zig | |||
@@ -162,7 +162,7 @@ pub fn cmdGen(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !voi | |||
162 | 162 | ||
163 | try PrefixKeyGenerator.init(arena, ty.?, capitalized_prefix).generate(); | 163 | try PrefixKeyGenerator.init(arena, ty.?, capitalized_prefix).generate(); |
164 | } else { | 164 | } else { |
165 | var kp = nkeys.SeedKeyPair.init(ty.?) catch |e| fatal("could not generate key pair: {e}", .{e}); | 165 | var kp = nkeys.SeedKeyPair.generate(ty.?) catch |e| fatal("could not generate key pair: {e}", .{e}); |
166 | defer kp.wipe(); | 166 | defer kp.wipe(); |
167 | try stdout.writeAll(&kp.seed); | 167 | try stdout.writeAll(&kp.seed); |
168 | try stdout.writeAll("\n"); | 168 | try stdout.writeAll("\n"); |
@@ -396,7 +396,7 @@ const PrefixKeyGenerator = struct { | |||
396 | while (true) { | 396 | while (true) { |
397 | if (self.done.load(.SeqCst)) return; | 397 | if (self.done.load(.SeqCst)) return; |
398 | 398 | ||
399 | var kp = nkeys.SeedKeyPair.init(self.ty) catch |e| fatal("could not generate key pair: {e}", .{e}); | 399 | var kp = nkeys.SeedKeyPair.generate(self.ty) catch |e| fatal("could not generate key pair: {e}", .{e}); |
400 | defer kp.wipe(); | 400 | defer kp.wipe(); |
401 | var public_key = kp.publicKey() catch |e| fatal("could not generate public key: {e}", .{e}); | 401 | var public_key = kp.publicKey() catch |e| fatal("could not generate public key: {e}", .{e}); |
402 | if (!mem.startsWith(u8, public_key[1..], self.prefix)) continue; | 402 | if (!mem.startsWith(u8, public_key[1..], self.prefix)) continue; |
@@ -425,22 +425,6 @@ const PrefixKeyGenerator = struct { | |||
425 | }; | 425 | }; |
426 | }; | 426 | }; |
427 | 427 | ||
428 | pub fn readKeyFile(allocator: *Allocator, file: fs.File) nkeys.Key { | ||
429 | var bytes = file.readToEndAlloc(allocator, std.math.maxInt(usize)) catch fatal("could not read key file", .{}); | ||
430 | |||
431 | var iterator = mem.split(bytes, "\n"); | ||
432 | while (iterator.next()) |line| { | ||
433 | if (nkeys.isValidEncoding(line) and line.len == nkeys.text_seed_len) { | ||
434 | var k = nkeys.fromText(line) catch continue; | ||
435 | defer k.wipe(); | ||
436 | allocator.free(bytes); | ||
437 | return k; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | fatal("could not find a valid key", .{}); | ||
442 | } | ||
443 | |||
444 | fn two(slice: []const bool) bool { | 428 | fn two(slice: []const bool) bool { |
445 | var one = false; | 429 | var one = false; |
446 | for (slice) |x| if (x and one) { | 430 | for (slice) |x| if (x and one) { |
@@ -457,6 +441,79 @@ fn toUpper(allocator: *Allocator, slice: []const u8) ![]u8 { | |||
457 | return result; | 441 | return result; |
458 | } | 442 | } |
459 | 443 | ||
444 | pub const Nkey = union(enum) { | ||
445 | seed_key_pair: nkeys.SeedKeyPair, | ||
446 | public_key: nkeys.PublicKey, | ||
447 | |||
448 | const Self = @This(); | ||
449 | |||
450 | pub fn publicKey(self: *const Self) !nkeys.text_public { | ||
451 | return switch (self.*) { | ||
452 | .seed_key_pair => |*kp| try kp.publicKey(), | ||
453 | .public_key => |*pk| try pk.publicKey(), | ||
454 | }; | ||
455 | } | ||
456 | |||
457 | pub fn intoPublicKey(self: *const Self) !nkeys.PublicKey { | ||
458 | return switch (self.*) { | ||
459 | .seed_key_pair => |*kp| try kp.intoPublicKey(), | ||
460 | .public_key => |pk| pk, | ||
461 | }; | ||
462 | } | ||
463 | |||
464 | pub fn verify( | ||
465 | self: *const Self, | ||
466 | msg: []const u8, | ||
467 | sig: [std.crypto.sign.Ed25519.signature_length]u8, | ||
468 | ) !void { | ||
469 | return switch (self.*) { | ||
470 | .seed_key_pair => |*kp| try kp.verify(msg, sig), | ||
471 | .public_key => |*pk| try pk.verify(msg, sig), | ||
472 | }; | ||
473 | } | ||
474 | |||
475 | pub fn wipe(self: *Self) void { | ||
476 | return switch (self.*) { | ||
477 | .seed_key_pair => |*kp| kp.wipe(), | ||
478 | .public_key => |*pk| pk.wipe(), | ||
479 | }; | ||
480 | } | ||
481 | |||
482 | pub fn fromText(text: []const u8) !Self { | ||
483 | if (!nkeys.isValidEncoding(text)) return error.InvalidEncoding; | ||
484 | switch (text[0]) { | ||
485 | 'S' => { | ||
486 | // It's a seed. | ||
487 | if (text.len != nkeys.text_seed_len) return error.InvalidSeed; | ||
488 | return Self{ .seed_key_pair = try nkeys.SeedKeyPair.fromTextSeed(text[0..nkeys.text_seed_len]) }; | ||
489 | }, | ||
490 | 'P' => return error.InvalidEncoding, // unsupported for now | ||
491 | else => { | ||
492 | if (text.len != nkeys.text_public_len) return error.InvalidEncoding; | ||
493 | return Self{ .public_key = try nkeys.PublicKey.fromTextPublicKey(text[0..nkeys.text_public_len]) }; | ||
494 | }, | ||
495 | } | ||
496 | } | ||
497 | }; | ||
498 | |||
499 | pub fn readKeyFile(allocator: *Allocator, file: fs.File) Nkey { | ||
500 | var bytes = file.readToEndAlloc(allocator, std.math.maxInt(usize)) catch fatal("could not read key file", .{}); | ||
501 | |||
502 | var iterator = mem.split(bytes, "\n"); | ||
503 | while (iterator.next()) |line| { | ||
504 | if (nkeys.isValidEncoding(line) and line.len == nkeys.text_seed_len) { | ||
505 | var k = Nkey.fromText(line) catch continue; | ||
506 | defer k.wipe(); | ||
507 | allocator.free(bytes); | ||
508 | return k; | ||
509 | } | ||
510 | } | ||
511 | |||
512 | fatal("could not find a valid key", .{}); | ||
513 | } | ||
514 | |||
460 | test { | 515 | test { |
461 | testing.refAllDecls(@This()); | 516 | testing.refAllDecls(@This()); |
517 | testing.refAllDecls(Nkey); | ||
518 | testing.refAllDecls(PrefixKeyGenerator); | ||
462 | } | 519 | } |