diff options
-rw-r--r-- | src/base32.zig | 40 | ||||
-rw-r--r-- | src/nkeys.zig | 18 |
2 files changed, 33 insertions, 25 deletions
diff --git a/src/base32.zig b/src/base32.zig index 26622d8..149e5f0 100644 --- a/src/base32.zig +++ b/src/base32.zig | |||
@@ -7,8 +7,26 @@ pub const Encoder = struct { | |||
7 | index: ?usize, | 7 | index: ?usize, |
8 | bit_off: u3, | 8 | bit_off: u3, |
9 | 9 | ||
10 | fn bitmask(self: *const Self) u8 { | 10 | pub fn init(buffer: []const u8) Encoder { |
11 | return @as(u8, 0b11111000) >> self.bit_off; | 11 | return .{ |
12 | .buffer = buffer, | ||
13 | .index = 0, | ||
14 | .bit_off = 0, | ||
15 | }; | ||
16 | } | ||
17 | |||
18 | pub fn calcSize(source_len: usize) usize { | ||
19 | const source_len_bits = source_len * 8; | ||
20 | return source_len_bits / 5 + (if (source_len_bits % 5 > 0) @as(usize, 1) else 0); | ||
21 | } | ||
22 | |||
23 | pub fn encode(dest: []u8, source: []const u8) []const u8 { | ||
24 | const out_len = calcSize(source.len); | ||
25 | std.debug.assert(dest.len >= out_len); | ||
26 | |||
27 | var e = init(source); | ||
28 | for (dest) |*b| b.* = e.next() orelse unreachable; | ||
29 | return dest[0..out_len]; | ||
12 | } | 30 | } |
13 | 31 | ||
14 | fn n_front_bits(self: *const Self) u3 { | 32 | fn n_front_bits(self: *const Self) u3 { |
@@ -34,7 +52,8 @@ pub const Encoder = struct { | |||
34 | // 5 0b00000111 2 0b11100 | 52 | // 5 0b00000111 2 0b11100 |
35 | // 6 0b00000011 3 0b11000 | 53 | // 6 0b00000011 3 0b11000 |
36 | // 7 0b00000001 4 0b10000 | 54 | // 7 0b00000001 4 0b10000 |
37 | const bits = self.buffer[index] & self.bitmask(); | 55 | const bitmask = @as(u8, 0b11111000) >> self.bit_off; |
56 | const bits = self.buffer[index] & bitmask; | ||
38 | if (self.bit_off >= 4) return @truncate(u5, bits << (self.bit_off - 3)); | 57 | if (self.bit_off >= 4) return @truncate(u5, bits << (self.bit_off - 3)); |
39 | return @truncate(u5, bits >> (3 - self.bit_off)); | 58 | return @truncate(u5, bits >> (3 - self.bit_off)); |
40 | } | 59 | } |
@@ -66,10 +85,12 @@ pub const Encoder = struct { | |||
66 | return front_bits | back_bits; | 85 | return front_bits | back_bits; |
67 | } | 86 | } |
68 | 87 | ||
88 | // Returns the corresponding ASCII character for 5 bits of the input. | ||
69 | fn char(unencoded: u5) u8 { | 89 | fn char(unencoded: u5) u8 { |
70 | return unencoded + (if (unencoded < 26) @as(u8, 'A') else '2' - 26); | 90 | return unencoded + (if (unencoded < 26) @as(u8, 'A') else '2' - 26); |
71 | } | 91 | } |
72 | 92 | ||
93 | // Returns the next byte of the encoded buffer. | ||
73 | pub fn next(self: *Self) ?u8 { | 94 | pub fn next(self: *Self) ?u8 { |
74 | const unencoded = self.next_u5() orelse return null; | 95 | const unencoded = self.next_u5() orelse return null; |
75 | return char(unencoded); | 96 | return char(unencoded); |
@@ -121,24 +142,11 @@ pub const Decoder = struct { | |||
121 | } | 142 | } |
122 | }; | 143 | }; |
123 | 144 | ||
124 | pub fn encodedLen(src_len: usize) usize { | ||
125 | const src_len_bits = src_len * 8; | ||
126 | return src_len_bits / 5 + (if (src_len_bits % 5 > 0) @as(usize, 1) else 0); | ||
127 | } | ||
128 | |||
129 | pub fn decodedLen(enc_len: usize) usize { | 145 | pub fn decodedLen(enc_len: usize) usize { |
130 | const enc_len_bits = enc_len * 5; | 146 | const enc_len_bits = enc_len * 5; |
131 | return enc_len_bits / 8; | 147 | return enc_len_bits / 8; |
132 | } | 148 | } |
133 | 149 | ||
134 | pub fn encode(bs: []const u8, out: []u8) usize { | ||
135 | var e = Encoder{ .buffer = bs, .index = 0, .bit_off = 0 }; | ||
136 | for (out) |*b, i| { | ||
137 | b.* = e.next() orelse return i; | ||
138 | } | ||
139 | return out.len; | ||
140 | } | ||
141 | |||
142 | pub fn decode(ps: []const u8, out: []u8) DecodeError!usize { | 150 | pub fn decode(ps: []const u8, out: []u8) DecodeError!usize { |
143 | var d = Decoder{}; | 151 | var d = Decoder{}; |
144 | var i: usize = 0; | 152 | var i: usize = 0; |
diff --git a/src/nkeys.zig b/src/nkeys.zig index b8693ae..818fd98 100644 --- a/src/nkeys.zig +++ b/src/nkeys.zig | |||
@@ -211,9 +211,9 @@ const binary_public_size = 1 + Ed25519.public_length + 2; | |||
211 | // Two prefix bytes, two CRC bytes | 211 | // Two prefix bytes, two CRC bytes |
212 | const binary_seed_size = 2 + Ed25519.seed_length + 2; | 212 | const binary_seed_size = 2 + Ed25519.seed_length + 2; |
213 | 213 | ||
214 | pub const text_private_len = base32.encodedLen(binary_private_size); | 214 | pub const text_private_len = base32.Encoder.calcSize(binary_private_size); |
215 | pub const text_public_len = base32.encodedLen(binary_public_size); | 215 | pub const text_public_len = base32.Encoder.calcSize(binary_public_size); |
216 | pub const text_seed_len = base32.encodedLen(binary_seed_size); | 216 | pub const text_seed_len = base32.Encoder.calcSize(binary_seed_size); |
217 | 217 | ||
218 | pub const text_private = [text_private_len]u8; | 218 | pub const text_private = [text_private_len]u8; |
219 | pub const text_public = [text_public_len]u8; | 219 | pub const text_public = [text_public_len]u8; |
@@ -227,8 +227,8 @@ pub fn encodePrivate(key: *const [Ed25519.secret_length]u8) !text_private { | |||
227 | return encode(1, key.len, &[_]u8{@enumToInt(KeyTypePrefixByte.private)}, key); | 227 | return encode(1, key.len, &[_]u8{@enumToInt(KeyTypePrefixByte.private)}, key); |
228 | } | 228 | } |
229 | 229 | ||
230 | fn EncodedKey(comptime prefix_len: usize, comptime data_len: usize) type { | 230 | fn encoded_key(comptime prefix_len: usize, comptime data_len: usize) type { |
231 | return [base32.encodedLen(prefix_len + data_len + 2)]u8; | 231 | return [base32.Encoder.calcSize(prefix_len + data_len + 2)]u8; |
232 | } | 232 | } |
233 | 233 | ||
234 | fn encode( | 234 | fn encode( |
@@ -236,7 +236,7 @@ fn encode( | |||
236 | comptime data_len: usize, | 236 | comptime data_len: usize, |
237 | prefix: *const [prefix_len]u8, | 237 | prefix: *const [prefix_len]u8, |
238 | data: *const [data_len]u8, | 238 | data: *const [data_len]u8, |
239 | ) !EncodedKey(prefix_len, data_len) { | 239 | ) !encoded_key(prefix_len, data_len) { |
240 | var buf: [prefix_len + data_len + 2]u8 = undefined; | 240 | var buf: [prefix_len + data_len + 2]u8 = undefined; |
241 | defer wipeBytes(&buf); | 241 | defer wipeBytes(&buf); |
242 | 242 | ||
@@ -246,8 +246,8 @@ fn encode( | |||
246 | var checksum = crc16.make(buf[0..off]); | 246 | var checksum = crc16.make(buf[0..off]); |
247 | mem.writeIntLittle(u16, buf[buf.len - 2 .. buf.len], checksum); | 247 | mem.writeIntLittle(u16, buf[buf.len - 2 .. buf.len], checksum); |
248 | 248 | ||
249 | var text: EncodedKey(prefix_len, data_len) = undefined; | 249 | var text: encoded_key(prefix_len, data_len) = undefined; |
250 | std.debug.assert(base32.encode(&buf, &text) == text.len); | 250 | _ = base32.Encoder.encode(&text, &buf); |
251 | 251 | ||
252 | return text; | 252 | return text; |
253 | } | 253 | } |
@@ -285,7 +285,7 @@ fn DecodedNKey(comptime prefix_len: usize, comptime data_len: usize) type { | |||
285 | fn decode( | 285 | fn decode( |
286 | comptime prefix_len: usize, | 286 | comptime prefix_len: usize, |
287 | comptime data_len: usize, | 287 | comptime data_len: usize, |
288 | text: *const [base32.encodedLen(prefix_len + data_len + 2)]u8, | 288 | text: *const [base32.Encoder.calcSize(prefix_len + data_len + 2)]u8, |
289 | ) !DecodedNKey(prefix_len, data_len) { | 289 | ) !DecodedNKey(prefix_len, data_len) { |
290 | var raw: [prefix_len + data_len + 2]u8 = undefined; | 290 | var raw: [prefix_len + data_len + 2]u8 = undefined; |
291 | defer wipeBytes(&raw); | 291 | defer wipeBytes(&raw); |