Skip to content

Commit a173a71

Browse files
committed
Update default configuration for Pbkdf2PasswordEncoder
The recommended minimums for PBKDF2, as per OWASP Cheat Sheet Series (https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html), are: If FIPS-140 compliance is required, use PBKDF2 with a work factor of 310,000 or more and set with an internal hash function of HMAC-SHA-256. Previous default configuration: algorithm=SHA1, iterations=185000, hashLength=256 New default configuration: algorithm=SHA256, iterations=310000, hashLength=256 The default salt length was also updated from 8 to 16. Issue gh-10506
1 parent e81a30b commit a173a71

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed

crypto/src/main/java/org/springframework/security/crypto/factory/PasswordEncoderFactories.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -71,7 +71,14 @@ public static PasswordEncoder createDelegatingPasswordEncoder() {
7171
encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());
7272
encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));
7373
encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
74-
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
74+
75+
// Preserve the original settings for PBKDF2 for backwards compatibility.
76+
// The default configuration has been updated to the recommended minimums.
77+
// See gh-10506 Update PasswordEncoder Minimums
78+
Pbkdf2PasswordEncoder pbkdf2PasswordEncoder = new Pbkdf2PasswordEncoder("", 8, 185000, 256);
79+
pbkdf2PasswordEncoder.setAlgorithm(Pbkdf2PasswordEncoder.SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA1);
80+
encoders.put("pbkdf2", pbkdf2PasswordEncoder);
81+
7582
encoders.put("scrypt", new SCryptPasswordEncoder());
7683
encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));
7784
encoders.put("SHA-256",

crypto/src/main/java/org/springframework/security/crypto/password/Pbkdf2PasswordEncoder.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -50,11 +50,11 @@
5050
*/
5151
public class Pbkdf2PasswordEncoder implements PasswordEncoder {
5252

53-
private static final int DEFAULT_SALT_LENGTH = 8;
53+
private static final int DEFAULT_SALT_LENGTH = 16;
5454

5555
private static final int DEFAULT_HASH_WIDTH = 256;
5656

57-
private static final int DEFAULT_ITERATIONS = 185000;
57+
private static final int DEFAULT_ITERATIONS = 310000;
5858

5959
private final BytesKeyGenerator saltGenerator;
6060

@@ -64,7 +64,7 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
6464

6565
private final int iterations;
6666

67-
private String algorithm = SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA1.name();
67+
private String algorithm = SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA256.name();
6868

6969
private boolean encodeHashAsBase64;
7070

crypto/src/test/java/org/springframework/security/crypto/password/Pbkdf2PasswordEncoderTests.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818

1919
import java.util.Arrays;
2020

21+
import org.junit.jupiter.api.BeforeEach;
2122
import org.junit.jupiter.api.Test;
2223

2324
import org.springframework.security.crypto.codec.Hex;
@@ -28,11 +29,23 @@
2829

2930
public class Pbkdf2PasswordEncoderTests {
3031

31-
private Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder("secret");
32+
private Pbkdf2PasswordEncoder encoder;
3233

33-
private Pbkdf2PasswordEncoder encoderSalt16 = new Pbkdf2PasswordEncoder("", 16);
34+
private Pbkdf2PasswordEncoder encoderSalt16;
3435

35-
private Pbkdf2PasswordEncoder[] encoders = new Pbkdf2PasswordEncoder[] { this.encoder, this.encoderSalt16 };
36+
private Pbkdf2PasswordEncoder[] encoders;
37+
38+
@BeforeEach
39+
public void setup() {
40+
// Restore the original settings for PBKDF2 for backwards compatibility.
41+
// The default configuration has been updated to the recommended minimums.
42+
// See gh-10506 Update PasswordEncoder Minimums
43+
this.encoder = new Pbkdf2PasswordEncoder("secret", 8, 185000, 256);
44+
this.encoder.setAlgorithm(Pbkdf2PasswordEncoder.SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA1);
45+
this.encoderSalt16 = new Pbkdf2PasswordEncoder("", 16, 185000, 256);
46+
this.encoderSalt16.setAlgorithm(Pbkdf2PasswordEncoder.SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA1);
47+
this.encoders = new Pbkdf2PasswordEncoder[] { this.encoder, this.encoderSalt16 };
48+
}
3649

3750
@Test
3851
public void encodedLengthSuccess() {

0 commit comments

Comments
 (0)