Hashing, Salting, and Password Storage on Linux.
Every time you check your email, connect to a server through SSH, access your banking application, or make an online purchase, you are asked to prove your identity with a password. That small string of characters is often the first barrier protecting your digital identity.
But have you ever wondered:
- What actually happens when you create a password?
- How does a system verify your password without storing it?
- Where are Linux passwords stored?
- Why do companies store password hashes instead of the actual password?
- What happens if a database containing millions of passwords is stolen?
The answer begins with cryptographic hashing.
What Happens When You Create a Password?
A common misconception is that websites store your actual password in their database. They shouldn’t.
If a company were to store passwords in plain text and its database were compromised, every user’s password would be instantly exposed, allowing attackers to access not only that service but potentially any other accounts where those passwords were reused.
Instead, modern authentication systems never store your password itself. When you create a password, it is passed through a one-way mathematical function known as a cryptographic hash function. The resulting value—called a password hash—is what’s stored in the database. During login, the password you enter is hashed again and compared to the stored hash. If the hashes match, you’re authenticated—without the system ever needing to know or store your original password.
For example:
Password:
SuperSecurePassword123
↓
Hash Function
↓
8c1a8f6e8c7d1e...The server stores the generated hash, not your original password.
The resulting value—called a password hash—is what’s stored in the database. During login, the password you enter is hashed again and compared to the stored hash. If the hashes match, you’re authenticated—without the system ever needing to know or store your original password.
What Is Hashing?
A cryptographic hash function is a mathematical algorithm that takes an input (or message) of any size and produces a fixed-length output known as a hash value, message digest, or simply a hash.
Although the hash is fundamentally a sequence of binary bits, it is almost always represented in hexadecimal (base-16) notation. Hexadecimal uses the digits 0–9 and the letters a–f, providing a compact and human-readable way to display binary data. For example, a 256-bit hash is typically shown as a 64-character hexadecimal string, while a 512-bit hash is displayed as a 128-character hexadecimal string.
A hash function has several important properties:
1. Fixed Output Length
Regardless of the input size, the output length remains the same.
Example:
$ echo -n "hello" | sha512sum
or
$ echo -n "hello" | shasum -a 512
=
9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043 -A single character or an entire book will always produce a 512-bit output; in this case, 128 characters, no matter what.
Below is what the above command does:
echo -n "hello"
- echo prints the text hello.
- The
-nflag tells echo not to append a newline\nat the end. - Output:
hello(with no trailing newline)
|(pipe)- The pipe takes the output from
echoand sends it as the input to the next command.
- The pipe takes the output from
sha512sum- Reads the input (
hello) from standard input. - Computes its SHA-512 cryptographic hash.
- Outputs a 512-bit digest (128 hexadecimal characters), followed by a dash (
-) indicating the input came from standard input.
- Reads the input (
Why use -n ?
Without -n:
$ echo "hello" | sha512sumthe input is actually:
hello\nThat newline becomes part of the data being hashed, producing a completely different hash.
Compare:
$ echo -n "hello" | sha512sum # Hashes: hello
$ echo "hello" | sha512sum # Hashes: hello\n2. One-Way Function
Hashing is designed to be irreversible.
You can calculate:
Password → Hashbut you cannot realistically calculate:
Hash → Original PasswordThis is why hashes are useful for password storage.
3. Avalanche Effect
A strong hash function produces a completely different output when even one small piece of data changes.
Example:
$ echo -n "snubmonkey" | sha512sum
or
$ echo -n "snubmonkey" | shasum -a 512
=
1f99b23951f451867ef5a85cace49d38225a0d2918708baa565dca7fbf4de593cae9834510844f046efba4b57d78239c246d557d880601ed10fa5589fd96943e -Changing only capitalization:
$ echo -n "Snubmonkey" | sha512sum
or
$ echo -n "Snubmonkey" | shasum -a 512
=
dfdd2c9825c092184a4d8dff3a790067d7c6841b1cef1450b91336ed57c545f6ad14142890296ca572d580e736002a8688d23227b3fabe2f0710dae88c3e69b6 -A tiny change creates a completely different hash.
4. Collision Resistance
A collision occurs when two different inputs produce the same hash.
Example:
Password A → abc123hash
Password B → abc123hashA secure cryptographic hash function makes this extremely unlikely.
Hashing vs Encryption
These terms are often confused.
Encryption
Encryption is designed to be reversible.
Example:
Plain Text
↓
Encryption Key
↓
Encrypted Data
↓
Decryption Key
↓
Original DataUsed for:
- HTTPS
- VPN tunnels
- encrypted disks
- secure messaging
Hashing
Hashing is designed to be one-way.
Example:
Password
↓
Hash Function
↓
HashUsed for:
- Password storage
- File integrity checking
- Digital signatures
A password should be hashed, not encrypted.
Why Do We Hash Passwords?
Hashing provides several security benefits.
Password Protection
A database should contain:
Username:
me
Password:
$6$n4wLdmr59ptB8zWG$4.YWKc2kv...Not:
Username:
me
Password:
MySecretPassword123If attackers steal the database, they do not immediately obtain everyone’s passwords.
File Integrity Verification
One of the most important uses of cryptographic hashes is verifying file integrity—ensuring that a file has not been modified, corrupted, or tampered with.
Suppose you download an Ubuntu ISO image.
The Ubuntu website publishes the official SHA-256 hash:
Example:
Suppose you download an Ubuntu ISO image.
The Ubuntu website publishes the official SHA-256 hash:
Before download:
8a4d7e91.... (official hash)After downloading the file, you calculate its hash:
sha256sum ubuntu-24.04.isoOutput:
b45165... ubuntu-24.04.iso- Hashes match: The file is identical to the original.
- Hashes differ: The file has changed—it may be corrupted during download, damaged on disk, or maliciously modified.
Why is this important?
File integrity verification helps detect:
- Corrupted downloads caused by interrupted or faulty network transfers.
- Disk corruption from failing storage devices or filesystem errors.
- Accidental modifications made by users or software.
- Malicious tampering, where an attacker replaces a legitimate file with a modified version.
It does not automatically prove the file is safe or authentic.
That’s why reputable software distributors also use digital signatures (such as GPG signatures or code signing certificates). A digital signature verifies who created the file, while the hash verifies that the file hasn’t changed.
- Hash = Has the file changed?
- Digital Signature = Did this file really come from the claimed publisher?
Common Hash Algorithms
Over the years, numerous hashing algorithms have been developed to meet different security and performance requirements. Some have become industry standards, while others are now considered obsolete due to discovered vulnerabilities. Below are some of the most well-known cryptographic hash algorithms.
MD5
MD5 produces a 128-bit hash, represented as a 32-character string.
Example:
$ echo -n "snubmonkey" | md5sum
or
$ echo -n "snubmonkey" | md5Produces:
a512eef7ff2a054e3e8a195c194545e2However, MD5 is considered insecure because researchers discovered practical collision attacks.
It should not be used for security purposes.
SHA-1
SHA-1 produces a 160-bit hash, represented as a 42-character string.
It was widely used for:
- certificates
- file verification
- digital signatures
However, collision attacks have demonstrated that SHA-1 is no longer suitable for security-critical applications.
SHA-2
SHA-2 is a family of stronger algorithms:
- SHA-224 = 56-character string.
- SHA-256 = 64-character string.
- SHA-384 = 96-character string.
- SHA-512 = 128-character string.
Example:
$ echo -n "snubmonkey" | sha512sum
or
$ echo -n "snubmonkey" | shasum -a 512Produces:
1f99b23951f451867ef5a85cace49d38225a0d2918708baa565dca7fbf4de593cae9834510844f046efba4b57d78239c246d557d880601ed10fa5589fd96943e -
SHA-512 always produces:
512 bits
=
128 hexadecimal characters
⚠️ Important: SHA-512 Is Not a Password Hashing Algorithm
Although SHA-512 is cryptographically secure, it is designed to be fast.
That is good for:
- file verification
- signatures
- integrity checks
But bad for passwords.
Attackers can calculate billions of SHA-512 hashes per second using GPUs.
Modern password storage uses intentionally slow algorithms:
- Argon2id
- bcrypt
- scrypt
- PBKDF2
Their goal is to make password guessing expensive.
How Password Authentication Works
The process looks like this:
Step 1
A user creates:
Username:
batman
Password:
kryptoniteStep 2
The system generates:
Password Hash
+
Unique Saltand stores:
Username
Salt
HashStep 3
The user logs in:
Username:
batman
Password:
kryptoniteStep 4
The system hashes the entered password using the stored salt.
Step 5
The generated hash is compared with the stored hash.
Step 6
If both values match:
Access GrantedWhat Is Password Salting?
A salt is a random value added to a password before or after hashing.
Without salt:
Password:
kryptonite
SHA-512:
e134898b50cdc8105ca0d8402a5171fdff4bb3dbf73e74e41652debb1a8fb51146ef69a45c47beb6eca5d629648302a9bfde3872353db2c8ebab2b7a8aab2128 -
Every user with the same password creates the same hash.
Example:
Superman:
kryptonite
Batman:
kryptoniteBoth would have:
Same HashThis creates a security problem.
With salt:
Superman:
kryptonite + 123
Batman:
kryptonite + 321The results become completely different:
Superman Hash:
0a18fbbec840ebcd658526f25771ae7d41e0d5de6fd951f567e979b335bc912a27a4719557a83fd4053095de64b8e2cebd24501a27da62b541854131cb9b7453 -
Batman Hash:
d473fb20cf85e7d38e5356c30f35d42ea5aa311992b154368ed29abbe7af8c0d4c11137ff343f34a164d4b0165c2446f3d21c2f30d2b8514716ae1d7390b0bab -
Even though both users selected the same password, their stored hashes are different.
Linux Password Storage
On Linux systems such as Ubuntu, password hashes are stored in:
/etc/shadowExample:
$ sudo grep kryptonite /etc/shadowOutput:
kryptonite:$6$n4wLdmr59ptB8zWG$4.YWKc2kv10JSB2jzaKcEUIL43u98NgijLhWljd9W7NaoipM.oRrm...The format is:
username:$algorithm$salt$hashExample:
$6$means:
SHA-512Common identifiers:
$1$ MD5
$5$ SHA-256
$6$ SHA-512
$2a$ bcrypt
$2y$ bcryptThe /etc/shadow file also contains:
- last password change date
- password expiration rules
- account aging information
Only root can read this file.
Are Hashes Enough to Protect Passwords?
No.
A hash protects passwords only when users choose strong passwords.
If an attacker obtains password hashes, they can perform:
Dictionary Attacks
Trying common passwords:
password123
welcome
qwerty
letmeinBrute Force Attacks
Trying every possible combination:
aaaaaaa
aaaaaab
aaaaaac
...Rainbow Table Attacks
Precomputed databases containing:
Hash → Possible PasswordSalt makes rainbow tables ineffective.
Strong Password Recommendations
Use:
- Long passwords (15+ characters recommended)
- Unique passwords for every service
- Password managers
- Multi-factor authentication
Avoid:
- Password reuse
- Dictionary words
- Personal information
- SMS-only authentication when stronger options exist
Hashing is one of the foundations of modern cybersecurity.
It allows systems to verify passwords without storing the passwords themselves.
However, hashing alone is not magic.
Security depends on:
- strong password policies
- secure hashing algorithms
- proper salting
- multi-factor authentication
- responsible system design
The password you create today may protect your digital identity for years. Understanding what happens behind the scenes is the first step toward protecting yourself online.
Stay tuned for more.