JEP draft: Argon2 Password Hashing Algorithm

OwnerArtur Barashev
TypeFeature
ScopeSE
StatusSubmitted
Componentsecurity-libs / javax.crypto
EffortM
DurationM
Relates toJEP 510: Key Derivation Function API
Reviewed bySean Mullan
Created2026/02/03 15:26
Updated2026/03/16 19:07
Issue8377081

Summary

Enhance the security of Java applications by providing an implementation of the Argon2 password hashing algorithm. Argon2 provides additional protection against brute-force password guessing attacks and was the winner of the 2015 Password Hashing Competition.

Goals

Non-Goals

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 graphics processing units (GPUs) or application-specific integrated circuits (ASICs).

Argon2 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 should provide a standard memory-hard password hashing algorithm. Other cryptographic libraries such as OpenSSL and BouncyCastle already support Argon2.

Description

Argon2 defines three variants:

This JEP proposes to implement Argon2id, thus offering a balance between side-channel resistance and TMTO protection. The algorithm will be implemented as a KDF service of the SunJCE provider, adhering to the API introduced in JEP 510.

Argon2id has several input parameters which can be used to configure the algorithm. These parameters can be tailored based on the security requirements of your application and the system it is running on. The memory (m, in KiB), iterations (t) and parallelism (p, number of execution threads) parameters allow applications to tune computational and memory cost according to their deployment requirements. The salt (typically 16 bytes), and optional secret (k) parameters are commonly used in password hashing algorithms to make password guessing attacks harder. Other parameters include optional associated data (x), the algorithm version (defaults to V13), and the tag length (tagLen, typically 32 bytes) which is the length of the resulting hash.

Integration with the KDF API

Argon2id is exposed as a standard KDF algorithm named "Argon2id". Applications obtain an instance using:

KDF.getInstance("Argon2id");

Argon2ParameterSpec class

The javax.crypto.spec.Argon2ParameterSpec class specifies parameters for the Argon2 algorithm:

public final class Argon2ParameterSpec implements AlgorithmParameterSpec {
    // input parameters
    int memoryKiB();
    int iterations();
    int parallelism();
    int tagLen();
    byte[] secret();
    byte[] associatedData();
    Argon2ParameterSpec.Version version();
    // password and salt
    byte[] password();
    byte[] salt();
    // builder
    static Argon2ParameterSpec.Builder newBuilder();
}

Argon2ParameterSpec.Builder class

The inner javax.crypto.spec.Argon2ParameterSpec.Builder class builds Argon2 inputs:

public static final class Builder {
    Builder memoryKiB(int m); 
    Builder memoryPowerOfTwo(int mPower);
    Builder iterations(int t);
    Builder parallelism(int p);
    Builder tagLen(int tagLen);
    Builder secret(byte[] k);
    Builder associatedData(byte[] x); 
    Builder version(Argon2ParameterSpec.Version ver);
    Argon2ParameterSpec build(byte[] salt, byte[] password);
    Argon2ParameterSpec build(byte[] salt, char[] password, Charset cs);
};

Argon2ParameterSpec.Version class

The inner javax.crypto.spec.Argon2ParameterSpec.Version class encapsulates Argon2 versions:

public enum Version {
    V10(0x10),  // version 1.0, not supported by SunJCE provider
    V13(0x13);  // RFC 9106 version, supported by SunJCE provider
};

Code Example

This example is based on the uniformly safe option №2 specified in section 4 of RFC 9106.

First, we create an Argon2ParameterSpec.Builder with 64 MiB of RAM, 3 iterations, 4 parallelly processed lanes and 256-bit tag length. Note: the memoryPowerOfTwo method sets the memory parameter to 2ⁿ KiB, where n is the value passed to the method; so in this example, 2¹⁶ = 65536 KiB or 64 MiB.

Argon2ParameterSpec.Builder builder = Argon2ParameterSpec.newBuilder()
    .memoryPowerOfTwo(16).iterations(3).parallelism(4).tagLen(32);

Next we call the build method and specify a random 128-bit salt and password we want to hash:

Argon2ParameterSpec param = builder.build(randomSalt128, password);

Then we obtain an Argon2id KDF instance and generate a password hash as a byte array:

KDF k = KDF.getInstance("Argon2id");
byte[] passwordHash = k.deriveData(param);

And we can also generate output as a SecretKey:

SecretKey key = k.deriveKey("Generic", param);

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:

Alternatives

The OWASP Password Storage Cheat Sheet lists three modern hashing algorithms that should be considered when selecting a password hashing algorithm: Argon2id, scrypt, and bcrypt. Of those 3, it recommends Argon2id as the preferred option. Here is some additional rationale as to why we chose Argon2id over scrypt and bcrypt:

Testing

Risks and Assumptions