1
1
/*
2
- * Copyright 2002-2020 the original author or authors.
2
+ * Copyright 2002-2022 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
36
36
* <li>a configurable random salt value length (default is {@value #DEFAULT_SALT_LENGTH}
37
37
* bytes)</li>
38
38
* <li>a configurable number of iterations (default is {@value #DEFAULT_ITERATIONS})</li>
39
- * <li>a configurable output hash width (default is {@value #DEFAULT_HASH_WIDTH}
40
- * bits)</li>
41
39
* <li>a configurable key derivation function (see {@link SecretKeyFactoryAlgorithm})</li>
42
40
* <li>a configurable secret appended to the random salt (default is empty)</li>
43
41
* </ul>
50
48
*/
51
49
public class Pbkdf2PasswordEncoder implements PasswordEncoder {
52
50
53
- private static final int DEFAULT_SALT_LENGTH = 8 ;
51
+ private static final int DEFAULT_SALT_LENGTH = 16 ;
54
52
55
- private static final int DEFAULT_HASH_WIDTH = 256 ;
53
+ private static final SecretKeyFactoryAlgorithm DEFAULT_ALGORITHM = SecretKeyFactoryAlgorithm . PBKDF2WithHmacSHA256 ;
56
54
57
- private static final int DEFAULT_ITERATIONS = 185000 ;
55
+ private static final int DEFAULT_HASH_WIDTH = 256 ; // SHA-256
56
+
57
+ private static final int DEFAULT_ITERATIONS = 310000 ;
58
58
59
59
private final BytesKeyGenerator saltGenerator ;
60
60
61
61
private final byte [] secret ;
62
62
63
- private final int hashWidth ;
64
-
65
63
private final int iterations ;
66
64
67
- private String algorithm = SecretKeyFactoryAlgorithm .PBKDF2WithHmacSHA1 .name ();
65
+ private String algorithm = DEFAULT_ALGORITHM .name ();
66
+
67
+ private int hashWidth = DEFAULT_HASH_WIDTH ;
68
+
69
+ // @formatter:off
70
+ /*
71
+ The length of the hash should be derived from the hashing algorithm.
72
+
73
+ For example:
74
+ SHA-1 - 160 bits (20 bytes)
75
+ SHA-256 - 256 bits (32 bytes)
76
+ SHA-512 - 512 bits (64 bytes)
77
+
78
+ However, the original configuration for PBKDF2 was hashWidth=256 and algorithm=SHA-1, which is incorrect.
79
+ The default configuration has been updated to hashWidth=256 and algorithm=SHA-256 (see gh-10506).
80
+ In order to preserve backwards compatibility, the variable 'overrideHashWidth' has been introduced
81
+ to indicate usage of the deprecated constructor that honors the hashWidth parameter.
82
+ */
83
+ // @formatter:on
84
+ private boolean overrideHashWidth = true ;
68
85
69
86
private boolean encodeHashAsBase64 ;
70
87
71
88
/**
72
89
* Constructs a PBKDF2 password encoder with no additional secret value. There will be
73
- * a salt length of {@value #DEFAULT_SALT_LENGTH} bytes, {@value #DEFAULT_ITERATIONS}
74
- * iterations and a hash width of {@value #DEFAULT_HASH_WIDTH} bits. The default is
75
- * based upon aiming for .5 seconds to validate the password when this class was
76
- * added. Users should tune password verification to their own systems.
90
+ * a salt length of 8 bytes, 185,000 iterations, SHA-1 algorithm and a hash length of
91
+ * 256 bits. The default is based upon aiming for .5 seconds to validate the password
92
+ * when this class was added. Users should tune password verification to their own
93
+ * systems.
94
+ * @deprecated Use {@link #defaultsForSpringSecurity_v5_5()} instead
77
95
*/
96
+ @ Deprecated
78
97
public Pbkdf2PasswordEncoder () {
79
98
this ("" );
80
99
}
81
100
82
101
/**
83
- * Constructs a standard password encoder with a secret value which is also included
84
- * in the password hash. There will be a salt length of {@value #DEFAULT_SALT_LENGTH}
85
- * bytes, {@value #DEFAULT_ITERATIONS} iterations and a hash width of
86
- * {@value #DEFAULT_HASH_WIDTH} bits.
102
+ * Constructs a PBKDF2 password encoder with a secret value which is also included in
103
+ * the password hash. There will be a salt length of 8 bytes, 185,000 iterations,
104
+ * SHA-1 algorithm and a hash length of 256 bits.
87
105
* @param secret the secret key used in the encoding process (should not be shared)
106
+ * @deprecated Use {@link #Pbkdf2PasswordEncoder(CharSequence, int, int, int)} instead
88
107
*/
108
+ @ Deprecated
89
109
public Pbkdf2PasswordEncoder (CharSequence secret ) {
90
- this (secret , DEFAULT_SALT_LENGTH , DEFAULT_ITERATIONS , DEFAULT_HASH_WIDTH );
110
+ this (secret , 8 );
91
111
}
92
112
93
113
/**
94
- * Constructs a standard password encoder with a secret value as well as salt length.
95
- * There will be {@value #DEFAULT_ITERATIONS} iterations and a hash width of
96
- * {@value #DEFAULT_HASH_WIDTH} bits.
114
+ * Constructs a PBKDF2 password encoder with a secret value as well as salt length.
115
+ * There will be 185,000 iterations, SHA-1 algorithm and a hash length of 256 bits.
97
116
* @param secret the secret
98
117
* @param saltLength the salt length (in bytes)
99
118
* @since 5.5
119
+ * @deprecated Use {@link #Pbkdf2PasswordEncoder(CharSequence, int, int, int)} instead
100
120
*/
121
+ @ Deprecated
101
122
public Pbkdf2PasswordEncoder (CharSequence secret , int saltLength ) {
102
- this (secret , saltLength , DEFAULT_ITERATIONS , DEFAULT_HASH_WIDTH );
123
+ this (secret , saltLength , 185000 , 256 );
103
124
}
104
125
105
126
/**
106
- * Constructs a standard password encoder with a secret value as well as iterations
107
- * and hash width. The salt length will be of {@value #DEFAULT_SALT_LENGTH} bytes.
127
+ * Constructs a PBKDF2 password encoder with a secret value as well as iterations and
128
+ * hash width. The salt length will be 8 bytes.
108
129
* @param secret the secret
109
130
* @param iterations the number of iterations. Users should aim for taking about .5
110
131
* seconds on their own system.
111
132
* @param hashWidth the size of the hash (in bits)
133
+ * @deprecated Use {@link #Pbkdf2PasswordEncoder(CharSequence, int, int, int)} instead
112
134
*/
135
+ @ Deprecated
113
136
public Pbkdf2PasswordEncoder (CharSequence secret , int iterations , int hashWidth ) {
114
- this (secret , DEFAULT_SALT_LENGTH , iterations , hashWidth );
137
+ this (secret , 8 , iterations , hashWidth );
115
138
}
116
139
117
140
/**
118
- * Constructs a standard password encoder with a secret value as well as salt length,
141
+ * Constructs a PBKDF2 password encoder with a secret value as well as salt length,
119
142
* iterations and hash width.
120
143
* @param secret the secret
121
144
* @param saltLength the salt length (in bytes)
122
145
* @param iterations the number of iterations. Users should aim for taking about .5
123
146
* seconds on their own system.
124
147
* @param hashWidth the size of the hash (in bits)
125
148
* @since 5.5
149
+ * @deprecated Use
150
+ * {@link #Pbkdf2PasswordEncoder(CharSequence, int, int, SecretKeyFactoryAlgorithm)}
151
+ * instead
126
152
*/
153
+ @ Deprecated
127
154
public Pbkdf2PasswordEncoder (CharSequence secret , int saltLength , int iterations , int hashWidth ) {
128
155
this .secret = Utf8 .encode (secret );
129
156
this .saltGenerator = KeyGenerators .secureRandom (saltLength );
130
157
this .iterations = iterations ;
131
158
this .hashWidth = hashWidth ;
159
+ this .algorithm = SecretKeyFactoryAlgorithm .PBKDF2WithHmacSHA1 .name ();
160
+ this .overrideHashWidth = false ; // Honor 'hashWidth' to preserve backwards
161
+ // compatibility
162
+ }
163
+
164
+ /**
165
+ * Constructs a PBKDF2 password encoder with a secret value as well as salt length,
166
+ * iterations and algorithm.
167
+ * @param secret the secret
168
+ * @param saltLength the salt length (in bytes)
169
+ * @param iterations the number of iterations. Users should aim for taking about .5
170
+ * seconds on their own system.
171
+ * @param secretKeyFactoryAlgorithm the algorithm to use
172
+ * @since 5.8
173
+ */
174
+ public Pbkdf2PasswordEncoder (CharSequence secret , int saltLength , int iterations ,
175
+ SecretKeyFactoryAlgorithm secretKeyFactoryAlgorithm ) {
176
+ this .secret = Utf8 .encode (secret );
177
+ this .saltGenerator = KeyGenerators .secureRandom (saltLength );
178
+ this .iterations = iterations ;
179
+ setAlgorithm (secretKeyFactoryAlgorithm );
180
+ }
181
+
182
+ /**
183
+ * Constructs a PBKDF2 password encoder with no additional secret value. There will be
184
+ * a salt length of 8 bytes, 185,000 iterations, SHA-1 algorithm and a hash length of
185
+ * 256 bits. The default is based upon aiming for .5 seconds to validate the password
186
+ * when this class was added. Users should tune password verification to their own
187
+ * systems.
188
+ * @return the {@link Pbkdf2PasswordEncoder}
189
+ * @since 5.8
190
+ * @deprecated Use {@link #defaultsForSpringSecurity_v5_8()} instead
191
+ */
192
+ @ Deprecated
193
+ public static Pbkdf2PasswordEncoder defaultsForSpringSecurity_v5_5 () {
194
+ return new Pbkdf2PasswordEncoder ("" , 8 , 185000 , 256 );
195
+ }
196
+
197
+ /**
198
+ * Constructs a PBKDF2 password encoder with no additional secret value. There will be
199
+ * a salt length of 16 bytes, 310,000 iterations, SHA-256 algorithm and a hash length
200
+ * of 256 bits. The default is based upon aiming for .5 seconds to validate the
201
+ * password when this class was added. Users should tune password verification to
202
+ * their own systems.
203
+ * @return the {@link Pbkdf2PasswordEncoder}
204
+ * @since 5.8
205
+ */
206
+ public static Pbkdf2PasswordEncoder defaultsForSpringSecurity_v5_8 () {
207
+ return new Pbkdf2PasswordEncoder ("" , DEFAULT_SALT_LENGTH , DEFAULT_ITERATIONS , DEFAULT_ALGORITHM );
132
208
}
133
209
134
210
/**
@@ -153,6 +229,10 @@ public void setAlgorithm(SecretKeyFactoryAlgorithm secretKeyFactoryAlgorithm) {
153
229
catch (NoSuchAlgorithmException ex ) {
154
230
throw new IllegalArgumentException ("Invalid algorithm '" + algorithmName + "'." , ex );
155
231
}
232
+ if (this .overrideHashWidth ) {
233
+ this .hashWidth = SecretKeyFactoryAlgorithm .PBKDF2WithHmacSHA1 .equals (secretKeyFactoryAlgorithm ) ? 160
234
+ : SecretKeyFactoryAlgorithm .PBKDF2WithHmacSHA256 .equals (secretKeyFactoryAlgorithm ) ? 256 : 512 ;
235
+ }
156
236
}
157
237
158
238
/**
0 commit comments