@ -16,6 +16,7 @@
@@ -16,6 +16,7 @@
package org.springframework.security.crypto.password ;
import java.security.GeneralSecurityException ;
import java.security.NoSuchAlgorithmException ;
import javax.crypto.SecretKeyFactory ;
import javax.crypto.spec.PBEKeySpec ;
@ -41,7 +42,7 @@ import static org.springframework.security.crypto.util.EncodingUtils.subArray;
@@ -41,7 +42,7 @@ import static org.springframework.security.crypto.util.EncodingUtils.subArray;
* @since 4 . 1
* /
public class Pbkdf2PasswordEncoder implements PasswordEncoder {
private static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1" ;
private static final int DEFAULT_HASH_WIDTH = 256 ;
private static final int DEFAULT_ITERATIONS = 185000 ;
@ -50,6 +51,7 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
@@ -50,6 +51,7 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
private final byte [ ] secret ;
private final int hashWidth ;
private final int iterations ;
private String algorithm = SecretKeyFactoryAlgorithm . PBKDF2WithHmacSHA1 . name ( ) ;
/ * *
* Constructs a PBKDF2 password encoder with no additional secret value . There will be
@ -86,6 +88,28 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
@@ -86,6 +88,28 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
this . hashWidth = hashWidth ;
}
/ * *
* Sets the algorithm to use . See
* < a href = "http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory" > SecretKeyFactory Algorithms < / a >
* @param secretKeyFactoryAlgorithm the algorithm to use ( i . e .
* { @code Pbkdf2PasswordEncoder . PBKDF2_WITH_HMAC_SHA1 } ,
* { @code Pbkdf2PasswordEncoder . PBKDF2_WITH_HMAC_SHA256 } ,
* { @code Pbkdf2PasswordEncoder . PBKDF2_WITH_HMAC_SHA512 } )
* /
public void setAlgorithm ( SecretKeyFactoryAlgorithm secretKeyFactoryAlgorithm ) {
if ( secretKeyFactoryAlgorithm = = null ) {
throw new IllegalArgumentException ( "secretKeyFactoryAlgorithm cannot be null" ) ;
}
String algorithmName = secretKeyFactoryAlgorithm . name ( ) ;
try {
SecretKeyFactory . getInstance ( algorithmName ) ;
}
catch ( NoSuchAlgorithmException e ) {
throw new IllegalArgumentException ( "Invalid algorithm '" + algorithmName + "'." , e ) ;
}
this . algorithm = algorithmName ;
}
@Override
public String encode ( CharSequence rawPassword ) {
byte [ ] salt = this . saltGenerator . generateKey ( ) ;
@ -119,11 +143,20 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
@@ -119,11 +143,20 @@ public class Pbkdf2PasswordEncoder implements PasswordEncoder {
try {
PBEKeySpec spec = new PBEKeySpec ( rawPassword . toString ( ) . toCharArray ( ) ,
concatenate ( salt , this . secret ) , this . iterations , this . hashWidth ) ;
SecretKeyFactory skf = SecretKeyFactory . getInstance ( PBKDF2_ALGORITHM ) ;
SecretKeyFactory skf = SecretKeyFactory . getInstance ( this . algorithm ) ;
return concatenate ( salt , skf . generateSecret ( spec ) . getEncoded ( ) ) ;
}
catch ( GeneralSecurityException e ) {
throw new IllegalStateException ( "Could not create hash" , e ) ;
}
}
}
/ * *
* The Algorithm used for creating the { @link SecretKeyFactory }
* /
public enum SecretKeyFactoryAlgorithm {
PBKDF2WithHmacSHA1 ,
PBKDF2WithHmacSHA256 ,
PBKDF2WithHmacSHA512
}
}