SRI Hash Generator
Hash a script or stylesheet and get the integrity= attribute the browser checks — computed on this device, never uploaded.
—Hash expressions
- —
- —
This address is printed into the tag as text. It is never requested, resolved or read.
anonymousA subresource on another origin must be served with CORS headers and carry crossorigin, or the browser cannot read the response to check the hash and the load fails.
<script src="" integrity="" crossorigin="anonymous"></script>Ctrl+↵ runs this tool · Ctrl+⇧+C copies the integrity value · This tool never fetches a URL: it hashes what you paste or drop. Generic file checksums live on the File Checksum Verifier.
Do it offline:$ printf "%s" "alert('Hello, world.');" | openssl dgst -sha384 -binary | openssl base64 -A
How to use it
- Give it the exact bytes you deploy: a minified bundle and its source are two files with two hashes, so hash the built artefact.
- Keep sha384 unless something asks for another width — it is the algorithm the specification uses in its own worked example.
- Copy the integrity= value, or take the finished script or link tag with your address filled in. That address is escaped into the markup, and nothing else happens to it.
- Keep crossorigin="anonymous" when the subresource sits on another origin, and hash again on every redeploy — a stale attribute blocks the load.
Subresource Integrity pins a tag to one exact byte sequence: the browser hashes what it downloaded, compares that against the integrity attribute you published, and refuses anything else. Paste the file you ship or drop it here, keep sha384, and take the value with the tag already built around it. Hashing happens in this page; no address is requested.
Examples
alert('Hello, world.');sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xOThe example the specification itself works through, so it can be checked against a source outside this page. Before the hyphen, the algorithm; after it, the digest in standard base64 with padding.
sha384 + sha512 · alert('Hello, world.');sha512-Q2bFTOhEALkN8hOms2FKTDLy7eugP2zFZ1T8LCvX42Fp3WoNr3bjZSAHeOsHrbV1Fu9/A0EzCinRE7Af1ofPrw== sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xOTwo expressions, one space between them, emitted strongest first whichever box was ticked first. A reader that understands both uses the sha512 one alone.
Verify · alert('Hello, world.'); · sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xOmatch · sha384 · expected and computed agree: H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xOCheck mode answers the question a blocked tag raises: is the attribute wrong, or is this not the file it was written for. Both digests are shown side by side, so one differing character is visible.
Verify · md5-XUFAKrxLKna5cZ2REBfFkg== sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=match · sha256 · 1 of 2 tokens dropped: md5An unreadable token is dropped, never fatal: md5 is not one of the three defined algorithms, so the sha256 expression decides alone. The drop is still reported — half an attribute doing nothing is worth knowing.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
A trailing newline is a different file
The commonest reason a correct-looking attribute blocks a working script: the copy that was hashed ended with a line break and the deployed one did not. CRLF against LF does the same, as does a byte-order mark. Nothing here trims or normalises — a forgiving hash is one the browser disagrees with.
Text is hashed as UTF-8 bytes
The paste pane encodes what you type as UTF-8 before hashing — what a server sends and a browser reads back. An accented character or an emoji contributes several bytes, and another encoding of the same characters gives another digest.
More expressions are not more chances
Listing sha256 beside sha512 gives a file no second chance: a reader keeps only the expressions written with the strongest algorithm it understands. A stale sha512 beside a fresh sha256 fails; the reverse pairing passes.
Files up to 32 MB, hashed in one pass
A dropped file is read into memory in a worker and digested once, which puts a printed ceiling of 33,554,432 bytes on it. The cap is stated beside the control, and a file over it is refused rather than truncated.
link here means rel="stylesheet"
The two tags on offer are the two this page vouches for: a script element, and a link element carrying a stylesheet relationship. Other relations, such as a module preload, have their own rules, so no markup is guessed for them.
Common errors
Token 1 of 2 (`sha384-abc`): the digest is 3 base64 characters, but a sha384 digest is exactly 64, so this digest can never match the content. A browser does NOT ignore the token — the algorithm is one it knows, so the token still counts, and if it is the strongest one present the check fails and the subresource is blocked. Re-copy the digest from the tool that produced it.- The algorithm name fixes the digest length exactly, so width is checked first. That name alone decides whether a browser keeps the token, so a truncated digest blocks the tag.
Token 1 of 2 (`md5-XUFAKrxLKna5cZ2REBfFkg==`): `md5` is not an SRI hash algorithm, so a browser ignores it. SRI defines sha256, sha384 and sha512 only, written as `algorithm-base64`.- Usually a digest lifted from a download page, where md5 and sha1 are still published. It is dropped and the rest still decide, which is what a browser does.
No usable hash expression is left in this integrity= value (all 2 tokens dropped) — a browser then applies no integrity check at all and loads the subresource unchecked. Fix or replace the tokens listed below.- The failure worth being loud about: an attribute nothing can read blocks nothing, leaving the tag unprotected while looking protected.
That file is 33,554,433 bytes (32.0 MB) — this tool hashes files up to 33,554,432 bytes (32 MB) in one pass. Nothing was hashed.- One byte over the printed ceiling, refused with both numbers so the gap is arithmetic.
FAQ
Does the file I drop here get uploaded anywhere?
No. It is read by this page, hashed in a worker on your machine and then dropped; no request in this code could send it, and its bytes never enter a permalink. To check a download against a published checksum, use /file-checksum-verifier instead.
Why does the tag need crossorigin="anonymous"?
Because a browser will not hash a response it was not allowed to read. A subresource from another origin arrives opaque unless the request was made in CORS mode and the server allowed it, and an opaque response fails closed — the tag is blocked. Same-origin subresources need no such attribute.
Can I paste a CDN address and have it hashed for me?
Not here, and the reason is worth stating rather than hiding: this site is static, so CORS blocks it from reading an arbitrary asset, and doing it server-side would mean running a proxy — a backend, which is not added quietly. Download the file and drop it in.
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Runs the mode you are in — generate, or check.
- ⌘/Ctrl + Shift + C
- Copies the integrity= value, whatever is selected on the page.