diff options
author | Rutger Broekhoff | 2021-05-22 21:19:53 +0200 |
---|---|---|
committer | Rutger Broekhoff | 2021-05-22 21:19:53 +0200 |
commit | 07ac8dc00e7676d7845a881970c259679b0c5d23 (patch) | |
tree | b2ea799f35eab953d083472ea435ca101e7f321f /src/nkeys.zig | |
parent | 4716921ce42b5153b5c60edf3638e1592f72f743 (diff) | |
download | zig-nkeys-07ac8dc00e7676d7845a881970c259679b0c5d23.tar.gz zig-nkeys-07ac8dc00e7676d7845a881970c259679b0c5d23.zip |
Clean up
`NKey` has been replaced with `Nkey` in all Zig source files,
even though this capitalization is technically incorrect.
The standard library also uses 'strict' camel/PascalCase everywhere,
meaning that abbreviations like CRC, AES and GUID are spelled like
Crc, Aes and Guid respectively.
`var` has been replaced with `const` where applicable.
Also, the `Key` type has been moved from src/nkeys.zig
to src/znk.zig for now - it's still a little bit lacking and might
not need to be included in the library.
Diffstat (limited to 'src/nkeys.zig')
-rw-r--r-- | src/nkeys.zig | 189 |
1 files changed, 70 insertions, 119 deletions
diff --git a/src/nkeys.zig b/src/nkeys.zig index 8806a81..1880fa8 100644 --- a/src/nkeys.zig +++ b/src/nkeys.zig | |||
@@ -11,63 +11,8 @@ const Error = error{ | |||
11 | InvalidPrefixByte, | 11 | InvalidPrefixByte, |
12 | InvalidEncoding, | 12 | InvalidEncoding, |
13 | InvalidSeed, | 13 | InvalidSeed, |
14 | NoNKeySeedFound, | 14 | NoNkeySeedFound, |
15 | NoNKeyUserSeedFound, | 15 | NoNkeyUserSeedFound, |
16 | }; | ||
17 | |||
18 | pub fn fromText(text: []const u8) !Key { | ||
19 | if (!isValidEncoding(text)) return error.InvalidEncoding; | ||
20 | switch (text[0]) { | ||
21 | 'S' => { | ||
22 | // It's a seed. | ||
23 | if (text.len != text_seed_len) return error.InvalidSeed; | ||
24 | return Key{ .seed_key_pair = try fromSeed(text[0..text_seed_len]) }; | ||
25 | }, | ||
26 | 'P' => return error.InvalidEncoding, // unsupported for now | ||
27 | else => { | ||
28 | if (text.len != text_public_len) return error.InvalidEncoding; | ||
29 | return Key{ .public_key = try fromPublicKey(text[0..text_public_len]) }; | ||
30 | }, | ||
31 | } | ||
32 | } | ||
33 | |||
34 | pub const Key = union(enum) { | ||
35 | seed_key_pair: SeedKeyPair, | ||
36 | public_key: PublicKey, | ||
37 | |||
38 | const Self = @This(); | ||
39 | |||
40 | pub fn publicKey(self: *const Self) !text_public { | ||
41 | return switch (self.*) { | ||
42 | .seed_key_pair => |*kp| try kp.publicKey(), | ||
43 | .public_key => |*pk| try pk.publicKey(), | ||
44 | }; | ||
45 | } | ||
46 | |||
47 | pub fn intoPublicKey(self: *const Self) !PublicKey { | ||
48 | return switch (self.*) { | ||
49 | .seed_key_pair => |*kp| try kp.intoPublicKey(), | ||
50 | .public_key => |pk| pk, | ||
51 | }; | ||
52 | } | ||
53 | |||
54 | pub fn verify( | ||
55 | self: *const Self, | ||
56 | msg: []const u8, | ||
57 | sig: [Ed25519.signature_length]u8, | ||
58 | ) !void { | ||
59 | return switch (self.*) { | ||
60 | .seed_key_pair => |*kp| try kp.verify(msg, sig), | ||
61 | .public_key => |*pk| try pk.verify(msg, sig), | ||
62 | }; | ||
63 | } | ||
64 | |||
65 | pub fn wipe(self: *Self) void { | ||
66 | return switch (self.*) { | ||
67 | .seed_key_pair => |*kp| kp.wipe(), | ||
68 | .public_key => |*pk| pk.wipe(), | ||
69 | }; | ||
70 | } | ||
71 | }; | 16 | }; |
72 | 17 | ||
73 | pub const KeyTypePrefixByte = enum(u8) { | 18 | pub const KeyTypePrefixByte = enum(u8) { |
@@ -100,22 +45,24 @@ pub const SeedKeyPair = struct { | |||
100 | 45 | ||
101 | seed: text_seed, | 46 | seed: text_seed, |
102 | 47 | ||
103 | pub fn init(prefix: PublicPrefixByte) !Self { | 48 | pub fn generate(prefix: PublicPrefixByte) !Self { |
104 | var raw_seed: [Ed25519.seed_length]u8 = undefined; | 49 | var raw_seed: [Ed25519.seed_length]u8 = undefined; |
105 | crypto.random.bytes(&raw_seed); | 50 | crypto.random.bytes(&raw_seed); |
106 | defer wipeBytes(&raw_seed); | 51 | defer wipeBytes(&raw_seed); |
107 | 52 | ||
108 | var seed = try encodeSeed(prefix, &raw_seed); | 53 | return Self{ .seed = try encodeSeed(prefix, &raw_seed) }; |
109 | return Self{ .seed = seed }; | ||
110 | } | 54 | } |
111 | 55 | ||
112 | pub fn initFromSeed(seed: *const text_seed) !Self { | 56 | pub fn fromTextSeed(seed: *const text_seed) !Self { |
113 | var decoded = try decodeSeed(seed); | 57 | var decoded = try decodeSeed(seed); |
114 | defer decoded.wipe(); | 58 | decoded.wipe(); |
115 | |||
116 | return Self{ .seed = seed.* }; | 59 | return Self{ .seed = seed.* }; |
117 | } | 60 | } |
118 | 61 | ||
62 | pub fn fromRawSeed(prefix: PublicPrefixByte, raw_seed: *const [Ed25519.seed_length]u8) !Self { | ||
63 | return Self{ .seed = try encodeSeed(prefix, raw_seed) }; | ||
64 | } | ||
65 | |||
119 | fn rawSeed(self: *const Self) ![Ed25519.seed_length]u8 { | 66 | fn rawSeed(self: *const Self) ![Ed25519.seed_length]u8 { |
120 | return (try decodeSeed(&self.seed)).seed; | 67 | return (try decodeSeed(&self.seed)).seed; |
121 | } | 68 | } |
@@ -140,6 +87,7 @@ pub const SeedKeyPair = struct { | |||
140 | 87 | ||
141 | pub fn intoPublicKey(self: *const Self) !PublicKey { | 88 | pub fn intoPublicKey(self: *const Self) !PublicKey { |
142 | var decoded = try decodeSeed(&self.seed); | 89 | var decoded = try decodeSeed(&self.seed); |
90 | defer decoded.wipe(); | ||
143 | var kp = try Ed25519.KeyPair.create(decoded.seed); | 91 | var kp = try Ed25519.KeyPair.create(decoded.seed); |
144 | defer wipeKeyPair(&kp); | 92 | defer wipeKeyPair(&kp); |
145 | return PublicKey{ | 93 | return PublicKey{ |
@@ -186,6 +134,16 @@ pub const PublicKey = struct { | |||
186 | prefix: PublicPrefixByte, | 134 | prefix: PublicPrefixByte, |
187 | key: [Ed25519.public_length]u8, | 135 | key: [Ed25519.public_length]u8, |
188 | 136 | ||
137 | pub fn fromTextPublicKey(text: *const text_public) !PublicKey { | ||
138 | var decoded = try decode(1, Ed25519.public_length, text); | ||
139 | defer decoded.wipe(); // gets copied | ||
140 | |||
141 | return PublicKey{ | ||
142 | .prefix = try PublicPrefixByte.fromU8(decoded.prefix[0]), | ||
143 | .key = decoded.data, | ||
144 | }; | ||
145 | } | ||
146 | |||
189 | pub fn publicKey(self: *const Self) !text_public { | 147 | pub fn publicKey(self: *const Self) !text_public { |
190 | return try encodePublic(self.prefix, &self.key); | 148 | return try encodePublic(self.prefix, &self.key); |
191 | } | 149 | } |
@@ -199,8 +157,8 @@ pub const PublicKey = struct { | |||
199 | } | 157 | } |
200 | 158 | ||
201 | pub fn wipe(self: *Self) void { | 159 | pub fn wipe(self: *Self) void { |
202 | self.prefix = .user; | 160 | self.prefix = .account; |
203 | std.crypto.random.bytes(&self.key); | 161 | wipeBytes(&self.key); |
204 | } | 162 | } |
205 | }; | 163 | }; |
206 | 164 | ||
@@ -247,22 +205,22 @@ fn encode( | |||
247 | mem.writeIntLittle(u16, buf[buf.len - 2 .. buf.len], checksum); | 205 | mem.writeIntLittle(u16, buf[buf.len - 2 .. buf.len], checksum); |
248 | 206 | ||
249 | var text: encoded_key(prefix_len, data_len) = undefined; | 207 | var text: encoded_key(prefix_len, data_len) = undefined; |
250 | _ = base32.Encoder.encode(&text, &buf); | 208 | std.debug.assert(base32.Encoder.encode(&text, &buf).len == text.len); |
251 | 209 | ||
252 | return text; | 210 | return text; |
253 | } | 211 | } |
254 | 212 | ||
255 | pub fn encodeSeed(prefix: PublicPrefixByte, src: *const [Ed25519.seed_length]u8) !text_seed { | 213 | pub fn encodeSeed(prefix: PublicPrefixByte, src: *const [Ed25519.seed_length]u8) !text_seed { |
256 | var full_prefix = [_]u8{ | 214 | const full_prefix = &[_]u8{ |
257 | @enumToInt(KeyTypePrefixByte.seed) | (@enumToInt(prefix) >> 5), | 215 | @enumToInt(KeyTypePrefixByte.seed) | (@enumToInt(prefix) >> 5), |
258 | (@enumToInt(prefix) & 0b00011111) << 3, | 216 | (@enumToInt(prefix) & 0b00011111) << 3, |
259 | }; | 217 | }; |
260 | return encode(full_prefix.len, src.len, &full_prefix, src); | 218 | return encode(full_prefix.len, src.len, full_prefix, src); |
261 | } | 219 | } |
262 | 220 | ||
263 | pub fn decodePrivate(text: *const text_private) ![Ed25519.secret_length]u8 { | 221 | pub fn decodePrivate(text: *const text_private) ![Ed25519.secret_length]u8 { |
264 | var decoded = try decode(1, Ed25519.secret_length, text); | 222 | var decoded = try decode(1, Ed25519.secret_length, text); |
265 | defer wipeBytes(&decoded.data); | 223 | defer decoded.wipe(); |
266 | if (decoded.prefix[0] != @enumToInt(KeyTypePrefixByte.private)) | 224 | if (decoded.prefix[0] != @enumToInt(KeyTypePrefixByte.private)) |
267 | return error.InvalidPrefixByte; | 225 | return error.InvalidPrefixByte; |
268 | return decoded.data; | 226 | return decoded.data; |
@@ -270,15 +228,23 @@ pub fn decodePrivate(text: *const text_private) ![Ed25519.secret_length]u8 { | |||
270 | 228 | ||
271 | pub fn decodePublic(prefix: PublicPrefixByte, text: *const text_public) ![Ed25519.public_length]u8 { | 229 | pub fn decodePublic(prefix: PublicPrefixByte, text: *const text_public) ![Ed25519.public_length]u8 { |
272 | var decoded = try decode(1, Ed25519.public_length, text); | 230 | var decoded = try decode(1, Ed25519.public_length, text); |
231 | defer decoded.wipe(); | ||
273 | if (decoded.data[0] != @enumToInt(prefix)) | 232 | if (decoded.data[0] != @enumToInt(prefix)) |
274 | return error.InvalidPrefixByte; | 233 | return error.InvalidPrefixByte; |
275 | return decoded.data; | 234 | return decoded.data; |
276 | } | 235 | } |
277 | 236 | ||
278 | fn DecodedNKey(comptime prefix_len: usize, comptime data_len: usize) type { | 237 | fn DecodedNkey(comptime prefix_len: usize, comptime data_len: usize) type { |
279 | return struct { | 238 | return struct { |
239 | const Self = @This(); | ||
240 | |||
280 | prefix: [prefix_len]u8, | 241 | prefix: [prefix_len]u8, |
281 | data: [data_len]u8, | 242 | data: [data_len]u8, |
243 | |||
244 | pub fn wipe(self: *Self) void { | ||
245 | self.prefix[0] = @enumToInt(PublicPrefixByte.account); | ||
246 | wipeBytes(&self.data); | ||
247 | } | ||
282 | }; | 248 | }; |
283 | } | 249 | } |
284 | 250 | ||
@@ -286,15 +252,15 @@ fn decode( | |||
286 | comptime prefix_len: usize, | 252 | comptime prefix_len: usize, |
287 | comptime data_len: usize, | 253 | comptime data_len: usize, |
288 | text: *const [base32.Encoder.calcSize(prefix_len + data_len + 2)]u8, | 254 | text: *const [base32.Encoder.calcSize(prefix_len + data_len + 2)]u8, |
289 | ) !DecodedNKey(prefix_len, data_len) { | 255 | ) !DecodedNkey(prefix_len, data_len) { |
290 | var raw: [prefix_len + data_len + 2]u8 = undefined; | 256 | var raw: [prefix_len + data_len + 2]u8 = undefined; |
291 | defer wipeBytes(&raw); | 257 | defer wipeBytes(&raw); |
292 | _ = try base32.Decoder.decode(&raw, text[0..]); | 258 | std.debug.assert((try base32.Decoder.decode(&raw, text[0..])).len == raw.len); |
293 | 259 | ||
294 | var checksum = mem.readIntLittle(u16, raw[raw.len - 2 .. raw.len]); | 260 | var checksum = mem.readIntLittle(u16, raw[raw.len - 2 .. raw.len]); |
295 | try crc16.validate(raw[0 .. raw.len - 2], checksum); | 261 | try crc16.validate(raw[0 .. raw.len - 2], checksum); |
296 | 262 | ||
297 | return DecodedNKey(prefix_len, data_len){ | 263 | return DecodedNkey(prefix_len, data_len){ |
298 | .prefix = raw[0..prefix_len].*, | 264 | .prefix = raw[0..prefix_len].*, |
299 | .data = raw[prefix_len .. raw.len - 2].*, | 265 | .data = raw[prefix_len .. raw.len - 2].*, |
300 | }; | 266 | }; |
@@ -314,7 +280,7 @@ pub const DecodedSeed = struct { | |||
314 | 280 | ||
315 | pub fn decodeSeed(text: *const text_seed) !DecodedSeed { | 281 | pub fn decodeSeed(text: *const text_seed) !DecodedSeed { |
316 | var decoded = try decode(2, Ed25519.seed_length, text); | 282 | var decoded = try decode(2, Ed25519.seed_length, text); |
317 | defer wipeBytes(&decoded.data); // gets copied | 283 | defer decoded.wipe(); // gets copied |
318 | 284 | ||
319 | var key_ty_prefix = decoded.prefix[0] & 0b11111000; | 285 | var key_ty_prefix = decoded.prefix[0] & 0b11111000; |
320 | var entity_ty_prefix = (decoded.prefix[0] & 0b00000111) << 5 | ((decoded.prefix[1] & 0b11111000) >> 3); | 286 | var entity_ty_prefix = (decoded.prefix[0] & 0b00000111) << 5 | ((decoded.prefix[1] & 0b11111000) >> 3); |
@@ -328,22 +294,6 @@ pub fn decodeSeed(text: *const text_seed) !DecodedSeed { | |||
328 | }; | 294 | }; |
329 | } | 295 | } |
330 | 296 | ||
331 | pub fn fromPublicKey(text: *const text_public) !PublicKey { | ||
332 | var decoded = try decode(1, Ed25519.public_length, text); | ||
333 | defer wipeBytes(&decoded.data); // gets copied | ||
334 | |||
335 | return PublicKey{ | ||
336 | .prefix = try PublicPrefixByte.fromU8(decoded.prefix[0]), | ||
337 | .key = decoded.data, | ||
338 | }; | ||
339 | } | ||
340 | |||
341 | pub fn fromSeed(text: *const text_seed) !SeedKeyPair { | ||
342 | var res = try decodeSeed(text); | ||
343 | wipeBytes(&res.seed); | ||
344 | return SeedKeyPair{ .seed = text.* }; | ||
345 | } | ||
346 | |||
347 | pub fn isValidEncoding(text: []const u8) bool { | 297 | pub fn isValidEncoding(text: []const u8) bool { |
348 | if (text.len < 4) return false; | 298 | if (text.len < 4) return false; |
349 | var made_crc: u16 = 0; | 299 | var made_crc: u16 = 0; |
@@ -367,24 +317,21 @@ pub fn isValidEncoding(text: []const u8) bool { | |||
367 | 317 | ||
368 | pub fn isValidSeed(text: *const text_seed) bool { | 318 | pub fn isValidSeed(text: *const text_seed) bool { |
369 | var res = decodeSeed(text) catch return false; | 319 | var res = decodeSeed(text) catch return false; |
370 | wipeBytes(&res.seed); | 320 | res.wipe(); |
371 | return true; | 321 | return true; |
372 | } | 322 | } |
373 | 323 | ||
374 | pub fn isValidPublicKey(text: *const text_public, with_type: ?PublicPrefixByte) bool { | 324 | pub fn isValidPublicKey(text: *const text_public, with_type: ?PublicPrefixByte) bool { |
375 | var res = decode(1, Ed25519.public_length, text) catch return false; | 325 | var res = decode(1, Ed25519.public_length, text) catch return false; |
376 | var public = PublicPrefixByte.fromU8(res.data[0]) catch return false; | 326 | defer res.wipe(); |
327 | const public = PublicPrefixByte.fromU8(res.data[0]) catch return false; | ||
377 | return if (with_type) |ty| public == ty else true; | 328 | return if (with_type) |ty| public == ty else true; |
378 | } | 329 | } |
379 | 330 | ||
380 | pub fn fromRawSeed(prefix: PublicPrefixByte, raw_seed: *const [Ed25519.seed_length]u8) !SeedKeyPair { | ||
381 | return SeedKeyPair{ .seed = try encodeSeed(prefix, raw_seed) }; | ||
382 | } | ||
383 | |||
384 | pub fn getNextLine(text: []const u8, off: *usize) ?[]const u8 { | 331 | pub fn getNextLine(text: []const u8, off: *usize) ?[]const u8 { |
385 | if (off.* >= text.len) return null; | 332 | if (off.* >= text.len) return null; |
386 | var newline_pos = mem.indexOfPos(u8, text, off.*, "\n") orelse return null; | 333 | const newline_pos = mem.indexOfPos(u8, text, off.*, "\n") orelse return null; |
387 | var start = off.*; | 334 | const start = off.*; |
388 | var end = newline_pos; | 335 | var end = newline_pos; |
389 | if (newline_pos > 0 and text[newline_pos - 1] == '\r') end -= 1; | 336 | if (newline_pos > 0 and text[newline_pos - 1] == '\r') end -= 1; |
390 | off.* = newline_pos + 1; | 337 | off.* = newline_pos + 1; |
@@ -424,13 +371,13 @@ pub fn findKeySection(text: []const u8, off: *usize) ?[]const u8 { | |||
424 | 371 | ||
425 | // TODO(rutgerbrf): switch to std.mem.SplitIterator | 372 | // TODO(rutgerbrf): switch to std.mem.SplitIterator |
426 | while (true) { | 373 | while (true) { |
427 | var opening_line = getNextLine(text, off) orelse return null; | 374 | const opening_line = getNextLine(text, off) orelse return null; |
428 | if (!isKeySectionBarrier(opening_line)) continue; | 375 | if (!isKeySectionBarrier(opening_line)) continue; |
429 | 376 | ||
430 | var contents_line = getNextLine(text, off) orelse return null; | 377 | const contents_line = getNextLine(text, off) orelse return null; |
431 | if (!areKeySectionContentsValid(contents_line)) continue; | 378 | if (!areKeySectionContentsValid(contents_line)) continue; |
432 | 379 | ||
433 | var closing_line = getNextLine(text, off) orelse return null; | 380 | const closing_line = getNextLine(text, off) orelse return null; |
434 | if (!isKeySectionBarrier(closing_line)) continue; | 381 | if (!isKeySectionBarrier(closing_line)) continue; |
435 | 382 | ||
436 | return contents_line; | 383 | return contents_line; |
@@ -442,82 +389,86 @@ pub fn parseDecoratedJwt(contents: []const u8) ![]const u8 { | |||
442 | return findKeySection(contents, ¤t_off) orelse return contents; | 389 | return findKeySection(contents, ¤t_off) orelse return contents; |
443 | } | 390 | } |
444 | 391 | ||
445 | fn validNKey(text: []const u8) bool { | 392 | fn validNkey(text: []const u8) bool { |
446 | var valid_prefix = | 393 | const valid_prefix = |
447 | mem.startsWith(u8, text, "SO") or | 394 | mem.startsWith(u8, text, "SO") or |
448 | mem.startsWith(u8, text, "SA") or | 395 | mem.startsWith(u8, text, "SA") or |
449 | mem.startsWith(u8, text, "SU"); | 396 | mem.startsWith(u8, text, "SU"); |
450 | var valid_len = text.len >= text_seed_len; | 397 | const valid_len = text.len >= text_seed_len; |
451 | return valid_prefix and valid_len; | 398 | return valid_prefix and valid_len; |
452 | } | 399 | } |
453 | 400 | ||
454 | fn findNKey(text: []const u8) ?[]const u8 { | 401 | fn findNkey(text: []const u8) ?[]const u8 { |
455 | var current_off: usize = 0; | 402 | var current_off: usize = 0; |
456 | while (true) { | 403 | while (true) { |
457 | var line = getNextLine(text, ¤t_off) orelse return null; | 404 | var line = getNextLine(text, ¤t_off) orelse return null; |
458 | for (line) |c, i| { | 405 | for (line) |c, i| { |
459 | if (!ascii.isSpace(c)) { | 406 | if (!ascii.isSpace(c)) { |
460 | if (validNKey(line[i..])) return line[i..]; | 407 | if (validNkey(line[i..])) return line[i..]; |
461 | break; | 408 | break; |
462 | } | 409 | } |
463 | } | 410 | } |
464 | } | 411 | } |
465 | } | 412 | } |
466 | 413 | ||
467 | pub fn parseDecoratedNKey(contents: []const u8) !SeedKeyPair { | 414 | pub fn parseDecoratedNkey(contents: []const u8) !SeedKeyPair { |
468 | var current_off: usize = 0; | 415 | var current_off: usize = 0; |
469 | |||
470 | var seed: ?[]const u8 = null; | 416 | var seed: ?[]const u8 = null; |
471 | if (findKeySection(contents, ¤t_off) != null) | 417 | if (findKeySection(contents, ¤t_off) != null) |
472 | seed = findKeySection(contents, ¤t_off); | 418 | seed = findKeySection(contents, ¤t_off); |
473 | if (seed == null) | 419 | if (seed == null) |
474 | seed = findNKey(contents) orelse return error.NoNKeySeedFound; | 420 | seed = findNkey(contents) orelse return error.NoNkeySeedFound; |
475 | if (!validNKey(seed.?)) | 421 | if (!validNkey(seed.?)) |
476 | return error.NoNKeySeedFound; | 422 | return error.NoNkeySeedFound; |
477 | return fromSeed(seed.?[0..text_seed_len]); | 423 | return SeedKeyPair.fromTextSeed(seed.?[0..text_seed_len]); |
478 | } | 424 | } |
479 | 425 | ||
480 | pub fn parseDecoratedUserNKey(contents: []const u8) !SeedKeyPair { | 426 | pub fn parseDecoratedUserNkey(contents: []const u8) !SeedKeyPair { |
481 | var key = try parseDecoratedNKey(contents); | 427 | var key = try parseDecoratedNkey(contents); |
482 | if (!mem.startsWith(u8, &key.seed, "SU")) return error.NoNKeyUserSeedFound; | 428 | if (!mem.startsWith(u8, &key.seed, "SU")) return error.NoNkeyUserSeedFound; |
483 | defer key.wipe(); | 429 | defer key.wipe(); |
484 | return key; | 430 | return key; |
485 | } | 431 | } |
486 | 432 | ||
487 | test { | 433 | test { |
488 | testing.refAllDecls(@This()); | 434 | testing.refAllDecls(@This()); |
489 | testing.refAllDecls(Key); | ||
490 | testing.refAllDecls(SeedKeyPair); | 435 | testing.refAllDecls(SeedKeyPair); |
491 | testing.refAllDecls(PublicKey); | 436 | testing.refAllDecls(PublicKey); |
492 | } | 437 | } |
493 | 438 | ||
494 | test { | 439 | test { |
495 | var key_pair = try SeedKeyPair.init(PublicPrefixByte.server); | 440 | var key_pair = try SeedKeyPair.generate(PublicPrefixByte.server); |
496 | defer key_pair.wipe(); | 441 | defer key_pair.wipe(); |
497 | 442 | ||
498 | var decoded_seed = try decodeSeed(&key_pair.seed); | 443 | var decoded_seed = try decodeSeed(&key_pair.seed); |
444 | defer decoded_seed.wipe(); | ||
499 | var encoded_second_time = try encodeSeed(decoded_seed.prefix, &decoded_seed.seed); | 445 | var encoded_second_time = try encodeSeed(decoded_seed.prefix, &decoded_seed.seed); |
446 | defer wipeBytes(&encoded_second_time); | ||
500 | try testing.expectEqualSlices(u8, &key_pair.seed, &encoded_second_time); | 447 | try testing.expectEqualSlices(u8, &key_pair.seed, &encoded_second_time); |
501 | try testing.expect(isValidEncoding(&key_pair.seed)); | 448 | try testing.expect(isValidEncoding(&key_pair.seed)); |
502 | 449 | ||
503 | var pub_key_str_a = try key_pair.publicKey(); | 450 | var pub_key_str_a = try key_pair.publicKey(); |
451 | defer wipeBytes(&pub_key_str_a); | ||
504 | var priv_key_str = try key_pair.privateKey(); | 452 | var priv_key_str = try key_pair.privateKey(); |
453 | defer wipeBytes(&priv_key_str); | ||
505 | try testing.expect(pub_key_str_a.len != 0); | 454 | try testing.expect(pub_key_str_a.len != 0); |
506 | try testing.expect(priv_key_str.len != 0); | 455 | try testing.expect(priv_key_str.len != 0); |
507 | try testing.expect(isValidEncoding(&pub_key_str_a)); | 456 | try testing.expect(isValidEncoding(&pub_key_str_a)); |
508 | try testing.expect(isValidEncoding(&priv_key_str)); | 457 | try testing.expect(isValidEncoding(&priv_key_str)); |
509 | wipeBytes(&priv_key_str); | ||
510 | 458 | ||
511 | var pub_key = try key_pair.intoPublicKey(); | 459 | var pub_key = try key_pair.intoPublicKey(); |
460 | defer pub_key.wipe(); | ||
512 | var pub_key_str_b = try pub_key.publicKey(); | 461 | var pub_key_str_b = try pub_key.publicKey(); |
462 | defer wipeBytes(&pub_key_str_b); | ||
513 | try testing.expectEqualSlices(u8, &pub_key_str_a, &pub_key_str_b); | 463 | try testing.expectEqualSlices(u8, &pub_key_str_a, &pub_key_str_b); |
514 | } | 464 | } |
515 | 465 | ||
516 | test { | 466 | test { |
517 | var creds_bytes = try std.fs.cwd().readFileAlloc(testing.allocator, "fixtures/test.creds", std.math.maxInt(usize)); | 467 | var creds_bytes = try std.fs.cwd().readFileAlloc(testing.allocator, "fixtures/test.creds", std.math.maxInt(usize)); |
518 | defer testing.allocator.free(creds_bytes); | 468 | defer testing.allocator.free(creds_bytes); |
469 | defer wipeBytes(creds_bytes); | ||
519 | 470 | ||
520 | // TODO(rutgerbrf): validate the contents of the results of these functions | 471 | // TODO(rutgerbrf): validate the contents of the results of these functions |
521 | _ = try parseDecoratedUserNKey(creds_bytes); | 472 | _ = try parseDecoratedUserNkey(creds_bytes); |
522 | _ = try parseDecoratedJwt(creds_bytes); | 473 | _ = try parseDecoratedJwt(creds_bytes); |
523 | } | 474 | } |