Commit 24ff8a1a5f
Changed files (1)
src
src/Package.zig
@@ -299,16 +299,37 @@ fn fetchAndUnpack(
// Check if the expected_hash is already present in the global package
// cache, and thereby avoid both fetching and unpacking.
if (expected_hash) |h| cached: {
- if (h.len != 2 * Hash.digest_length) {
+ const hex_multihash_len = 2 * multihash_len;
+ if (h.len >= 2) {
+ const their_multihash_func = std.fmt.parseInt(u8, h[0..2], 16) catch |err| {
+ return reportError(
+ ini,
+ comp_directory,
+ h.ptr,
+ "invalid multihash value: unable to parse hash function: {s}",
+ .{@errorName(err)},
+ );
+ };
+ if (@intToEnum(MultihashFunction, their_multihash_func) != multihash_function) {
+ return reportError(
+ ini,
+ comp_directory,
+ h.ptr,
+ "unsupported hash function: only sha2-256 is supported",
+ .{},
+ );
+ }
+ }
+ if (h.len != hex_multihash_len) {
return reportError(
ini,
comp_directory,
h.ptr,
"wrong hash size. expected: {d}, found: {d}",
- .{ Hash.digest_length, h.len },
+ .{ hex_multihash_len, h.len },
);
}
- const hex_digest = h[0 .. 2 * Hash.digest_length];
+ const hex_digest = h[0..hex_multihash_len];
const pkg_dir_sub_path = "p" ++ s ++ hex_digest;
var pkg_dir = global_cache_directory.handle.openDir(pkg_dir_sub_path, .{}) catch |err| switch (err) {
error.FileNotFound => break :cached,
@@ -397,8 +418,8 @@ fn fetchAndUnpack(
const pkg_dir_sub_path = "p" ++ s ++ hexDigest(actual_hash);
try renameTmpIntoCache(global_cache_directory.handle, tmp_dir_sub_path, pkg_dir_sub_path);
+ const actual_hex = hexDigest(actual_hash);
if (expected_hash) |h| {
- const actual_hex = hexDigest(actual_hash);
if (!mem.eql(u8, h, &actual_hex)) {
return reportError(
ini,
@@ -414,7 +435,7 @@ fn fetchAndUnpack(
comp_directory,
url.ptr,
"url field is missing corresponding hash field: hash={s}",
- .{std.fmt.fmtSliceHexLower(&actual_hash)},
+ .{&actual_hex},
);
}
@@ -592,11 +613,30 @@ test hex64 {
try std.testing.expectEqualStrings("[00efcdab78563412]", s);
}
-fn hexDigest(digest: [Hash.digest_length]u8) [Hash.digest_length * 2]u8 {
- var result: [Hash.digest_length * 2]u8 = undefined;
+const multihash_function: MultihashFunction = switch (Hash) {
+ std.crypto.hash.sha2.Sha256 => .@"sha2-256",
+ else => @compileError("unreachable"),
+};
+comptime {
+ // We avoid unnecessary uleb128 code in hexDigest by asserting here the
+ // values are small enough to be contained in the one-byte encoding.
+ assert(@enumToInt(multihash_function) < 127);
+ assert(Hash.digest_length < 127);
+}
+const multihash_len = 1 + 1 + Hash.digest_length;
+
+fn hexDigest(digest: [Hash.digest_length]u8) [multihash_len * 2]u8 {
+ var result: [multihash_len * 2]u8 = undefined;
+
+ result[0] = hex_charset[@enumToInt(multihash_function) >> 4];
+ result[1] = hex_charset[@enumToInt(multihash_function) & 15];
+
+ result[2] = hex_charset[Hash.digest_length >> 4];
+ result[3] = hex_charset[Hash.digest_length & 15];
+
for (digest) |byte, i| {
- result[i * 2 + 0] = hex_charset[byte >> 4];
- result[i * 2 + 1] = hex_charset[byte & 15];
+ result[4 + i * 2] = hex_charset[byte >> 4];
+ result[5 + i * 2] = hex_charset[byte & 15];
}
return result;
}
@@ -629,3 +669,21 @@ fn renameTmpIntoCache(
break;
}
}
+
+const MultihashFunction = enum(u16) {
+ identity = 0x00,
+ sha1 = 0x11,
+ @"sha2-256" = 0x12,
+ @"sha2-512" = 0x13,
+ @"sha3-512" = 0x14,
+ @"sha3-384" = 0x15,
+ @"sha3-256" = 0x16,
+ @"sha3-224" = 0x17,
+ @"sha2-384" = 0x20,
+ @"sha2-256-trunc254-padded" = 0x1012,
+ @"sha2-224" = 0x1013,
+ @"sha2-512-224" = 0x1014,
+ @"sha2-512-256" = 0x1015,
+ @"blake2b-256" = 0xb220,
+ _,
+};