About SHA-1 Hash
SHA-1 takes an input of any length and produces a fixed 160-bit digest, written as 40 hexadecimal characters. The same input always gives the same digest, a one-character change gives a completely different one, and there is no way to run the function backwards to recover the input.
Internally it processes the message in 512-bit blocks using 32-bit words, after padding the message and appending its bit length. That padding step is why hashing an empty string still produces a full-length digest rather than nothing.
SHA-1 is broken for collision resistance and must not be used for signatures, certificates or deduplicating untrusted content. The SHAttered attack produced a real collision in 2017, and chosen-prefix collisions followed in 2020 at practical cost.
It is still fine as a non-security checksum, inside HMAC (HMAC-SHA1 is not affected by these collision attacks), and for reading legacy systems - Git object IDs, older TLS fingerprints, existing database columns you cannot migrate yet.
Where you will actually meet SHA-1: Git object IDs (still SHA-1 by default, with SHA-256 repositories an opt-in that most tooling does not yet support), older TLS certificate fingerprints, legacy HMAC-SHA1 in AWS Signature v2 and OAuth 1.0a, and the odd database column nobody has migrated. Recognising it is easy - 40 hex characters.
This page runs SHA-1 entirely in your browser through the Web Crypto API - the same implementation your browser uses for TLS. Nothing you paste is uploaded, logged, or leaves the tab, which matters when the thing you are hashing is a real token or customer record.
How to use the SHA-1 Hash
- Paste or type your input into the text box - any text, JSON, a token, or a whole file's contents.
- The 160-bit digest is computed as you type and shown as 40 lowercase hex characters.
- Use the copy button to take the digest, and compare it against the value you are checking against.
- Comparing two digests by eye is error-prone - paste both into the Text Diff tool if they are long, or compare the first and last eight characters at minimum.
Examples
-
Input
legacy-content
SHA-1 Hash in code
The same operation this tool performs, in the languages you are most likely to need it.
const bytes = new TextEncoder().encode("hello world");
const digest = await crypto.subtle.digest("SHA-1", bytes);
const hex = [...new Uint8Array(digest)]
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
console.log(hex); // 40 hex characters
import { createHash } from "node:crypto";
const hex = createHash("sha1").update("hello world").digest("hex");
console.log(hex);
// Large files: stream instead of buffering the whole thing
import { createReadStream } from "node:fs";
import { pipeline } from "node:stream/promises";
const hash = createHash("sha1");
await pipeline(createReadStream("big.tar.gz"), hash);
console.log(hash.digest("hex"));
import hashlib
print(hashlib.sha1(b"hello world").hexdigest())
# Large files: read in chunks so you don't load it all into memory
h = hashlib.sha1()
with open("big.tar.gz", "rb") as f:
for chunk in iter(lambda: f.read(1024 * 1024), b""):
h.update(chunk)
print(h.hexdigest())
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest("hello world".getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : digest) sb.append(String.format("%02x", b));
System.out.println(sb);
package main
import (
"crypto/sha1"
"encoding/hex"
"fmt"
)
func main() {
sum := sha1.Sum([]byte("hello world"))
fmt.Println(hex.EncodeToString(sum[:]))
}
using System.Security.Cryptography;
using System.Text;
byte[] digest = SHA1.HashData(Encoding.UTF8.GetBytes("hello world"));
Console.WriteLine(Convert.ToHexString(digest).ToLowerInvariant());
# macOS / Linux
echo -n "hello world" | shasum -a 1 | cut -d" " -f1
# Note the -n: without it, echo appends a newline and you get a
# different digest than every other example on this page.
When you need this
- Verifying a Git object hash or a legacy artifact checksum.
- Reading a certificate fingerprint from older documentation or tooling.
- Reproducing an OAuth 1.0a or AWS SigV2 signature while maintaining an old integration.
- Checking a value stored in a system that predates SHA-2 adoption.
- Confirming a supposedly SHA-1 field really is 40 hex characters and not something else.
Common problems and what causes them
- Assuming SHA-1 is safe because Git uses it
- Git relies on SHA-1 for object naming but adds a collision-detection layer (sha1dc) that rejects known attack patterns, and SHA-256 repositories exist as an opt-in. That is a mitigation for one specific attack shape, not evidence that SHA-1 is collision-resistant. Do not reason from Git to your own design.
- Using SHA-1 for a content-addressed store of untrusted data
- If users can supply the content, chosen-prefix collisions let two different files share one identifier - so one can be substituted for the other. This is the one place a SHA-1 checksum is actively dangerous rather than merely dated.
- Your digest doesn't match the other system's, for the same input
- Almost always a trailing newline or an encoding difference. `echo "x"` appends \n but `echo -n "x"` does not, and a file saved with CRLF line endings hashes differently from the same file with LF. Hash the exact bytes, not the visually identical text.
- Hex vs Base64 vs raw bytes
- The same 160-bit digest can be printed as 40 hex characters, as Base64, or stored as 20 raw bytes. A mismatch is often just two systems formatting the same digest differently - decode both to bytes before concluding they differ.
- Uppercase vs lowercase hex
- Hex digests are case-insensitive as values but not as strings. `A3F1` and `a3f1` are the same digest and different strings, so a naive `==` comparison fails. Normalise case before comparing.
- Using SHA-1 to hash passwords
- A fast hash is the wrong tool for passwords - commodity hardware computes billions per second, so a leaked table is brute-forced quickly. Use bcrypt, scrypt or Argon2, which are deliberately slow and salted.
- Comparing digests with a non-constant-time comparison
- When you are checking a digest that acts as a secret or a signature, an early-exit string compare leaks how many leading characters matched. Use a constant-time comparison (`crypto.timingSafeEqual`, `hmac.compare_digest`, `MessageDigest.isEqual`).
FAQ
- Is SHA-1 still used anywhere legitimately?
- Yes, in narrow places: Git object IDs (with collision detection bolted on), HMAC-SHA1 in OAuth 1.0a and AWS Signature v2, and reading existing data. HMAC-SHA1 in particular is not broken by the collision attacks, because HMAC does not depend on collision resistance.
- How was SHA-1 actually broken?
- The SHAttered attack in 2017 produced two different PDFs with the same SHA-1 digest, at a cost of roughly 6,500 CPU-years. Chosen-prefix collisions followed in 2020 for around 45,000 USD of cloud compute, which is what made forged certificates practical rather than theoretical.
- How long is a SHA-1 hash?
- Always 160 bits - 40 hexadecimal characters, or 20 bytes raw - no matter whether the input is one character or a gigabyte.
- Can a SHA-1 hash be decrypted or reversed?
- No. Hashing is not encryption; it discards information and has no key and no inverse. What people mean by "reversing" a hash is looking it up in a precomputed table of common inputs, which is why unsalted hashes of predictable values (short passwords, email addresses) are not private.
- Is SHA-1 safe to use in 2026?
- SHA-1 is broken for collision resistance and must not be used for signatures, certificates or deduplicating untrusted content. The SHAttered attack produced a real collision in 2017, and chosen-prefix collisions followed in 2020 at practical cost.
- Why does the same text give a different hash elsewhere?
- Check for a trailing newline, CRLF vs LF line endings, a byte-order mark at the start of the file, or a different character encoding. All of those change the bytes without changing what you see on screen.
- Is this tool sending my input to a server?
- No. The digest is computed in your browser with the Web Crypto API. There is no upload, no request, and no logging - you can confirm it by opening your network tab, or by disconnecting from the network and using the tool offline.
- Should I use SHA-1 or HMAC-SHA-1?
- Use plain SHA-1 when you want an integrity check that anyone can recompute. Use HMAC-SHA-1 when the check has to prove the sender knew a shared secret - webhook signatures, API request signing, tamper-evident tokens. Never hand-roll that as hash(secret + message).
- Should I use SHA-1 for new code?
- No - use SHA-256 or stronger.