SHA-256 vs SHA-384 vs SHA-512 for SRI
Permalink to "SHA-256 vs SHA-384 vs SHA-512 for SRI"Part of Understanding Cryptographic Hash Algorithms for SRI, this page is a decision guide: it helps you pick which of the three SRI-supported algorithms to standardize on, based on collision resistance, token length, compliance, and performance rather than on how to run the hashing commands.
Quick Reference
Permalink to "Quick Reference"| Property | SHA-256 | SHA-384 | SHA-512 |
|---|---|---|---|
| Algorithm identifier | sha256 |
sha384 |
sha512 |
| Digest size | 256 bits | 384 bits | 512 bits |
| Collision resistance | 128-bit | 192-bit | 256-bit |
| Base64 token length | 44 chars | 64 chars | 88 chars |
| Underlying word size | 32-bit | 64-bit | 64-bit |
| NIST SP 800-131A | Approved | Approved | Approved |
| PCI DSS v4.0.1 | Acceptable | Recommended | Acceptable |
| Relative performance (64-bit CPU) | Baseline | ~Same as SHA-512 | Fast |
| Browser support | All engines | All engines | All engines |
| When to choose | Legacy or size-constrained | Default for production | High-assurance / payment pages |
Standardize on SHA-384. Reach for SHA-512 only when a policy mandates the maximum digest, and drop to SHA-256 only when a legacy system cannot store the longer token.
How the three algorithms actually differ
Permalink to "How the three algorithms actually differ"All three are members of the SHA-2 family defined in FIPS 180-4, and every current browser engine accepts all three in an integrity attribute. The security-relevant number is collision resistance, which is half the digest size: 128-bit for SHA-256, 192-bit for SHA-384, 256-bit for SHA-512. Even the weakest of these is astronomically beyond any collision attack demonstrated against a web asset, so for SRI the choice is dominated by two practical factors — token length and CPU cost — rather than by a real security gap.
The counter-intuitive detail is that SHA-384 is not slower than SHA-256. SHA-384 is a truncated variant of SHA-512, and both operate on 64-bit words, so on any modern 64-bit CPU they run at essentially the same speed — often faster than the 32-bit-word SHA-256. That is why the W3C recommends SHA-384 as the SRI baseline: you get 192-bit resistance and a shorter token than SHA-512 at no performance penalty. The step-by-step commands for producing these tokens live in How to Calculate SHA-256 vs SHA-384 for SRI; this page is about which one to commit to.
Canonical Comparison
Permalink to "Canonical Comparison"To make an evidence-based choice, generate all three tokens for the exact bytes you will ship and compare them side by side. SHA-384 is the token you place in the tag; the other two are for the decision record. The mechanics of the digest commands themselves — binary mode, flag order, and the shasum equivalents — are covered in Generating SRI Hashes with OpenSSL and shasum.
# Produce all three SRI tokens for the served artifact
for algo in sha256 sha384 sha512; do
printf '%s-' "$algo"
openssl dgst -"$algo" -binary lib.min.js | openssl base64 -A
echo
done
Expected output — note how the token grows with the digest size:
sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC
sha512-z4PhNX7vuL3xVChQ1m2AB9Yg5AULVxXcg/SpIdNs6c5H0NE8XYXysP+DGNKHfuwvY7kxvUdBeoGlODJ6+SfaPg==
Every token has the same two-part shape: the algorithm name, a single hyphen, then the raw digest bytes in standard base64. Nothing about the encoding changes between algorithms — only the number of digest bytes does, and that is what drives the character count you see above. SHA-256 emits 32 bytes and lands on a 44-character token with one = of padding, SHA-384 emits 48 bytes and divides evenly into 64 characters with no padding at all, and SHA-512 emits 64 bytes and needs == to reach 88 characters.
The SHA-384 token is the one to deploy by default:
<script
src="https://cdn.example.com/lib.min.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>
Variant Examples
Permalink to "Variant Examples"Multi-algorithm attribute for a rolling upgrade
Permalink to "Multi-algorithm attribute for a rolling upgrade"If you are migrating an existing SHA-256 deployment to SHA-384, list both tokens. The browser evaluates only the strongest algorithm it supports and ignores the weaker one — this is a transition aid, not a requirement that both match:
<script
src="https://cdn.example.com/lib.min.js"
integrity="sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU= sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>
Choosing per compliance regime
Permalink to "Choosing per compliance regime"Match the algorithm to the strictest control you must satisfy. All three are NIST SP 800-131A approved, so the decision is about internal policy and payment-page scope:
General web assets ............... SHA-384 (W3C recommended default)
PCI DSS v4.0.1 payment pages ..... SHA-384 minimum; SHA-512 if policy mandates max digest
Legacy tooling / tight budgets ... SHA-256 (shortest token, still approved)
FIPS high-assurance systems ...... SHA-512 (256-bit resistance, longest token)
Reduced to a decision, only two questions ever change the answer: whether something downstream cannot store a 64-character token, and whether a written policy demands the largest available digest. If neither is true — which is the common case — SHA-384 wins by default.
Enforcing a single algorithm in the build
Permalink to "Enforcing a single algorithm in the build"Pin your build tooling to one algorithm so tokens never drift between assets. For example, with the Webpack plugin:
// webpack.config.js — emit only sha384 tokens
import { SubresourceIntegrityPlugin } from 'webpack-subresource-integrity';
export default {
output: { crossOriginLoading: 'anonymous' },
plugins: [
new SubresourceIntegrityPlugin({ hashFuncNames: ['sha384'] }),
],
};
Gotchas and Edge Cases
Permalink to "Gotchas and Edge Cases"-
A longer hash is not meaningfully “more secure” for SRI. The jump from SHA-256’s 128-bit to SHA-512’s 256-bit collision resistance has no practical bearing on web-asset tampering, which relies on a preimage the attacker cannot compute at any of these sizes. Choose on token length and compliance, not on a false sense that bigger is safer.
-
SHA-224 and SHA-1 are not valid SRI algorithms. Only
sha256,sha384, andsha512are accepted. A token prefixed with anything else — includingsha1— is treated as an unrecognized digest and the browser reports that it could not find a valid digest, blocking the resource. -
Always add
crossorigin="anonymous"regardless of algorithm. The algorithm choice is irrelevant if the attribute is missing: without it the browser issues a no-CORS request, receives an opaque response it cannot read, and blocks the resource before any hash is compared. This omission is the most common SRI failure and is unrelated to which SHA variant you picked; How CORS and crossorigin Affect SRI covers the request modes and response headers involved. -
Do not mix algorithms across a single asset’s history expecting AND semantics. Multiple space-separated tokens are OR-with-strongest-wins, never AND. Listing
sha256-…andsha384-…does not force the browser to verify both. -
Token length changes your CSP hash source too. If you also pin the script in a
Content-Security-Policyscript-srchash source, that hash must use the same algorithm and value; switching from SHA-256 to SHA-384 means updating both theintegrityattribute and the CSP source.
Verification Steps
Permalink to "Verification Steps"1. Confirm the deployed token uses your chosen algorithm
Permalink to "1. Confirm the deployed token uses your chosen algorithm"grep -oE 'integrity="sha(256|384|512)-[^"]+"' dist/index.html | sort -u
Expected output when standardized on SHA-384 (values differ per asset):
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
Any sha256- or sha512- line here flags an asset that drifted from your standard. Turning that grep into a build-breaking assertion is the subject of Failing CI on SRI Hash Drift, which is the only reliable way to stop a stray algorithm from reaching production.
2. Re-derive the token from the served bytes
Permalink to "2. Re-derive the token from the served bytes"curl -sL https://cdn.example.com/lib.min.js | openssl dgst -sha384 -binary | openssl base64 -A
The output must match the sha384- token in your HTML character-for-character.
3. Confirm clean validation in the browser
Permalink to "3. Confirm clean validation in the browser"Load the page with DevTools open. A mismatched or unsupported algorithm produces this exact console error:
Failed to find a valid digest in the 'integrity' attribute for resource
'https://cdn.example.com/lib.min.js' with computed SHA-384 integrity
'sha384-…'. The resource has been blocked.
No message and a 200 OK in the Network tab confirms the algorithm and token are correct.
Frequently Asked Questions
Permalink to "Frequently Asked Questions"Is SHA-512 more secure than SHA-384 for SRI?
SHA-512 offers 256-bit collision resistance versus 192-bit for SHA-384. Both are far beyond any feasible collision attack for web assets, so the practical security difference is negligible. SHA-512 mainly adds token length (88 vs 64 base64 characters). SHA-384 is a truncated SHA-512 computed at the same speed, which is why it is the recommended default.
Why is SHA-384 the default instead of SHA-256?
SHA-384 provides 192-bit collision resistance against SHA-256’s 128-bit, is the W3C-recommended algorithm for SRI, and satisfies PCI DSS v4.0.1 without the longest token length. On 64-bit CPUs it is also frequently faster than SHA-256 because the SHA-512 family uses 64-bit words.
Can I combine SHA-256 and SHA-384 in one integrity attribute?
Yes. Space-separate the tokens: integrity=“sha256-… sha384-…”. The browser evaluates only the strongest algorithm it supports from the list and ignores the rest. This is a migration aid, not a way to require both digests to match.
Does a longer hash meaningfully slow page load?
No. The difference between a SHA-256 and a SHA-512 token is roughly 44 bytes of uncompressed HTML per tag, which gzip collapses to almost nothing. Hash computation happens once per resource on already-downloaded bytes and is imperceptible next to network latency.
Related
Permalink to "Related"- How to Calculate SHA-256 vs SHA-384 for SRI — the step-by-step commands for generating each token via CLI, Node.js, Python, and build tooling
- Understanding Cryptographic Hash Algorithms for SRI — parent page covering the mathematical foundations and NIST compliance mapping for SRI hashing
- Base64 Encoding Rules for SRI Hashes — why each algorithm lands on 44, 64, or 88 characters, and which encoding variants a browser will reject
- Browser Enforcement & Security Boundaries — how the browser computes and compares the digest you chose, including opaque-response handling