Linux Password Hashing Explained: /etc/shadow, Salting, and Security.

Learn how Linux password hashing works, how salts protect stored credentials, what /etc/shadow contains, and why modern systems use specialized password-hashing algorithms.

Linux Password Hashing Explained: /etc/shadow, Salting, and Security.
Illustration by SNUBmonkeyteam

In our previous post, [Cryptographic Hashing Explained: Linux Commands and Examples], we explored cryptographic hashes and how Linux uses them to verify file integrity.

In this article, we'll focus on Linux password hashing and security. You'll learn how Linux stores password information in /etc/shadow, how salting protects credentials, and why specialized algorithms such as Argon2id, bcrypt, and yescrypt help defend against password-guessing attacks.

Understanding these mechanisms is essential for Linux administrators who want to secure user accounts and protect authentication credentials.

How Password Hashing Works

Password hashing transforms a password into a representation that can be stored and checked during authentication.

Consider a user who enters a password when logging in to a Linux system.

The authentication process typically works as follows:

  1. The user enters a password.
  2. The system retrieves the user's stored password-hash information.
  3. A password-verification function processes the supplied password using the stored parameters and salt.
  4. The system compares the result with the stored verifier.
  5. Authentication succeeds if verification passes and any other required authentication checks are satisfied.

The original password does not need to be stored in readable form.

Unlike encryption, password hashing is not designed to be reversed. When a user forgets a password, a properly configured system generally resets it rather than decrypting the original value.

Important: A password hash is not the same as a password. It is a stored representation used to verify a password attempt.

Where Linux Stores Password Information

On most traditional Linux systems, account information is maintained in two important files: /etc/passwd and /etc/shadow.

The /etc/passwd File

The /etc/passwd file contains basic account information, including usernames, user IDs, group IDs, home directories, and login shells.

You can inspect its contents with:

$ cat /etc/passwd

A typical entry looks like this:

john:x:1000:1000:John Doe:/home/john:/bin/bash

The second field contains x, indicating that the password information is stored separately, usually in /etc/shadow.

The /etc/passwd file is generally readable by local users because many system components need to look up account information.


The /etc/shadow File

The /etc/shadow file contains password-hash information and related account-aging fields.

Because this information is security-sensitive, access is restricted to privileged users and authorized system components.

To inspect a specific account's entry, use:

$ sudo grep '^john:' /etc/shadow

Replace john with the actual username.

A password-hash field may look like this:

$6$salt-value$hashed-password-value

This is an illustrative example of the format used by SHA-512-based Unix password hashing.

A real entry contains the actual salt and encoded hash, along with account information in subsequent colon-separated fields.

Never share the contents of /etc/shadow publicly.
The stored hashes are not plaintext passwords, but an attacker who obtains them may attempt to recover the passwords through offline guessing.

Understanding Linux Password-Hash Formats

Linux password hashes often use a structured format that identifies the algorithm and its parameters.

For example:

$6$salt-value$hashed-password-value

The components mean:

  • $6$ identifies the SHA-512-based crypt password-hashing format.
  • salt-value represents the salt used during hashing.
  • hashed-password-value represents the resulting encoded password hash.

The $6$ identifier does not mean that Linux simply calculates one ordinary SHA-512 hash of the password. The SHA-512-based crypt scheme uses a specific password-hashing construction with its own processing rules.

Other common identifiers include:

  • $1$ — MD5-based crypt, an obsolete choice for password storage.
  • $5$ — SHA-256-based crypt.
  • $6$ — SHA-512-based crypt.
  • $2a$, $2b$, or $2y$ — variants associated with bcrypt.
  • $y$ — yescrypt, used by some Linux distributions.

The exact formats available depend on the Linux distribution, authentication configuration, and installed libraries.

Seeing a hash prefix helps identify the format, but it does not, by itself, prove that an account is securely configured.

What Is a Salt in Password Hashing?

A salt is a value incorporated into the password-hashing process to make identical passwords produce different stored results.

Consider two users who choose the same password.

Without a salt, a deterministic hashing process using the same algorithm and parameters produces the same hash for both users. An attacker who obtains the password database can immediately identify identical hash values.

With unique salts, the password-hashing function processes each password with a different salt. As a result, identical passwords generally produce different stored hashes.

Salts provide several important security benefits:

  • They prevent identical passwords from automatically producing identical stored hashes when different salts are used.
  • They make precomputed lookup tables, including conventional rainbow tables, far less useful against the salted hashes.
  • They require attackers to perform separate password-guessing work for each salt rather than reusing one computed result across every account.

A salt does not need to be secret. It is normally stored alongside the password hash so that the system can verify future login attempts.

