Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the Shiro's SaltedAuthenticationInfo?

Tags:

java

salt

shiro

I work on an authentication component for my application. I'm using the Apache Shiro API with salted password.

I create a new user with the salt like in this example :

ByteSource salt = randomNumberGenerator.nextBytes(32);      
byte[] byteTabSalt = salt.getBytes();   
String strSalt = byteArrayToHexString(byteTabSalt);         
String hashedPasswordBase64 = new Sha256Hash(inPassword, salt, 512).toBase64();

But I'dont understand how I am suppose to use the salt to auhtenticate a user in the doGetAuthenticationInfo method. My method must return a SaltedAuthenticatedInfo but I don't understand how I'm suppose to create it.

I don't understand the link between the Credential Matcher and the SaltedAuthenticateInfo.

Do I have to inform a credential matcher when I create password salts ?

Thanks for your help.

like image 491
Fred37b Avatar asked Sep 10 '12 15:09

Fred37b


1 Answers

SaltedAuthenticationInfo

SaltedAuthenticationInfo is an interface. The Shiro API provides a number of default implementations for convenience. As much as possible try to use one of the default implementations; avoid creating your own.
I suggest SimpleAuthenticationInfo which implements more than just SaltedAuthenticationInfo but will probably suffice for your purposes.
See org.apache.shiro.authc.SimpleAuthenticationInfo for more information.

If you absolutely need to implement your own SaltedAuthenticationInfo, you should follow the documentation carefully.
See org.apache.shiro.authc.AuthenticationInfo and org.apache.shiro.authc.SaltedAuthenticationInfo for more information.

HashedCredentialMatcher

boolean doCredentialsMatch(AuthenticationToken, AuthenticationInfo) actually takes care of the authentication logic.
This method takes the user-submitted credentials in the form of an AuthenticationToken and compares them to the previously stored credentials in the form of AuthenticationInfo.
You have to make sure that you pass all the necessary information to HashCredentialMatcher first though (iterations, algorithm, and a salt in the SaltedAuthenticationInfo).

pseudo-example use,

final int iterations = 50000;

AuthenticationToken authToken = ...;
SaltedAuthenticationInfo saltedAuthInfo = ...;

HashedCredentialsMatcher authenticator = 
     new HashedCredentialsMatcher(Sha256Hash.ALGORITHM_NAME);
authenticator.setHashIterations(iterations);

final boolean successfulAuthentication = 
     authenticator.doCredentialsMatch(authToken, saltedAuthInfo);

See org.apache.shiro.authc.credential.HashedCredentialsMatcher for more information.

Other security notes

  • Salt length
    256-bit salt looks good. With a salt that large you minimize the risk of any two users sharing the same salt. Keep in mind when picking a salt length that the Birthday Paradox comes into play.

  • Number of iterations
    As a rule of thumb you should never use less than 10,000. You currently use 512,

    String hashedPasswordBase64 = new Sha256Hash(inPassword, salt, 512).toBase64();
    

    Most hashing algorithms are extremely fast (sha256 included), you don't want to do any would-be hackers any favors. The more iterations you use the slower authentication will be, but it directly slows down cracking attempts as well.

    You will want to set the number of iterations as high as possible while still maintaining an acceptable responsiveness for your application. You may be surprised how high you can go.
    Personally I tend to use millions; but I am paranoid and don't mind a slight delay
    See Key Stretching for more information.

  • Personally I would avoid hard coding any of the hashing parameters (hashing algorithm, salt size, iteration count, ect)
    By hard coding these values you limit your immediate ability to adapt and respond.

    Storing these values with the hashed credentials allows you to make a more dynamic authentication where you can configure and roll out stronger algorithms in the future with relatively little effort.

    For example your default hashing algorithm may be sha256 using 50,000 iterations and a 256-bit salt. In the future though 50,000 iterations may not be enough.
    Without much fuss you would be able to change the preferred algorithm configuration to iterate 100,000 times for all new passwords. You don't have to worry about breaking old passwords because you are not changing the algorithm parameters that you stored with existing credentials. You can also use this to change the salt-size or even the algorithm altogether.

    If desired you can then make everyone to change their password; forcing users pick up the new (hopefully stronger) preferred algorithm setup.
    The Unix operating system has done this for years with /etc/shadow.

    It takes a bit more effort up front, but it's worth the investment. Strong authentication controls are critical.

like image 80
Jared Paolin Avatar answered Oct 23 '22 06:10

Jared Paolin