English

Developer tools · SHA hash calculator

Subresource Integrity: How Browsers Use SHA-384 to Check Scripts

· Background

sha-256 base64 browser-apis security

Integrity attribute showing algorithm prefix, hyphen and base64 digest
Original ToolAcre vector illustration

The integrity attribute lets a browser refuse a CDN script whose bytes have changed. This post explains the attribute's format, why SHA-384 in base64 is the common choice, and what SRI cannot protect against.

The CDN that could serve anything — the supply-chain risk SRI was designed for

A script tag on a web page can carry an integrity attribute: `<script src="https://cdn.example.com/lib.js" integrity="sha384-..."></script>`. The integrity value is a cryptographic digest of the script's bytes. When the browser downloads the script, it computes the digest of the received bytes and compares against the integrity attribute. If they match, the script is loaded. If they do not match, the browser refuses to load it and reports the failure in the console. This protects against a compromised CDN serving modified code, or against a network attacker intercepting and altering the response.

Subresource Integrity (SRI) is a W3C specification that applies to scripts and stylesheets. It is the only cryptographic guarantee a browser can make about the content of a cross-origin resource: the bytes must match the digest, or the resource is rejected. This does not prove who created the resource, only that it has not changed since the digest was computed. For a resource served over HTTPS from a reputable CDN, the digest provides a safeguard against the CDN being compromised or serving stale cached content to you specifically.

The integrity attribute — algorithm prefix, hyphen, base64 digest, and support for multiple hashes

The integrity attribute has a specific format: algorithm-name, hyphen, digest in base64. Example: `integrity="sha384-JZDdQnrrAMe+sxxpn47in+PwhkxrCrt4SNvt+xWqV3zPJUkeFF0Qq/wNtuvNqPP5"`. The algorithm name can be SHA-256, SHA-384 or SHA-512. Base64 is the encoding, not hexadecimal; this is a deliberate choice by the SRI specification. Base64 is more compact than hex (about 33% shorter for the same digest), which matters when embedding in HTML attributes. The hyphen separates algorithm name from digest. Multiple integrity values can be listed, space-separated: if any one of them matches, the resource is accepted.

Why SHA-384? The SRI specification allows SHA-256, SHA-384 and SHA-512. SHA-384 became the community default because it offers a size/security balance. SHA-256 is smaller (32 bytes, 44 characters in base64) but SHA-384 is wider (48 bytes, 64 characters in base64) and did not meaningfully increase the attribute size compared to SHA-256. SHA-512 is available but rarely used because its larger digest did not seem necessary for this use case. The choice of SHA-384 is historical and pragmatic, not a reflection of superior security properties (all three are cryptographically strong for this purpose).

SHA-384 is offered and produces the required base64 material; community preference is not inferred from the tool

Base64 encoding in SRI is standard base64, not base64url. Standard base64 uses + and / characters, which are valid in HTML attributes without percent-encoding, though they have special meanings in URLs and form data. The SRI format is designed for HTML attributes, not URLs, so standard base64 is appropriate. If you are building an integrity value by hand, you compute the SHA-384 digest (a sequence of bytes), then encode those bytes as standard base64, then prepend `sha384-` and paste into the integrity attribute.

The browser performs the same steps in reverse: extract the base64 from the integrity attribute, decode to bytes to recover the digest, compute SHA-384 of the downloaded script bytes and compare the two digest values. They must match exactly; a single-bit difference in the digest causes rejection. There is no fuzzy matching or partial credit: integrity is binary.

Cross-origin SRI behavior requires browser documentation beyond this hash calculator

SRI requires CORS on cross-origin responses. If you load a script from a different origin, the server must respond with `Access-Control-Allow-Origin: *` or a specific origin header that includes yours. Without CORS headers, the browser cannot check the SRI, because without CORS it cannot confirm that the response body matches what the server intended to send. CORS headers are the server's statement that this response is safe to check; SRI is your check that the bytes are correct. Together, they form a supply-chain commitment: the server allows you to verify the content, and you do.

