Skip to content

Commit 24ff8a1

Browse files
committed
zig build: use multihash for the hash field
https://multiformats.io/multihash/ Still, only SHA2-256 is supported. This is only intended to future-proof the hash field of the manifest. closes #14284
1 parent ea6e0e3 commit 24ff8a1

File tree

1 file changed

+67
-9
lines changed

1 file changed

+67
-9
lines changed

src/Package.zig

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -299,16 +299,37 @@ fn fetchAndUnpack(
299299
// Check if the expected_hash is already present in the global package
300300
// cache, and thereby avoid both fetching and unpacking.
301301
if (expected_hash) |h| cached: {
302-
if (h.len != 2 * Hash.digest_length) {
302+
const hex_multihash_len = 2 * multihash_len;
303+
if (h.len >= 2) {
304+
const their_multihash_func = std.fmt.parseInt(u8, h[0..2], 16) catch |err| {
305+
return reportError(
306+
ini,
307+
comp_directory,
308+
h.ptr,
309+
"invalid multihash value: unable to parse hash function: {s}",
310+
.{@errorName(err)},
311+
);
312+
};
313+
if (@intToEnum(MultihashFunction, their_multihash_func) != multihash_function) {
314+
return reportError(
315+
ini,
316+
comp_directory,
317+
h.ptr,
318+
"unsupported hash function: only sha2-256 is supported",
319+
.{},
320+
);
321+
}
322+
}
323+
if (h.len != hex_multihash_len) {
303324
return reportError(
304325
ini,
305326
comp_directory,
306327
h.ptr,
307328
"wrong hash size. expected: {d}, found: {d}",
308-
.{ Hash.digest_length, h.len },
329+
.{ hex_multihash_len, h.len },
309330
);
310331
}
311-
const hex_digest = h[0 .. 2 * Hash.digest_length];
332+
const hex_digest = h[0..hex_multihash_len];
312333
const pkg_dir_sub_path = "p" ++ s ++ hex_digest;
313334
var pkg_dir = global_cache_directory.handle.openDir(pkg_dir_sub_path, .{}) catch |err| switch (err) {
314335
error.FileNotFound => break :cached,
@@ -397,8 +418,8 @@ fn fetchAndUnpack(
397418
const pkg_dir_sub_path = "p" ++ s ++ hexDigest(actual_hash);
398419
try renameTmpIntoCache(global_cache_directory.handle, tmp_dir_sub_path, pkg_dir_sub_path);
399420

421+
const actual_hex = hexDigest(actual_hash);
400422
if (expected_hash) |h| {
401-
const actual_hex = hexDigest(actual_hash);
402423
if (!mem.eql(u8, h, &actual_hex)) {
403424
return reportError(
404425
ini,
@@ -414,7 +435,7 @@ fn fetchAndUnpack(
414435
comp_directory,
415436
url.ptr,
416437
"url field is missing corresponding hash field: hash={s}",
417-
.{std.fmt.fmtSliceHexLower(&actual_hash)},
438+
.{&actual_hex},
418439
);
419440
}
420441

@@ -592,11 +613,30 @@ test hex64 {
592613
try std.testing.expectEqualStrings("[00efcdab78563412]", s);
593614
}
594615

595-
fn hexDigest(digest: [Hash.digest_length]u8) [Hash.digest_length * 2]u8 {
596-
var result: [Hash.digest_length * 2]u8 = undefined;
616+
const multihash_function: MultihashFunction = switch (Hash) {
617+
std.crypto.hash.sha2.Sha256 => .@"sha2-256",
618+
else => @compileError("unreachable"),
619+
};
620+
comptime {
621+
// We avoid unnecessary uleb128 code in hexDigest by asserting here the
622+
// values are small enough to be contained in the one-byte encoding.
623+
assert(@enumToInt(multihash_function) < 127);
624+
assert(Hash.digest_length < 127);
625+
}
626+
const multihash_len = 1 + 1 + Hash.digest_length;
627+
628+
fn hexDigest(digest: [Hash.digest_length]u8) [multihash_len * 2]u8 {
629+
var result: [multihash_len * 2]u8 = undefined;
630+
631+
result[0] = hex_charset[@enumToInt(multihash_function) >> 4];
632+
result[1] = hex_charset[@enumToInt(multihash_function) & 15];
633+
634+
result[2] = hex_charset[Hash.digest_length >> 4];
635+
result[3] = hex_charset[Hash.digest_length & 15];
636+
597637
for (digest) |byte, i| {
598-
result[i * 2 + 0] = hex_charset[byte >> 4];
599-
result[i * 2 + 1] = hex_charset[byte & 15];
638+
result[4 + i * 2] = hex_charset[byte >> 4];
639+
result[5 + i * 2] = hex_charset[byte & 15];
600640
}
601641
return result;
602642
}
@@ -629,3 +669,21 @@ fn renameTmpIntoCache(
629669
break;
630670
}
631671
}
672+
673+
const MultihashFunction = enum(u16) {
674+
identity = 0x00,
675+
sha1 = 0x11,
676+
@"sha2-256" = 0x12,
677+
@"sha2-512" = 0x13,
678+
@"sha3-512" = 0x14,
679+
@"sha3-384" = 0x15,
680+
@"sha3-256" = 0x16,
681+
@"sha3-224" = 0x17,
682+
@"sha2-384" = 0x20,
683+
@"sha2-256-trunc254-padded" = 0x1012,
684+
@"sha2-224" = 0x1013,
685+
@"sha2-512-224" = 0x1014,
686+
@"sha2-512-256" = 0x1015,
687+
@"blake2b-256" = 0xb220,
688+
_,
689+
};

0 commit comments

Comments
 (0)