A salt does not make a weak password strong. Attackers can still guess common passwords and calculate the corresponding salted hash. Salting improves resistance to certain attacks, but it does not eliminate password guessing.

Why SHA-512 Alone Is Not Enough for Password Storage

SHA-512 is a cryptographic hash function that produces a 512-bit digest. It is useful for many integrity-related tasks, but its speed creates a problem when storing passwords.

General-purpose hash functions are designed to process data efficiently. Modern hardware can calculate enormous numbers of these hashes, allowing attackers to test many password guesses quickly if they obtain a password database.

For example, suppose an attacker obtains a database containing password hashes. The attacker can try candidate passwords, process each guess using the appropriate algorithm and parameters, and compare the results with the stolen entries.

If the password is weak and the hashing process is fast, the attacker may recover it relatively quickly.

This is why secure password storage requires more than selecting a cryptographically strong general-purpose hash function.

Password-hashing algorithms are deliberately designed to make each password guess more expensive.

Modern Password-Hashing Algorithms

Password-hashing algorithms make each password guess more costly. Their work settings should be chosen for the application and updated as hardware and recommendations change.

1. Argon2id

Argon2id uses configurable memory and computation to make large-scale password guessing more expensive. It is a strong choice for new applications when supported by the application framework and authentication system.

2. bcrypt

bcrypt is widely supported and has a configurable work factor. A higher factor increases the cost of each guess. Use a reputable library and account for bcrypt’s input-length limit.

3. scrypt

scrypt is designed to require both memory and computation, increasing the cost of testing many guesses in parallel. It remains a suitable option where supported and properly configured.

4. PBKDF2

PBKDF2 repeatedly applies a pseudorandom function to a password-derived value. More iterations increase the cost of each guess. It is widely supported, but must use appropriate parameters and a suitable underlying function.


Which Algorithm Should You Choose?

For new applications, Argon2id is often a strong default when the platform supports it and the parameters can be tuned appropriately.

bcrypt, scrypt, and PBKDF2 can also be suitable choices depending on the application, platform requirements, and security policies.

The algorithm alone does not determine security. Developers and administrators must also consider:

  • The strength of user-selected passwords.
  • The algorithm's parameters and computational cost.
  • The implementation and its handling of salts.
  • The ability to upgrade parameters as hardware becomes faster.
  • The authentication system's protection against online login attempts.

Use well-maintained authentication libraries and established system mechanisms rather than writing custom password-hashing code.

Common Password-Guessing Attacks

Knowing how attackers guess passwords helps explain why secure password storage matters.

1. Dictionary attacks

Dictionary attacks try likely passwords drawn from common words, leaked credentials, and predictable variations. Passwords based on names, dates, or familiar patterns are more likely to be guessed.

2. Brute-force attacks

Brute-force attacks systematically test password combinations. The effort required depends on factors such as password length, predictability, the hashing algorithm, and the attacker’s computing power. Long, unique passwords are harder to guess.

3. Rainbow-table attacks

Rainbow tables are precomputed data used to speed up the recovery of some password hashes. Unique salts make these tables far less useful by requiring attackers to calculate guesses separately for each salt. Salts do not stop guessing altogether.

4. Offline attacks

An offline attack begins when someone obtains stored password hashes and tests guesses without contacting the login service. Because online rate limits do not apply, strong password hashing and unique salts are important safeguards.

Linux Password-Hashing Best Practices

  1. Use strong, unique passwords. Avoid common words, predictable patterns, and reusing passwords across services.
  2. Use modern password-hashing methods. For applications you manage, use a maintained implementation of Argon2id or another suitable password-hashing algorithm. For Linux system accounts, use the mechanisms supported by your distribution.
  3. Protect /etc/shadow. Keep its intended ownership and permissions. Never make it world-readable or store copies in unsecured locations.
  4. Treat password hashes as sensitive. Hashes are not plaintext passwords, but attackers can still try to recover the passwords from them.
  5. Keep systems and authentication software updated. Updates help address known security weaknesses.
  6. Enable multifactor authentication where appropriate. An additional factor can help protect accounts if a password is compromised.
  7. Limit online login attempts. Use rate limits, monitoring, and suitable authentication policies. These controls do not stop offline guessing against stolen hashes.
  8. Plan to update hashing parameters. As hardware improves, older settings may become less effective. Use systems that can update password hashes when users sign in or reset their passwords.

Linux password hashing protects credentials without storing plain-text passwords. Understanding /etc/passwd, /etc/shadow, unique salts, and secure algorithms like Argon2id, bcrypt, scrypt, and PBKDF2 is essential for protecting accounts and auditing systems.

Keep Us Caffeinated  ⦿ ⦿
Spotify Logo
↑
SNUBmonkey Join our readers