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