Password Hashing
Secure password storage using cryptographic hashing algorithms
Radiator Server supports multiple password hashing algorithms for secure credential storage. When user passwords are loaded from backends (SQL, JSON files, etc.), Radiator automatically detects the hashing algorithm based on the password format prefix and uses the appropriate verification method during authentication.
How It Works
- Passwords stored in backends include a prefix that identifies the hashing algorithm:
{argon2},{crypt-sha256}, etc. - When a backend loads user data, the password format is detected automatically
- During authentication, Radiator compares the provided plaintext password against the stored hash using the appropriate algorithm
- No configuration is needed - the algorithm is determined by the password prefix
Supported Algorithms
Radiator supports the following password hashing algorithms:
| Algorithm | Prefix | Security Level | Use Case |
|---|---|---|---|
| Argon2 | {argon2} | Highest | Strongest GPU/ASIC resistance; needs the CPU and memory budget to match |
| PBKDF2-SHA512 | {pbkdf2-sha512} | High | FIPS 140-approved KDF; LDAP/RFC 2307bis interoperability |
| PBKDF2-SHA256 | {pbkdf2-sha256} | High | FIPS 140-approved KDF; LDAP/RFC 2307bis interoperability |
| PBKDF2-SHA1 | {pbkdf2-sha1} or {pbkdf2} | Medium | Legacy LDAP/Dovecot stores (use SHA-256/512 for new data) |
| Crypt SHA-512 | {crypt-sha512} | Medium | Legacy systems, Linux/Unix compatibility |
| Crypt SHA-256 | {crypt-sha256} | Medium | Legacy systems, Linux/Unix compatibility |
| NT Hash | {nthash} | Low | Windows compatibility (not recommended for new systems) |
| Plaintext | (no prefix) | None | Required for protocols that need the cleartext password (CHAP, MS-CHAP/MS-CHAPv2, EAP-MD5); development/testing |
Prefix matching is case-insensitive, so LDAP RFC 2307bis style values like {PBKDF2-SHA512} work alongside the lowercase {pbkdf2-sha512} form.
Argon2 (Highest security)
Argon2 offers the strongest resistance against brute-force attacks among the supported algorithms, including GPU- and ASIC-based cracking. Radiator uses the Argon2id variant for balanced protection against side-channel and GPU attacks.
Argon2 is memory-hard by design, so each verification allocates the configured memory budget (e.g. 16 MiB at m=16384). Under high authentication volume this becomes the limiting factor: peak concurrent requests × m must fit in the server's RAM budget, and CPU stays busy for the full verification time. For example, 10 concurrent verifications at m=4096 reserve ~40 MB, and at m=16384 ~160 MB. If the deployment cannot guarantee that headroom, choose a lower-memory PBKDF2 variant rather than under-tuning Argon2.
Format:
{argon2}$argon2id$v=19$m=16384,t=2,p=1$<salt>$<hash>
Parameters:
m=4096(4 MiB),m=16384(16 MiB), orm=32768(32 MiB) - Memory cost in KiB (specified via-m 12/14/15where 2^n KiB)t=2ort=3- Time cost (number of iterations through memory)p=1orp=2- Parallelism (number of parallel threads)- Salt and hash are base64-encoded
Recommended settings:
- Standard:
t=2, p=1, m=4096(4 MiB) - Good balance for most use cases - High security:
t=2, p=1, m=16384(16 MiB) - Better protection against attacks - Very high security:
t=3, p=1, m=16384(16 MiB) - Excellent protection
See "Performance Considerations" section below for detailed timing benchmarks.
Generate Argon2 hash:
# Standard security (4 MiB, ~100ms on typical vCPU)
echo -n "password" | argon2 $(openssl rand -base64 16) -id -t 2 -m 12 -p 1 -l 32 -e
# High security (16 MiB, ~400ms)
echo -n "password" | argon2 $(openssl rand -base64 16) -id -t 2 -m 14 -p 1 -l 32 -e
Example:
{argon2}$argon2id$v=19$m=16384,t=2,p=1$ZTM0ODY1YTUxZTQ1ZWFiNQ$MAz1wx2FHcKDw6vYVVUKTwR+Sc240NzMAQxjbtRhDbY
PBKDF2 (SHA-512 / SHA-256 / SHA-1)
PBKDF2-HMAC is the password hashing function specified in RFC 2898. Radiator supports the SHA-512, SHA-256 and SHA-1 variants. PBKDF2 is not memory-hard, so each verification needs only a few hundred bytes of working memory regardless of iteration count — this makes it well suited to high-volume authentication servers where Argon2's per-request memory budget would not fit.
When to choose PBKDF2:
- High-volume / memory-constrained deployments. PBKDF2 scales to thousands of concurrent verifications without the multi-MiB-per-request RAM cost of Argon2.
- FIPS 140 / NIST SP 800-132 compliance. PBKDF2 is an approved key derivation function under FIPS 140-3 and is recommended by NIST SP 800-132 for password-based key derivation; Argon2 is not (yet) on the FIPS-approved list.
- OWASP Password Storage Cheat Sheet lists PBKDF2 as an acceptable second choice after Argon2id, particularly for FIPS-validated environments.
- Interoperability with existing identity stores that emit
{PBKDF2-SHAxxx}or{PBKDF2}hashes (OpenLDAP, 389-ds, Dovecot, Django, Synology DSM, ...).
For green-field deployments with the CPU and memory headroom to absorb Argon2's per-request cost, prefer Argon2id. Otherwise PBKDF2-HMAC-SHA512 is the next-strongest option in Radiator.
Formats accepted on input:
-
PHC string (the standard portable format for PBKDF2-SHA256 / PBKDF2-SHA512):
{pbkdf2-sha512}$pbkdf2-sha512$i=210000,l=64$<b64-salt>$<b64-hash> {pbkdf2-sha256}$pbkdf2-sha256$i=600000,l=32$<b64-salt>$<b64-hash> -
LDAP RFC 2307bis layout (also commonly used for PBKDF2-SHA1, which has no PHC identifier):
{pbkdf2-sha512}<iterations>$<b64-salt>$<b64-hash> {pbkdf2-sha256}<iterations>$<b64-salt>$<b64-hash> {pbkdf2-sha1}<iterations>$<b64-salt>$<b64-hash> {pbkdf2}<iterations>$<b64-salt>$<b64-hash> # alias for PBKDF2-SHA1
Both standard and unpadded base64 encodings are accepted. The iteration count and salt embedded in the stored value are always honoured during verification, so hashes generated against older defaults keep working.
When generating new PBKDF2 hashes for Radiator, follow the OWASP Password Storage Cheat Sheet defaults: 1 300 000 iterations for SHA-1, 600 000 for SHA-256 and 210 000 for SHA-512, with at least a 16-byte CSPRNG salt. Hashes are produced by the identity store (LDAP, application database, password manager, ...) before being handed to Radiator; Radiator only verifies them.
Example:
{pbkdf2-sha512}$pbkdf2-sha512$i=210000,l=64$Z2QuoEKKKa3xJ3OQM/CR6w$Q1qfeq43...
{pbkdf2-sha1}2$c2FsdA==$6mwBTcctb4zNHtkqzh1B8NjeiVc=
Crypt SHA-512
SHA-512 based crypt hashing, commonly used in Linux/Unix systems. Provides reasonable security for legacy applications.
Format:
{crypt-sha512}$6$rounds=5000$<salt>$<hash>
Example:
{crypt-sha512}$6$rounds=5000$saltsaltsal$hash...
Crypt SHA-256
SHA-256 based crypt hashing, similar to SHA-512 but with shorter hash length.
Format:
{crypt-sha256}$5$rounds=5000$<salt>$<hash>
Example:
{crypt-sha256}$5$rounds=5000$saltsaltsal$hash...
NT Hash
NT hash (MD4-based) used in Windows systems. Provided for compatibility but not recommended for new deployments due to weak security.
Format:
{nthash}<hex-encoded-hash>
Plaintext
Passwords without a prefix are treated as plaintext. Plaintext storage is required for authentication protocols where the server cannot verify the credential without knowing the actual cleartext password:
- CHAP (RFC 1994) — the server must compute
MD5(ident || password || challenge)to compare against the client response. - MS-CHAP / MS-CHAPv2 — the server must derive the NT hash from the cleartext at verification time (a stored
{nthash}is also accepted; see above). - EAP-MD5 — same MD5 challenge/response construction as CHAP.
- Digest authentication variants that hash the cleartext into
HA1per request.
For PAP and any protocol that only needs to compare a presented password against a stored value, prefer a hashed format (Argon2, PBKDF2, crypt-sha512) over plaintext.
Example:
mypassword123
Warning: Never use plaintext passwords in production environments.
Warning: If a plaintext password contains text that looks like a hash prefix (e.g., {argon2}, {crypt-sha256}), Radiator will attempt to parse it as a hashed password, causing authentication to fail. Always use hashed passwords to avoid this ambiguity.
Usage Examples
JSON File Backend
{
"users": [
{
"username": "alice",
"password": "{argon2}$argon2id$v=19$m=16384,t=2,p=1$..."
},
{
"username": "bob",
"password": "{crypt-sha512}$6$rounds=5000$..."
}
]
}
SQL Backend
CREATE TABLE users (
username VARCHAR(255) PRIMARY KEY,
password TEXT NOT NULL
);
INSERT INTO users (username, password) VALUES
('alice', '{argon2}$argon2id$v=19$m=16384,t=2,p=1$...'),
('bob', '{crypt-sha256}$5$rounds=5000$...');
Backend Configuration
No special configuration is needed. The password format is detected automatically:
backends {
sqlite "USERS" {
filename "users.db";
query "FIND_USER" {
statement "SELECT username, password FROM users WHERE username = ?";
bindings { aaa.identity; }
mapping {
user.username = username;
user.password = password; # Format auto-detected from prefix
}
}
}
}
Security Recommendations
- Pick the strongest algorithm your capacity supports: Argon2id gives the best resistance against modern attacks but is memory-hard; under high authentication volume, prefer PBKDF2-HMAC-SHA512 if the server cannot sustain Argon2's per-request memory and CPU cost
- Choose appropriate parameters: Use
t=2, p=1, m=4096(4 MiB) for standard security (~100ms), orm=16384(16 MiB) for high security (~300-400ms) - Generate unique salts: Always use cryptographically random salts (use
openssl randor equivalent) - Migrate legacy hashes: If using crypt-sha256/512, consider migrating to Argon2, or to PBKDF2-HMAC-SHA512 where interoperability with LDAP-style password stores is required
- Never use plaintext: Always hash passwords, even for development databases
- Avoid NT Hash: Only use for Windows integration where absolutely required
Performance Considerations
Password hashing is intentionally slow to prevent brute-force attacks. The longer the time to verify the more resistant to brute-force attacks the hash is. It also costs more CPU time on the Radiator server so it is usually the dominant sizing guideline. Performance characteristics on typical server vCPU:
| Algorithm | Parameters | Hash time | CPUs for 100 TPS | Comments |
|---|---|---|---|---|
| Argon2id | t=2, p=1, m=4096 (4 MiB) | ~100 ms | ~10 | Standard security |
| Argon2id | t=2, p=1, m=16384 (16 MiB) | ~300-400 ms | ~30-40 | High security |
| Argon2id | t=3, p=1, m=16384 (16 MiB) | ~500-600 ms | ~50-60 | Very high security |
| PBKDF2-SHA1 | i=1 300 000 (OWASP default) | ~140 ms | ~14 | Legacy interop; prefer SHA-256/512 for new data |
| PBKDF2-SHA256 | i=600 000 (OWASP default) | ~70 ms | ~7 | FIPS 140-approved KDF |
| PBKDF2-SHA512 | i=210 000 (OWASP default) | ~110 ms | ~11 | FIPS 140-approved KDF |
| Crypt SHA-512 | rounds=5000 (default) | ~30 ms | ~3 | Legacy Linux/Unix compatibility |
| Crypt SHA-256 | rounds=5000 (default) | ~100 ms | ~10 | Legacy Linux/Unix compatibility |
| NT Hash | - | <1 ms | <1 | Weak security; Windows compatibility only |
The "CPUs for 100 TPS" column is hash_time_ms / 10: a single fully-busy core sustains 1000 / hash_time_ms verifications per second, so 100 TPS needs that many cores. Provision additional headroom for the rest of the request pipeline and traffic bursts.
Hash cost scales linearly with the work parameters: halving PBKDF2 i, or Argon2 t, p or m, halves both the verification time and the CPU needed for a given TPS target (Argon2 m also halves the per-request memory budget). This makes capacity planning a direct trade-off — pick the slowest hash the available computing budget can absorb at peak load.
Related Documentation
- HTTP Basic Authentication - Using password hashing with HTTP authentication
- TOTP/HOTP Authentication - Two-factor authentication with password hashing
- jsonfile Backend - Using password hashes in JSON files
- SQL Backends - Using password hashes in databases
About Radiator software development security
Architecture Overview
Backend Load Balancing
Basic Installation
Built-in Environment Variables
Comparison Operators
Configuration Editor
Configuration Import and Export
Containers
Data Types
Duration Units
Environment Variables
Execution Context
Execution Pipelines
Filters
Getting a Radiator License
Health check /live and /ready
High Availability and Load Balancing
High availability identifiers
HTTP Basic Authentication
Introduction
Linux systemd support
Local AAA Backends
Log storage and formatting
Management API privilege levels
Namespaces
Password Hashing
Probabilistic Sampling
Prometheus scraping
PROXY Protocol Support
Radiator server health and boot up logic
Radiator sizing
Radiator software releases
Rate Limiting
Rate Limiting Algorithms
Reverse Dynamic Authorization
Service Level Objective
TACACS+ Authentication, Authorization, and Accounting
Template Rendering CLI
Tools radiator-client
TOTP/HOTP Authentication
What is Radiator?
YubiKey Authentication
YubiKey Context Variables
About Radiator software development security
Architecture Overview
Backend Load Balancing
Basic Installation
Built-in Environment Variables
Comparison Operators
Configuration Editor
Configuration Import and Export
Containers
Data Types
Duration Units
Environment Variables
Execution Context
Execution Pipelines
Filters
Getting a Radiator License
Health check /live and /ready
High Availability and Load Balancing
High availability identifiers
HTTP Basic Authentication
Introduction
Linux systemd support
Local AAA Backends
Log storage and formatting
Management API privilege levels
Namespaces
Password Hashing
Probabilistic Sampling
Prometheus scraping
PROXY Protocol Support
Radiator server health and boot up logic
Radiator sizing
Radiator software releases
Rate Limiting
Rate Limiting Algorithms
Reverse Dynamic Authorization
Service Level Objective
TACACS+ Authentication, Authorization, and Accounting
Template Rendering CLI
Tools radiator-client
TOTP/HOTP Authentication
What is Radiator?
YubiKey Authentication
YubiKey Context Variables