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.
Fundamentals
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.
Foundation
📝 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)
Cheat Sheet
⚡ 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
Hands-On
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.
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.
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.
password_hash verify: yes
crypt verify: yes
password_verify works with crypt hashes: yes
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";
?>
📤 Output:
=== comparison: match
hash_equals(): match
Use hash_equals() in production to reduce timing-attack risk.
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.
Applications
🚀 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().
Important
📝 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.
Wrap Up
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().
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
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about crypt()
Use these points whenever you work with password hashing in PHP.
5
Core concepts
📝01
One-Way Hash
Not reversible.
Purpose
🔒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.