JEP draft: Argon2 Password Hashing Algorithm
| Owner | Artur Barashev |
| Type | Feature |
| Scope | SE |
| Status | Draft |
| Component | security-libs / javax.crypto |
| Effort | M |
| Duration | M |
| Relates to | JEP 510: Key Derivation Function API |
| Created | 2026/02/03 15:26 |
| Updated | 2026/02/27 20:45 |
| Issue | 8377081 |
Summary
Implement the Argon2id password-hashing algorithm in the SunJCE provider via the javax.crypto.KDF API. This makes a modern password-hashing algorithm available through the standard Java cryptographic architecture.
Goals
- Implement Argon2id adhering to the architecture introduced in JEP 510.
Non-Goals
- Enforce specific parameter-strength policies.
Motivation
The Java Platform should offer better support for password-hashing algorithms beyond PBKDF2. PBKDF2 is compute-bound and low-memory, which maps well to massively parallel hardware and makes it susceptible to offline cracking with GPUs/ASICs.
Argon2, the winner of the 2015 Password Hashing Competition (PHC) and standardized in RFC 9106, is a memory-hard algorithm.
Memory-hardness increases the cost of large-scale password guessing by limiting the degree to which attackers can exploit specialized hardware. For example, if each guess requires 64 MiB of memory, then a device with 8 GiB of available memory can execute only about 128 guesses in parallel, rather than thousands or millions.
The Java Platform does not currently provide a standardized memory-hard password-hashing algorithm. Applications that require Argon2 rely on third-party libraries.
Description
Argon2 defines three variants:
- Argon2d — data-dependent memory access, provides better protection against time-memory trade-off (TMTO) attacks.
- Argon2i — data-independent memory access, provides better protection against side-channel attacks.
- Argon2id — hybrid design, per RFC 9106 "Argon2id MUST be supported by any implementation of this document".
This JEP proposes to implement Argon2id, thus offering a balance of side-channel attack and TMTO protection. Argon2id is parameterized by memory (m, in KiB), iterations (t), parallelism (p), output length, and version. These parameters allow applications to tune computational and memory cost according to their deployment requirements.
Integration with the KDF API
-
Argon2id is exposed as a standard KDF algorithm named "Argon2id". Applications obtain an instance using:
KDF.getInstance("Argon2id"); -
Argon2-specific inputs are represented by:
public final class Argon2ParameterSpec implements AlgorithmParameterSpecThis class encapsulates the password, nonce, and all algorithm parameters required for an Argon2 derivation. It includes support for Argon2d and Argon2i variants, thus enabling other security providers to implement them if they choose to do so.
Example 1
// Specifying algorithm parameters manually and generating
// raw key material as a byte array.
Argon2ParameterSpec param =
Argon2ParameterSpec.newBuilder(argonVariant)
.nonce(nonce).parallelism(p).memoryKiB(m)
.iterations(t).tagLen(outputLen).build(password);
KDF k = KDF.getInstance("Argon2id");
byte[] value = k.deriveData(param);
Example 2
// Specifying algorithm parameters with PHC string and generating
// an output as a SecretKey.
Argon2ParameterSpec param =
Argon2ParameterSpec.newBuilder(phcString).build(password);
KDF k = KDF.getInstance("Argon2id");
SecretKey key = k.deriveKey("AES", param);
PHC String Format
The implementation supports parsing and encoding the PHC string format for all Argon2 variants.
Security Considerations
- Pass the password to the algorithm as either
byte[]orchar[]to reduce secret lifetime in memory. - Validate algorithm parameters to ensure they stay within their defined ranges.
- Provide DoS/misuse resistance when parsing PHC strings: the SunJCE implementation will enforce restrictions against algorithm parameters. This prevents a remote attacker from supplying a PHC string that requests an arbitrary amount of RAM.
Side-Channel Considerations
- Applications verifying passwords should compare derived values in constant time.
Implementation Notes
- Argon2 input and output limits defined as unsigned 32-bit values (2³²−1) in RFC 9106 are capped at 2³¹−1 due to Java array size constraints.
Failure Behavior
- Throws
IllegalArgumentExceptionif invalid input parameters are passed to the algorithm. - May throw
OutOfMemoryErrorif JVM cannot allocate memory requested by the algorithm.
Alternatives
- PBKDF2 — CPU-bound.
- bcrypt — widely deployed but not memory-hard by modern standards.
- scrypt — memory-hard but permits more efficient time–memory trade-offs than Argon2.
Testing
- Verification against RFC 9106 known-answer test vectors.
- PHC interoperability testing.
- Boundary and exception testing.
- Regression testing within the SunJCE provider.
Risks and Assumptions
- Argon2's memory-hardness relies on the JVM's ability to allocate large blocks of memory.
- Runtime effects (e.g., GC activity) may introduce timing variability; callers should not treat execution time as constant.
- The strength is not fixed. It depends entirely on the algorithm's parameters. If weak parameters are used, Argon2 becomes weak. As the memory (m) decreases, the iterations (t) must increase to maintain security levels.
Appendix
Migration from PBKDF2
PBKDF2 is implemented via javax.crypto.SecretKeyFactory while this JEP proposes to implement Argon2id via javax.crypto.KDF API. Java applications wishing to migrate from PBKDF2 to Argon2id will need to make code modifications to adopt KDF API.
While adopting Argon2id requires code changes, migrating stored credentials requires a data- and rollout-strategy as well, since PBKDF2 and Argon2id outputs are not interchangeable. Recommended strategies include:
- Opportunistic migration during user authentication.
- Possibly rehashing existing stored verifiers by applying Argon2id to the existing PBKDF2 output (application-dependent and must be evaluated carefully).
Recommended Parameter Profiles (Non-Normative Guidance)
RFC 9106 lists 2 uniformly safe options for Argon2id:
- High-security: m=2 GiB, t=1, p=4
- Memory-constrained: m=64 MiB, t=3, p=4