PHP crypt() Function

Beginner
⏱️ 9 min read
📚 Updated: Jul 2026
🎯 5 Examples
String Functions

What You’ll Learn

The crypt() function performs one-way hashing of strings using salt-based algorithms like bcrypt and SHA-512. It is the low-level foundation behind password storage in PHP—though modern apps should prefer password_hash().

01

One-Way Hash

Not encryption.

02

Salt Required

Mandatory since PHP 8.

03

Verify Pattern

crypt($input, $hash).

04

hash_equals()

Timing-safe compare.

05

bcrypt / SHA

Salt prefix sets algo.

06

password_hash

Modern replacement.

Definition and Usage

In PHP, crypt() hashes a string using the algorithm encoded in the $salt parameter. The returned hash includes the salt and algorithm identifier at the start (for example $2y$10$... for bcrypt), so you can store one string in your database and use it later for verification.

💡
Beginner Tip

For new password features, use password_hash() and password_verify(). Learn crypt() to understand legacy systems, read existing hashes, or work with non-PHP software that stores crypt-format passwords.

📝 Syntax

The crypt() function requires both a string and a salt:

PHP
string crypt(string $string, string $salt)

Parameters

  • $string — the plain text to hash (typically a password). bcrypt truncates input to 72 bytes.
  • $salt — a salt string that selects the algorithm. Examples: $2y$10$... (bcrypt), $6$... (SHA-512), $5$... (SHA-256). Required since PHP 8.0.

Return Value

Returns the hashed string on success. On failure, returns a string shorter than 13 characters that is guaranteed to differ from the salt. There is no decrypt function—hashing is one-way.

Supported Salt Prefixes

  • $2y$ — bcrypt (Blowfish), recommended for legacy crypt usage
  • $6$ — SHA-512 crypt
  • $5$ — SHA-256 crypt
  • $1$ — MD5 crypt (legacy, avoid for new code)
  • Two-character salt — standard DES (obsolete, avoid)

⚡ Quick Reference

Hash (bcrypt)
crypt($pass, '$2y$10$' . $salt22)

22-char salt after prefix

Verify
crypt($input, $stored) === $stored

Reuse hash as salt

Safe compare
hash_equals($stored, crypt($in, $stored))

Timing-attack safe

Modern
password_hash($pass, PASSWORD_DEFAULT)

Preferred for new apps

Examples Gallery

Run these examples in PHP 8+. Each demonstrates a common pattern beginners encounter with crypt().

📚 Getting Started

Hash a password with bcrypt and inspect the result format.

Example 1 — Hash a Password with bcrypt

Provide a bcrypt salt prefix ($2y$10$) plus 22 salt characters. The hash embeds the salt for later verification.

PHP
<?php
$password = "rasmuslerdorf";

// bcrypt: $2a$ + 2-digit cost + $ + 22-char salt
$salt = '$2a$07$usesomesillystringf';
$hash = crypt($password, $salt);

echo "Hash:   $hash\n";
echo "Length: " . strlen($hash) . " characters\n";
echo "Prefix: " . substr($hash, 0, 7) . " (bcrypt, cost 07)\n";
?>

How It Works

  • The first 29 characters of the hash contain the algorithm ($2a$ or $2y$), cost factor, and salt.
  • With the same salt and password, the hash is always identical—use a unique random salt per user in production.
  • Never store plain-text passwords; save the full hash string in your database.

Example 2 — Verify a Password (PHP Manual Pattern)

Pass the stored hash as the salt. If crypt() output matches the stored hash, the password is correct.

PHP
<?php
$userInput       = 'rasmuslerdorf';
$hashed_password = '$6$rounds=1000000$NJy4rIPjpOaU$0ACEYGg/aKCY3v8O8AfyiO7CTfZQ8/W231Qfh2tRLmfdvFD6XfHk12u6hMr9cYIA4hnpjLNSTRtUwYr9km9Ij/';

if (hash_equals($hashed_password, crypt($userInput, $hashed_password))) {
    echo "Password verified!\n";
} else {
    echo "Password incorrect.\n";
}
?>

How It Works

This is the official PHP documentation example. The stored hash uses SHA-512 crypt ($6$). hash_equals() compares strings in constant time to reduce timing-attack risk.

📈 Practical Patterns

Registration, login, and modern alternatives.

Example 3 — Registration and Login Flow

Simulate storing a hash at registration and checking it when the user logs in.

PHP
<?php
// --- Registration: hash and store in database ---
$password = "MySecretPass!";
$salt     = '$2y$10$' . bin2hex(random_bytes(11)); // 22 hex chars
$stored   = crypt($password, $salt);

// --- Login: user submits a password ---
function checkPassword(string $input, string $storedHash): bool
{
    return hash_equals($storedHash, crypt($input, $storedHash));
}

echo "Correct password: " . (checkPassword("MySecretPass!", $stored) ? "OK\n" : "FAIL\n");
echo "Wrong password:   " . (checkPassword("WrongPass!", $stored) ? "OK\n" : "FAIL\n");
?>

How It Works

Each registration generates a unique random salt, so two users with the same password get different hashes. At login, pass the stored hash as the salt—crypt() extracts the algorithm and salt automatically.

Example 4 — crypt() vs password_hash() (Recommended)

password_hash() is a secure wrapper around crypt() with automatic salt and cost management.

PHP
<?php
$password = "SecurePassword123";

