| ... | ... | @@ -11,20 +11,19 @@ pub const multihash_hex_digest_len = 2 * multihash_len; |
| 11 | 11 | pub const MultiHashHexDigest = [multihash_hex_digest_len]u8; |
| 12 | 12 | |
| 13 | 13 | pub const Nonce = packed struct(u64) { |
| 14 | | id: u16, |
| 15 | | reserved: u16 = 0, |
| 14 | id: u32, |
| 16 | 15 | checksum: u32, |
| 17 | 16 | |
| 18 | 17 | pub fn generate(name: []const u8) Nonce { |
| 19 | 18 | return .{ |
| 20 | | .id = std.crypto.random.intRangeLessThan(u16, 0x0001, 0xffff), |
| 19 | .id = std.crypto.random.intRangeLessThan(u32, 1, 0xffffffff), |
| 21 | 20 | .checksum = std.hash.Crc32.hash(name), |
| 22 | 21 | }; |
| 23 | 22 | } |
| 24 | 23 | |
| 25 | 24 | pub fn validate(n: Nonce, name: []const u8) bool { |
| 26 | 25 | switch (n.id) { |
| 27 | | 0x0000, 0xffff => return false, |
| 26 | 0x00000000, 0xffffffff => return false, |
| 28 | 27 | else => return std.hash.Crc32.hash(name) == n.checksum, |
| 29 | 28 | } |
| 30 | 29 | } |
| ... | ... | @@ -54,8 +53,8 @@ pub const Hash = struct { |
| 54 | 53 | pub const Algo = std.crypto.hash.sha2.Sha256; |
| 55 | 54 | pub const Digest = [Algo.digest_length]u8; |
| 56 | 55 | |
| 57 | | /// Example: "nnnn-vvvv-hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" |
| 58 | | pub const max_len = 32 + 1 + 32 + 1 + (16 + 32 + 192) / 6; |
| 56 | /// Example: "nnnn-vvvv-hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" |
| 57 | pub const max_len = 32 + 1 + 32 + 1 + (32 + 32 + 200) / 6; |
| 59 | 58 | |
| 60 | 59 | pub fn fromSlice(s: []const u8) Hash { |
| 61 | 60 | assert(s.len <= max_len); |
| ... | ... | @@ -96,14 +95,12 @@ pub const Hash = struct { |
| 96 | 95 | /// bytes and assumed be a valid zig identifier |
| 97 | 96 | /// * semver is the version field from build.zig.zon, asserted to be at |
| 98 | 97 | /// most 32 bytes |
| 99 | | /// * hashplus is the following 39-byte array, base64 encoded using -_ to make |
| 98 | /// * hashplus is the following 33-byte array, base64 encoded using -_ to make |
| 100 | 99 | /// it filesystem safe: |
| 101 | | /// - (2 bytes) LE u16 Package ID |
| 100 | /// - (4 bytes) LE u32 Package ID |
| 102 | 101 | /// - (4 bytes) LE u32 total decompressed size in bytes, overflow saturated |
| 103 | | /// - (24 bytes) truncated SHA-256 digest of hashed files of the package |
| 104 | | /// |
| 105 | | /// example: "nasm-2.16.1-3-AAD_ZlwACpGU-c3QXp_yNyn07Q5U9Rq-Cb1ur2G1" |
| 106 | | pub fn init(digest: Digest, name: []const u8, ver: []const u8, id: u16, size: u32) Hash { |
| 102 | /// - (25 bytes) truncated SHA-256 digest of hashed files of the package |
| 103 | pub fn init(digest: Digest, name: []const u8, ver: []const u8, id: u32, size: u32) Hash { |
| 107 | 104 | assert(name.len <= 32); |
| 108 | 105 | assert(ver.len <= 32); |
| 109 | 106 | var result: Hash = undefined; |
| ... | ... | @@ -112,11 +109,11 @@ pub const Hash = struct { |
| 112 | 109 | buf.appendAssumeCapacity('-'); |
| 113 | 110 | buf.appendSliceAssumeCapacity(ver); |
| 114 | 111 | buf.appendAssumeCapacity('-'); |
| 115 | | var hashplus: [30]u8 = undefined; |
| 116 | | std.mem.writeInt(u16, hashplus[0..2], id, .little); |
| 117 | | std.mem.writeInt(u32, hashplus[2..6], size, .little); |
| 118 | | hashplus[6..].* = digest[0..24].*; |
| 119 | | _ = std.base64.url_safe_no_pad.Encoder.encode(buf.addManyAsArrayAssumeCapacity(40), &hashplus); |
| 112 | var hashplus: [33]u8 = undefined; |
| 113 | std.mem.writeInt(u32, hashplus[0..4], id, .little); |
| 114 | std.mem.writeInt(u32, hashplus[4..8], size, .little); |
| 115 | hashplus[8..].* = digest[0..25].*; |
| 116 | _ = std.base64.url_safe_no_pad.Encoder.encode(buf.addManyAsArrayAssumeCapacity(44), &hashplus); |
| 120 | 117 | @memset(buf.unusedCapacitySlice(), 0); |
| 121 | 118 | return result; |
| 122 | 119 | } |
| ... | ... | @@ -194,8 +191,8 @@ test Hash { |
| 194 | 191 | 0xc7, 0xf5, 0x71, 0xb7, 0xb4, 0xe7, 0x6f, 0x3c, 0xdb, 0x87, 0x7a, 0x7f, 0xdd, 0xf9, 0x77, 0x87, |
| 195 | 192 | 0x9d, 0xd3, 0x86, 0xfa, 0x73, 0x57, 0x9a, 0xf7, 0x9d, 0x1e, 0xdb, 0x8f, 0x3a, 0xd9, 0xbd, 0x9f, |
| 196 | 193 | }; |
| 197 | | const result: Hash = .init(example_digest, "nasm", "2.16.1-2", 0xcafe, 10 * 1024 * 1024); |
| 198 | | try std.testing.expectEqualStrings("nasm-2.16.1-2-_soAAKAAx_Vxt7Tnbzzbh3p_3fl3h53ThvpzV5r3", result.toSlice()); |
| 194 | const result: Hash = .init(example_digest, "nasm", "2.16.1-3", 0xcafebabe, 10 * 1024 * 1024); |
| 195 | try std.testing.expectEqualStrings("nasm-2.16.1-3-vrr-ygAAoADH9XG3tOdvPNuHen_d-XeHndOG-nNXmved", result.toSlice()); |
| 199 | 196 | } |
| 200 | 197 | |
| 201 | 198 | test { |