diff --git a/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoder.java
index b3991cb8c22..e7248776a5d 100644
--- a/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoder.java
+++ b/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,9 +52,9 @@ public class Argon2PasswordEncoder implements PasswordEncoder {
private static final int DEFAULT_PARALLELISM = 1;
- private static final int DEFAULT_MEMORY = 1 << 12;
+ private static final int DEFAULT_MEMORY = 1 << 14;
- private static final int DEFAULT_ITERATIONS = 3;
+ private static final int DEFAULT_ITERATIONS = 2;
private final Log logger = LogFactory.getLog(getClass());
@@ -68,10 +68,24 @@ public class Argon2PasswordEncoder implements PasswordEncoder {
private final BytesKeyGenerator saltGenerator;
+ /**
+ * Constructs an Argon2 password encoder with a salt length of 16 bytes, a hash length
+ * of 32 bytes, parallelism of 1, memory cost of 1 << 12 and 3 iterations.
+ * @deprecated Use {@link #defaultsForSpringSecurity_v5_2()} instead
+ */
+ @Deprecated
public Argon2PasswordEncoder() {
- this(DEFAULT_SALT_LENGTH, DEFAULT_HASH_LENGTH, DEFAULT_PARALLELISM, DEFAULT_MEMORY, DEFAULT_ITERATIONS);
+ this(16, 32, 1, 1 << 12, 3);
}
+ /**
+ * Constructs an Argon2 password encoder with the provided parameters.
+ * @param saltLength the salt length (in bytes)
+ * @param hashLength the hash length (in bytes)
+ * @param parallelism the parallelism
+ * @param memory the memory cost
+ * @param iterations the number of iterations
+ */
public Argon2PasswordEncoder(int saltLength, int hashLength, int parallelism, int memory, int iterations) {
this.hashLength = hashLength;
this.parallelism = parallelism;
@@ -80,6 +94,29 @@ public Argon2PasswordEncoder(int saltLength, int hashLength, int parallelism, in
this.saltGenerator = KeyGenerators.secureRandom(saltLength);
}
+ /**
+ * Constructs an Argon2 password encoder with a salt length of 16 bytes, a hash length
+ * of 32 bytes, parallelism of 1, memory cost of 1 << 12 and 3 iterations.
+ * @return the {@link Argon2PasswordEncoder}
+ * @since 5.8
+ * @deprecated Use {@link #defaultsForSpringSecurity_v5_8()} instead
+ */
+ @Deprecated
+ public static Argon2PasswordEncoder defaultsForSpringSecurity_v5_2() {
+ return new Argon2PasswordEncoder(16, 32, 1, 1 << 12, 3);
+ }
+
+ /**
+ * Constructs an Argon2 password encoder with a salt length of 16 bytes, a hash length
+ * of 32 bytes, parallelism of 1, memory cost of 1 << 14 and 2 iterations.
+ * @return the {@link Argon2PasswordEncoder}
+ * @since 5.8
+ */
+ public static Argon2PasswordEncoder defaultsForSpringSecurity_v5_8() {
+ return new Argon2PasswordEncoder(DEFAULT_SALT_LENGTH, DEFAULT_HASH_LENGTH, DEFAULT_PARALLELISM, DEFAULT_MEMORY,
+ DEFAULT_ITERATIONS);
+ }
+
@Override
public String encode(CharSequence rawPassword) {
byte[] salt = this.saltGenerator.generateKey();
diff --git a/crypto/src/main/java/org/springframework/security/crypto/factory/PasswordEncoderFactories.java b/crypto/src/main/java/org/springframework/security/crypto/factory/PasswordEncoderFactories.java
index eb27d4a058c..dd9beafab2c 100644
--- a/crypto/src/main/java/org/springframework/security/crypto/factory/PasswordEncoderFactories.java
+++ b/crypto/src/main/java/org/springframework/security/crypto/factory/PasswordEncoderFactories.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,7 +58,9 @@ private PasswordEncoderFactories() {
*
SHA-256 - {@code new MessageDigestPasswordEncoder("SHA-256")}
* sha256 -
* {@link org.springframework.security.crypto.password.StandardPasswordEncoder}
- * argon2 - {@link Argon2PasswordEncoder}
+ * argon2 - {@link Argon2PasswordEncoder#defaultsForSpringSecurity_v5_2()}
+ * argon2@SpringSecurity_v5_8 -
+ * {@link Argon2PasswordEncoder#defaultsForSpringSecurity_v5_8()}
*
* @return the {@link PasswordEncoder} to use
*/
@@ -77,7 +79,8 @@ public static PasswordEncoder createDelegatingPasswordEncoder() {
encoders.put("SHA-256",
new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));
encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());
- encoders.put("argon2", new Argon2PasswordEncoder());
+ encoders.put("argon2", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2());
+ encoders.put("argon2@SpringSecurity_v5_8", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8());
return new DelegatingPasswordEncoder(encodingId, encoders);
}
diff --git a/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoderTests.java b/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoderTests.java
index 6aaa6904912..9fb2a7412e8 100644
--- a/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoderTests.java
+++ b/crypto/src/test/java/org/springframework/security/crypto/argon2/Argon2PasswordEncoderTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ public class Argon2PasswordEncoderTests {
@Mock
private BytesKeyGenerator keyGeneratorMock;
- private Argon2PasswordEncoder encoder = new Argon2PasswordEncoder();
+ private Argon2PasswordEncoder encoder = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2();
@Test
public void encodeDoesNotEqualPassword() {
@@ -127,6 +127,15 @@ public void encodeWhenUsingPredictableSaltWithCustomParamsThenEqualTestHash() th
"$argon2id$v=19$m=512,t=5,p=4$QUFBQUFBQUFBQUFBQUFBQQ$PNv4C3K50bz3rmON+LtFpdisD7ePieLNq+l5iUHgc1k");
}
+ @Test
+ public void encodeWhenUsingPredictableSaltWithDefaultsForSpringSecurity_v5_8ThenEqualTestHash() throws Exception {
+ this.encoder = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8();
+ injectPredictableSaltGen();
+ String hash = this.encoder.encode("sometestpassword");
+ assertThat(hash).isEqualTo(
+ "$argon2id$v=19$m=16384,t=2,p=1$QUFBQUFBQUFBQUFBQUFBQQ$zGt5MiNPSUOo4/7jBcJMayCPfcsLJ4c0WUxhwGDIYPw");
+ }
+
@Test
public void upgradeEncodingWhenSameEncodingThenFalse() {
String hash = this.encoder.encode("password");
@@ -135,7 +144,7 @@ public void upgradeEncodingWhenSameEncodingThenFalse() {
@Test
public void upgradeEncodingWhenSameStandardParamsThenFalse() {
- Argon2PasswordEncoder newEncoder = new Argon2PasswordEncoder();
+ Argon2PasswordEncoder newEncoder = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2();
String hash = this.encoder.encode("password");
assertThat(newEncoder.upgradeEncoding(hash)).isFalse();
}
diff --git a/crypto/src/test/java/org/springframework/security/crypto/factory/PasswordEncoderFactoriesTests.java b/crypto/src/test/java/org/springframework/security/crypto/factory/PasswordEncoderFactoriesTests.java
index ab2ca94a94c..d28f89dfae3 100644
--- a/crypto/src/test/java/org/springframework/security/crypto/factory/PasswordEncoderFactoriesTests.java
+++ b/crypto/src/test/java/org/springframework/security/crypto/factory/PasswordEncoderFactoriesTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -105,4 +105,10 @@ public void matchesWhenArgon2ThenWorks() {
assertThat(this.encoder.matches(this.rawPassword, encodedPassword)).isTrue();
}
+ @Test
+ public void matchesWhenArgon2SpringSecurity_v5_8ThenWorks() {
+ String encodedPassword = "{argon2@SpringSecurity_v5_8}$argon2id$v=19$m=16384,t=2,p=1$v7fN5p91BQbdbA2HfdSPRg$MULpa02CO/6FKfqwuerCFvS7OhMxGFCKUOoWfzt86Rc";
+ assertThat(this.encoder.matches(this.rawPassword, encodedPassword)).isTrue();
+ }
+
}