// Modern approach (recommended)
$hash1 = password_hash($password, PASSWORD_DEFAULT);
$ok1   = password_verify($password, $hash1);

// Low-level crypt() equivalent (manual salt)
$salt  = '$2y$10$' . bin2hex(random_bytes(11));
$hash2 = crypt($password, $salt);
$ok2   = hash_equals($hash2, crypt($password, $hash2));

echo "password_hash verify: " . ($ok1 ? "yes\n" : "no\n");
echo "crypt verify:         " . ($ok2 ? "yes\n" : "no\n");
echo "password_verify works with crypt hashes: "
   . (password_verify($password, $hash2) ? "yes\n" : "no\n");
?>

How It Works

password_verify() is compatible with hashes created by crypt(), so you can migrate gradually. For all new code, prefer password_hash() and PASSWORD_DEFAULT (currently bcrypt, may upgrade to Argon2).

Example 5 — Why Use hash_equals() Instead of ===

Never compare password hashes with a plain === in security-sensitive code—use hash_equals() for constant-time comparison.

PHP
<?php
$stored = crypt("demoPass", '$2y$10$usesomesillystringf');
$input  = "demoPass";
$computed = crypt($input, $stored);

// Both return true for a correct password:
$plainCompare = ($computed === $stored);
$safeCompare  = hash_equals($stored, $computed);

echo "=== comparison:        " . ($plainCompare ? "match\n" : "no match\n");
echo "hash_equals():         " . ($safeCompare ? "match\n" : "no match\n");
echo "\nUse hash_equals() in production to reduce timing-attack risk.\n";
?>

How It Works

Both operators produce the same result here, but === may exit early on the first differing character, leaking timing information. hash_equals() always compares every byte.

🚀 Common Use Cases

  • Password storage — hash user passwords before saving to a database (prefer password_hash()).
  • Legacy system maintenance — verify passwords stored in crypt format by older PHP apps.
  • Cross-platform compatibility — validate hashes created by Unix crypt utilities or other languages.
  • Understanding password_hash() — learn what happens under the hood when PHP hashes passwords.
  • Custom salt strategies — control algorithm and cost when you cannot use the password API.

🧠 How crypt() Works

1

PHP reads the salt prefix

The salt string tells PHP which algorithm to use—bcrypt ($2y$), SHA-512 ($6$), etc.

Input
2

One-way hash is computed

PHP runs the selected algorithm on the input string combined with the salt. The original text cannot be recovered.

Transform
3

Hash with embedded salt returned

The output includes the salt and algorithm prefix, ready to store in a database for future verification.

Output
=

Stored password hash

Verify later with crypt($input, $storedHash) and hash_equals().

📝 Notes

  • crypt() is hashing, not encryption—there is no decrypt function.
  • The $salt parameter is required since PHP 8.0 (the old reference showing crypt($password) alone is outdated).
  • Use a unique random salt per password in production—never reuse demo salts like usesomesillystringf.
  • MD5 crypt ($1$) and DES are legacy and weak—avoid for new applications.
  • Always compare hashes with hash_equals(), not ===, in security-sensitive code.

Conclusion

The crypt() function provides low-level, salt-based one-way hashing for passwords and other sensitive strings. Understanding its salt prefixes and verification pattern helps you maintain legacy systems and appreciate how password_hash() works.

For new PHP applications, use password_hash() and password_verify(). When you must use crypt() directly, always provide a strong salt and compare with hash_equals().

💡 Best Practices

✅ Do

  • Use password_hash() for all new password features
  • Generate unique salts with random_bytes()
  • Compare with hash_equals() when verifying
  • Store the full hash string (salt is embedded inside)
  • Use bcrypt ($2y$) or SHA-512 ($6$) for strong hashes

❌ Don’t

  • Call crypt() without a salt (removed in PHP 8)
  • Store plain-text passwords in your database
  • Reuse the same salt for every user
  • Use MD5 crypt ($1$) or DES for new passwords
  • Compare hashes with === in login systems

Key Takeaways

Knowledge Unlocked

Five things to remember about crypt()

Use these points whenever you work with password hashing in PHP.

5
Core concepts
🔒 02

Salt Required

Mandatory in PHP 8.

Syntax
🔄 03

Verify Pattern

crypt($in, $hash).

Usage
📧 04

hash_equals()

Safe comparison.

Security
05

password_hash

Modern default.

Modern

❓ Frequently Asked Questions

crypt() performs one-way hashing of a string using a salt-based algorithm such as bcrypt (Blowfish), SHA-256, or SHA-512. The returned hash embeds the salt and algorithm identifier—there is no decrypt function.
string crypt(string $string, string $salt). Both parameters are required since PHP 8.0. The salt string determines the algorithm (e.g. $2y$10$ for bcrypt) and must be generated securely.
Pass the stored hash as the salt: crypt($userInput, $storedHash). If the result equals $storedHash, the password is correct. Always compare with hash_equals() to prevent timing attacks.
Use password_hash() and password_verify() for new PHP applications. They wrap crypt() with secure defaults (bcrypt/argon2), automatic salt generation, and proper cost factors.
No. Since PHP 8.0, the salt parameter is required. Calling crypt() without a salt was already insecure in earlier versions and is no longer allowed.
No. crypt() is one-way hashing—you cannot recover the original password from the hash. Encryption is reversible; hashing is not.

Explore More PHP String Functions

Continue with explode(), htmlspecialchars(), and the rest of the string function reference.

Next: explode() →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful