Package org.apache.shiro.crypto.hash
Class DefaultHashService
- java.lang.Object
-
- org.apache.shiro.crypto.hash.DefaultHashService
-
- All Implemented Interfaces:
ConfigurableHashService
,HashService
public class DefaultHashService extends Object implements ConfigurableHashService
Default implementation of theHashService
interface, supporting a customizable hash algorithm name, secure-random salt generation, multiple hash iterations and an optional internalprivateSalt
.Hash Algorithm
You may specify a hash algorithm via thesetHashAlgorithmName(String)
property. Any algorithm name understood by the JDKMessageDigest.getInstance(String algorithmName)
method will work. The default isSHA-512
.Random Salts
When a salt is not specified in a request, this implementation generates secure random salts via itsrandomNumberGenerator
property. Random salts (and potentially combined with the internalprivateSalt
) is a very strong salting strategy, as salts should ideally never be based on known/guessable data. The default instance is aSecureRandomNumberGenerator
.Hash Iterations
Secure hashing strategies often employ multiple hash iterations to slow down the hashing process. This technique is usually used for password hashing, since the longer it takes to compute a password hash, the longer it would take for an attacker to compromise a password. This blog article explains in greater detail why this is useful, as well as information on how many iterations is 'enough'. You may set the number of hash iterations via thesetHashIterations(int)
property. The default is1
, but should be increased significantly if theHashService
is intended to be used for password hashing. See the linked blog article for more info.Private Salt
If using this implementation as part of a password hashing strategy, it might be desirable to configure aprivate salt
: A hash and the salt used to compute it are often stored together. If an attacker is ever able to access the hash (e.g. during password cracking) and it has the full salt value, the attacker has all of the input necessary to try to brute-force crack the hash (source + complete salt). However, if part of the salt is not available to the attacker (because it is not stored with the hash), it is much harder to crack the hash value since the attacker does not have the complete inputs necessary. TheprivateSalt
property exists to satisfy this private-and-not-shared part of the salt. If you configure this attribute, you can obtain this additional very important safety feature. *By default, theprivateSalt
is null, since a sensible default cannot be used that isn't easily compromised (because Shiro is an open-source project and any default could be easily seen and used).- Since:
- 1.2
-
-
Constructor Summary
Constructors Constructor Description DefaultHashService()
Constructs a newDefaultHashService
instance with the following defaults:hashAlgorithmName
=SHA-512
hashIterations
=1
randomNumberGenerator
= newSecureRandomNumberGenerator
()generatePublicSalt
=false
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description protected ByteSource
combine(ByteSource privateSalt, ByteSource publicSalt)
Combines the specified 'private' salt bytes with the specified additional extra bytes to use as the total salt during hash computation.Hash
computeHash(HashRequest request)
Computes and responds with a hash based on the specified request.protected String
getAlgorithmName(HashRequest request)
String
getHashAlgorithmName()
int
getHashIterations()
protected int
getIterations(HashRequest request)
ByteSource
getPrivateSalt()
protected ByteSource
getPublicSalt(HashRequest request)
Returns the public salt that should be used to compute a hash based on the specified request ornull
if no public salt should be used.RandomNumberGenerator
getRandomNumberGenerator()
boolean
isGeneratePublicSalt()
Returnstrue
if a public salt should be randomly generated and used to compute a hash if aHashRequest
does not specify a salt,false
otherwise.void
setGeneratePublicSalt(boolean generatePublicSalt)
Sets whether or not a public salt should be randomly generated and used to compute a hash if aHashRequest
does not specify a salt.void
setHashAlgorithmName(String name)
Sets the name of theMessageDigest
algorithm that will be used to compute hashes.void
setHashIterations(int count)
Sets the number of hash iterations that will be performed during hash computation.void
setPrivateSalt(ByteSource privateSalt)
Sets the 'private' (internal) salt to be paired with a 'public' (random or supplied) salt during hash computation.void
setRandomNumberGenerator(RandomNumberGenerator rng)
Sets a source of randomness used to generate public salts that will in turn be used during hash computation.
-
-
-
Constructor Detail
-
DefaultHashService
public DefaultHashService()
Constructs a newDefaultHashService
instance with the following defaults:hashAlgorithmName
=SHA-512
hashIterations
=1
randomNumberGenerator
= newSecureRandomNumberGenerator
()generatePublicSalt
=false
privateSalt
and significantly increase the number ofhashIterations
. See the class-level JavaDoc for more information.
-
-
Method Detail
-
computeHash
public Hash computeHash(HashRequest request)
Computes and responds with a hash based on the specified request. This implementation functions as follows:- If the request's
salt
is null: A salt will be generated and used to compute the hash. The salt is generated as follows:- Use the
randomNumberGenerator
to generate a new random number. combine
this random salt with any configuredprivateSalt
- Use the combined value as the salt used during hash computation
- Use the
-
If the request salt is not null:
This indicates that the hash computation is for comparison purposes (of a
previously computed hash). The request salt will be
combined
with any configuredprivateSalt
and used as the complete salt during hash computation.
Hash
'ssalt
property will contain only the 'public' part of the salt and NOT the privateSalt. See the class-level JavaDoc explanation for more info.- Specified by:
computeHash
in interfaceHashService
- Parameters:
request
- the request to process- Returns:
- the response containing the result of the hash computation, as well as any hash salt used that should be exposed to the caller.
- See Also:
Hash.getSalt()
- If the request's
-
getAlgorithmName
protected String getAlgorithmName(HashRequest request)
-
getIterations
protected int getIterations(HashRequest request)
-
getPublicSalt
protected ByteSource getPublicSalt(HashRequest request)
Returns the public salt that should be used to compute a hash based on the specified request ornull
if no public salt should be used. This implementation functions as follows:- If the request salt is not null and non-empty, this will be used, return it.
- If the request salt is null or empty:
- If a private salt has been set OR
isGeneratePublicSalt()
istrue
, auto generate a random public salt via the configuredrandomNumberGenerator
. - If a private salt has not been configured and
isGeneratePublicSalt()
isfalse
, do nothing - returnnull
to indicate a salt should not be used during hash computation.
- If a private salt has been set OR
- Parameters:
request
- request the request to process- Returns:
- the public salt that should be used to compute a hash based on the specified request or
null
if no public salt should be used.
-
combine
protected ByteSource combine(ByteSource privateSalt, ByteSource publicSalt)
Combines the specified 'private' salt bytes with the specified additional extra bytes to use as the total salt during hash computation.privateSaltBytes
will benull
}if no private salt has been configured.- Parameters:
privateSalt
- the (possiblynull
) 'private' salt to combine with the specified extra bytespublicSalt
- the extra bytes to use in addition to the given private salt.- Returns:
- a combination of the specified private salt bytes and extra bytes that will be used as the total salt during hash computation.
-
setHashAlgorithmName
public void setHashAlgorithmName(String name)
Description copied from interface:ConfigurableHashService
Sets the name of theMessageDigest
algorithm that will be used to compute hashes.- Specified by:
setHashAlgorithmName
in interfaceConfigurableHashService
- Parameters:
name
- the name of theMessageDigest
algorithm that will be used to compute hashes.
-
getHashAlgorithmName
public String getHashAlgorithmName()
-
setPrivateSalt
public void setPrivateSalt(ByteSource privateSalt)
Description copied from interface:ConfigurableHashService
Sets the 'private' (internal) salt to be paired with a 'public' (random or supplied) salt during hash computation.- Specified by:
setPrivateSalt
in interfaceConfigurableHashService
- Parameters:
privateSalt
- the 'private' internal salt to be paired with a 'public' (random or supplied) salt during hash computation.
-
getPrivateSalt
public ByteSource getPrivateSalt()
-
setHashIterations
public void setHashIterations(int count)
Description copied from interface:ConfigurableHashService
Sets the number of hash iterations that will be performed during hash computation.- Specified by:
setHashIterations
in interfaceConfigurableHashService
- Parameters:
count
- the number of hash iterations that will be performed during hash computation.
-
getHashIterations
public int getHashIterations()
-
setRandomNumberGenerator
public void setRandomNumberGenerator(RandomNumberGenerator rng)
Description copied from interface:ConfigurableHashService
Sets a source of randomness used to generate public salts that will in turn be used during hash computation.- Specified by:
setRandomNumberGenerator
in interfaceConfigurableHashService
- Parameters:
rng
- a source of randomness used to generate public salts that will in turn be used during hash computation.
-
getRandomNumberGenerator
public RandomNumberGenerator getRandomNumberGenerator()
-
isGeneratePublicSalt
public boolean isGeneratePublicSalt()
Returnstrue
if a public salt should be randomly generated and used to compute a hash if aHashRequest
does not specify a salt,false
otherwise. The default value isfalse
but should definitely be set totrue
if theHashService
instance is being used for password hashing. NOTE: this property only has an effect if aprivateSalt
is NOT configured. If a private salt has been configured and a request does not provide a salt, a random salt will always be generated to protect the integrity of the private salt (without a public salt, the private salt would be exposed as-is, which is undesirable).- Returns:
true
if a public salt should be randomly generated and used to compute a hash if aHashRequest
does not specify a salt,false
otherwise.
-
setGeneratePublicSalt
public void setGeneratePublicSalt(boolean generatePublicSalt)
Sets whether or not a public salt should be randomly generated and used to compute a hash if aHashRequest
does not specify a salt. The default value isfalse
but should definitely be set totrue
if theHashService
instance is being used for password hashing. NOTE: this property only has an effect if aprivateSalt
is NOT configured. If a private salt has been configured and a request does not provide a salt, a random salt will always be generated to protect the integrity of the private salt (without a public salt, the private salt would be exposed as-is, which is undesirable).- Parameters:
generatePublicSalt
- whether or not a public salt should be randomly generated and used to compute a hash if aHashRequest
does not specify a salt.
-
-