6

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.

Fred37b
  • 822
  • 2
  • 10
  • 29
  • 2
    512 is [*way* too low for the iteration count](http://security.stackexchange.com/questions/3959/recommended-of-iterations-when-using-pkbdf2-sha256). I think the lowest *anyone* recommends is 1000, and 10,000+ is more common. Also, you don't need to convert the salt to string. – Brendan Long Sep 11 '12 at 15:36
  • I convert my salt to string for putting it in my database. I will use a greater number for the iterations. Thanks for yours answers. – Fred37b Sep 12 '12 at 07:21

2 Answers2

7

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.

Jared Paolin
  • 247
  • 1
  • 3
  • 1
    Thanks for your help. I think my problem is I don't use the same Credentials Matcher's params. I don't give the right algorithm name to the credential. I will test this. – Fred37b Sep 12 '12 at 07:30
  • @Fred37b no problem. As noted above, make sure you set all the appropriate parameters on the `HashedCredentialMatcher`, including the number of iterations. – Jared Paolin Sep 12 '12 at 07:46
  • My method buildAuthenticationInfo(String username, char[] password) which create a AuthenticationInfo or SaltedAuthenticationInfo does not work at all. I don't create a correct AuthenticationInfo object. – Fred37b Sep 12 '12 at 08:58
  • am also having a problem with my implementation using shiro 1.2.0. since my methods are somehow different from what is discussed here i created a new thead here: http://stackoverflow.com/questions/12896592/having-trouble-with-apache-shiro-saltedauthentication-hashprovidedcredentials-no – black sensei Oct 15 '12 at 13:28
0

My error was to not create correctly the AuthenticationInfo which was compare the AuthenticationToken. So in the doGetAuthenticationInfo method of my own realm I do this :

Object principal   = arg0.getPrincipal();
Object credentials = arg0.getCredentials();
String realmName   = this.getName(); // to get the realm name

SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, credentials, realmName);

CredentialsMatcher credentialsMatcher = this.getCredentialsMatcher();
boolean successfulAuthentication = credentialsMatcher.doCredentialsMatch(arg0, simpleAuthenticationInfo);

And so the boolean successfulAuthentication is true. But I don't understand what's the difference between CredentialsMatcher and HashedCredentialsMatcher because that one was to false. I have to read Javadoc.

Fred37b
  • 822
  • 2
  • 10
  • 29