Skip to content

Compute sha256, sha1 and sha512-SRI digests through utils::digest instead of inline copies #706

Description

[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: discussion #560 register.

Kind: refactor (mechanical, no behavior change). Source: review 4.4 and 7.3; register C17.

Problem (main @ 045d7ec)

utils::digest holds the shape validators. Its sha256_hex(&str) -> Option<String> and sha1_hex(&str) check and lowercase a hex string. The computations carrying the same names live elsewhere, as private copies:

  • sha256_hex(bytes) -> String exists three times:

    vendor::verify::file_sha256_hex (L777) and ServiceFetch::sha256_hex are two more.

  • sha1_hex(bytes) exists twice: vendor/jvm/mod.rs and vendor/maven_repo.rs.``

  • The sha512 SRI is formatted three times. There is a public redirect::vlt_preflight::sha512_sri,`` yet vendor/npm_pack.rs and `vendor/bun_lock.rs` inline their own. `vendor` would also have to import from `patch::redirect` to reuse it, which goes against the layering.

  • About 20 production sites inline hex::encode(Sha256::digest(..)), for example in update/download.rs, policy/mod.rs, vendor/{verify,redownload,bun_workspace,bun_binary,state,nuget_feed,maven_repo,pypi}.rs and redirect/upstream/client.rs. Three more inline hex::encode(Sha1::digest(..)).

  • The 64-hex validator also exists three times: apply::is_valid_blob_hash, api::client::is_valid_sha256_hex and utils::digest::is_hex(s, 64).

No copy has drifted in its output yet; all of them produce lowercase hex. The hazard is the name clash: sha256_hex means validate in utils::digest and compute in three other modules, so an import can silently pick the wrong one.

Impact

This is maintenance cost and a misuse hazard, not a live bug. It is the prerequisite for one hash-comparison rule; the case-policy bug is filed separately.

Proposed change

  • Add the compute helpers to utils::digest: sha256_hex_of(&[u8]), sha1_hex_of(&[u8]) and sha512_sri_of(&[u8]), plus an async file_sha256_hex moved from vendor::verify. Rename the validators to parse_sha256_hex/parse_sha1_hex so no name means both things.
  • Fold apply::is_valid_blob_hash and client::is_valid_sha256_hex into digest::is_hex(s, 64), keeping is_valid_blob_hash as a thin re-export if the CLI uses it.
  • Delete: the five private compute copies, vlt_preflight::sha512_sri (callers move to digest), the inline SRI blocks in npm_pack and bun_lock, and the ~23 inline hex::encode(ShaN::digest) expressions in production code.

Size and scope

About 25 files, around 120 lines removed and 40 added, all mechanical. Out of scope:

  • changing any comparison's case sensitivity (see the hash-case bug);
  • the git-sha256 blob hash in hash/git_sha256.rs, a different algorithm;
  • test and bench fixture copies. A follow-up can switch tests over once the helpers exist.

Acceptance criteria

  • rg 'hex::encode\((sha2::|sha1::)?Sha(1|256)::digest' crates/socket-patch-core/src crates/socket-patch-cli/src matches only utils/digest.rs and test modules.
  • rg 'fn sha(1|256)_hex|fn sha512_sri' matches only utils/digest.rs in production code.
  • A unit test in utils/digest.rs pins known vectors ("", "abc") for all three compute helpers.
  • cargo test -p socket-patch-core and -p socket-patch-cli stay green.

Dependencies

None. This unblocks the hash-comparison bug fix (one digest::hex_eq).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:triagedarch-auditFiled by a scheduled architecture audit routine (see the architecture review discussion)priority:p3refactorStructural change: duplicated code or logic, missing abstraction, layering, dead code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions