authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-01 20:02:35-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-01 20:02:35-07:00
log24ff8a1a5fc00c405e5506251f11d23653d6c8b5
tree790bce1d2fba08d991aaea9b575ba7550627011b
parentea6e0e33a7630fb78550a5567a98420c3377350c

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 files changed, 67 insertions(+), 9 deletions(-)

src/Package.zig+67-9
......@@ -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
595fn hexDigest(digest: [Hash.digest_length]u8) [Hash.digest_length * 2]u8 {
596 var result: [Hash.digest_length * 2]u8 = undefined;
616const multihash_function: MultihashFunction = switch (Hash) {
617 std.crypto.hash.sha2.Sha256 => .@"sha2-256",
618 else => @compileError("unreachable"),
619};
620comptime {
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}
626const multihash_len = 1 + 1 + Hash.digest_length;
627
628fn 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
673const 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};