If a cross-origin script lacks CORS headers and has an integrity attribute, the browser will download it (if scripts from that origin are allowed by the site's CSP), but it will not verify the integrity. The script will be loaded as if the integrity attribute were absent. This is not a failure of SRI; it is a security boundary: you cannot verify a response you cannot read.

What happens on mismatch — the browser blocks the resource and reports in the console

When the browser detects an integrity mismatch, it refuses to execute the script and logs a message in the browser console. The message typically names the URL, the expected hash and the computed hash. The failure is atomic: either the resource is loaded as-is or it is rejected entirely. There is no partial loading or fallback. If a website relied on that script and it is rejected, the site may break. This is intentional: delivering wrong code is worse than delivering no code, and silent failures enable attacks to persist indefinitely.

Testing an SRI setup is straightforward: open the browser console, load the page and look for messages about integrity mismatches. If you see a mismatch, compare the computed hash shown in the console with the one in your integrity attribute. If they do not match, recompute: the script may have been updated and you need a new digest.

Worked example — computing a digest for a script and formatting it into an integrity value, including the base64 step

Computing an SRI digest manually requires only the script bytes and a hash tool. Download the script, paste it into the ToolAcre SHA hash calculator, select SHA-384, copy the base64 output (not the hex), prepend `sha384-` and paste into the integrity attribute. If the script is large, using curl or wget to save it to a file and then reading the file is faster than pasting. For inline scripts (in a `<script>` tag in the HTML rather than from a URL), SRI is not applicable; inline scripts are always trusted by definition. SRI is for external resources.

A worked example: suppose you want to load jQuery from a CDN with SRI. Find the script URL, download it (or use curl to fetch it), paste the bytes into the calculator or use `sha384sum` on the command line, get the SHA-384 digest as base64, and format as `sha384-[base64-digest]`. Paste into the script tag's integrity attribute. Load the page and verify no console errors appear.

What this does not cover — scripts that change intentionally, and sites like ToolAcre that load no external scripts at all and so have nothing to pin

SRI does not protect against all supply-chain attacks. It protects against bytes changing after the digest is computed, but not against the digest being computed from compromised code to begin with. If a CDN is compromised before you compute the digest, SRI cannot help. The digest is only as trustworthy as the source from which you computed it. For maximum assurance, compute digests from the original source (the library's GitHub releases, for example) and use those digests when loading from a CDN. The digest becomes a commitment from the maintainer through the release process.

SRI also does not protect against a compromised network at the moment you compute the digest, or against a compromised development machine. It protects only against changes to the script between the time the digest is created and the time the browser loads the script. For ongoing assurance, some deployments use release signing in addition to SRI: the release is signed by a maintainer's key, you verify the signature, compute the digest from the verified bytes and use that in SRI.

This article does not assert ToolAcre’s site-wide external-script inventory from hash sources

The ToolAcre SHA hash calculator emits the digest in standard base64 directly (as `base64` output from `toBase64()` function). To convert to SRI format, prepend the algorithm name and a hyphen: `sha256-`, `sha384-` or `sha512-`. The calculator does not apply that prefix automatically because hashes appear in many contexts (git, Docker, npm, URLs) where the algorithm name is separate or encoded differently. The boundary is clear: the calculator hashes UTF-8 text that you paste, not files or binary keys. It outputs both hex and base64. You choose which to use based on your context. For SRI, base64 is required by the specification. For git and other tools, hex is conventional. For npm and Go, base64 is used. The encoding choice is yours; the digest bytes are the same.

SRI remains one of the few cryptographic checks a browser can perform client-side without a centralized authority. Computing digests yourself with a trusted tool like ToolAcre's SHA calculator and verifying them against loaded resources is an accessible way to harden a website against certain supply-chain attacks. The protection is only as good as the digest; recompute after every update to the external resource and test that the browser loads the script without rejecting it.