SHA1
MySQL
hash storage
database security
data integrity

Storing SHA1 hash values in MySQL

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

A SHA1 hash is 160 bits long, which means it can be stored either as 20 raw bytes or as a 40-character hexadecimal string. In MySQL, both approaches work, but they are not equivalent in storage cost or ergonomics. The best design depends on whether you want compact binary storage or easier human readability. The more important security point is that SHA1 should not be used for password hashing in new systems.

Know the Two Common Storage Forms

SHA1 values are usually represented in one of two ways:

  • raw binary digest, which is 20 bytes
  • hexadecimal text, which is 40 characters

If you compute a SHA1 hash in application code and keep it as hex, a schema like this works:

sql
1CREATE TABLE documents (
2    id BIGINT PRIMARY KEY,
3    sha1_hex CHAR(40) NOT NULL
4);

If you store the raw digest instead, use a binary column:

sql
1CREATE TABLE documents (
2    id BIGINT PRIMARY KEY,
3    sha1_bin BINARY(20) NOT NULL
4);

Binary storage is smaller and usually better for indexing efficiency. Hex storage is easier to inspect manually in SQL queries.

CHAR(40) Versus BINARY(20)

CHAR(40) is simple because the value looks like what most developers expect:

text
2fd4e1c67a2d28fced849ee1bb76e7391b93eb12

But it uses twice as much space as the raw digest because every byte is written as two hex characters.

BINARY(20) is more compact and more natural if you care about storage efficiency or large indexes.

A practical rule is:

  • use CHAR(40) if human readability in SQL tooling matters more
  • use BINARY(20) if compact storage and indexing matter more

Insert SHA1 Values in MySQL

If you want MySQL to compute the SHA1 value and store it as hex text:

sql
INSERT INTO documents (id, sha1_hex)
VALUES (1, SHA1('hello world'));

If you want to store the raw binary digest, convert the hex output using UNHEX:

sql
INSERT INTO documents (id, sha1_bin)
VALUES (1, UNHEX(SHA1('hello world')));

SHA1() returns hex text by default, so UNHEX(...) is the bridge from textual representation to the compact binary form.

Read Binary Hashes Back as Hex

When you store a binary digest, it is often helpful to display it as hex in queries.

sql
SELECT id, HEX(sha1_bin) AS sha1_hex
FROM documents;

This gives you the familiar 40-character representation without giving up compact storage internally.

Indexing and Uniqueness

Hashes are often used for deduplication or integrity checks, so indexes matter.

sql
CREATE UNIQUE INDEX ux_documents_sha1_bin ON documents (sha1_bin);

Or for hex storage:

sql
CREATE UNIQUE INDEX ux_documents_sha1_hex ON documents (sha1_hex);

A unique index is useful if the hash is being used as a content fingerprint and duplicate values should not be inserted.

Do Not Use SHA1 for Passwords

This is the most important caution in the whole topic. SHA1 is no longer appropriate for password hashing. It is too fast and has known cryptographic weaknesses.

If the goal is password storage, use a dedicated password-hashing algorithm such as:

  • bcrypt
  • Argon2
  • PBKDF2

Those algorithms are intentionally slow and designed for credential storage. SHA1 is not.

SHA1 can still appear in non-password contexts such as legacy content fingerprints, file integrity checks, or compatibility with older systems, but even there many teams now prefer SHA-256 or stronger options.

Migration Considerations

If you already have SHA1 stored as CHAR(40) and want to move to BINARY(20), you can convert existing rows:

sql
UPDATE documents
SET sha1_bin = UNHEX(sha1_hex);

If you are migrating to a stronger hash such as SHA-256, remember that the schema needs to change too:

  • SHA1 hex length is 40
  • SHA-256 hex length is 64
  • SHA1 binary length is 20
  • SHA-256 binary length is 32

Do not assume a stronger hash will fit into the old column definition.

Common Pitfalls

A common mistake is storing SHA1 as VARCHAR(40) when the length is fixed. CHAR(40) or BINARY(20) is a better fit.

Another issue is treating SHA1 as acceptable for password storage. It is not. Use a password-hashing algorithm instead.

Developers also sometimes store hex text and then forget they are paying double the storage compared with raw binary.

Finally, be explicit about case handling. Hex strings can appear in upper or lower case; binary storage avoids that inconsistency entirely.

Summary

  • A SHA1 digest is 20 bytes in binary or 40 characters in hexadecimal.
  • Use BINARY(20) for compact storage or CHAR(40) for easier readability.
  • In MySQL, SHA1() returns hex text; UNHEX(SHA1(...)) stores the compact binary form.
  • 'HEX(binary_column) is useful for displaying binary digests as readable text.'
  • Do not use SHA1 for passwords; use a dedicated password-hashing algorithm instead.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.