Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stock and use a shiro's salt from database

I use shiro in application for the authenticate. I use hashed password with a salt and I store them in my database like this :

    private User createUserWithHashedPassword(String inName, String inFirstName, String inLastName, String inPassword){

    ByteSource salt  = randomNumberGenerator.nextBytes(32);

    byte[] byteTabSalt  = salt.getBytes();

    String strSalt = byteArrayToHexString(byteTabSalt);

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

    return new User(inName,inFirstName,inLastName,hashedPasswordBase64,strSalt);
}

I store the salt with a String in my database. Now in my realm I want to get back my datas from the database, I use a transactionnal service for this. But my salt is a Strong so I want it to turn back as ByteSource type with the static method :

ByteSource byteSourceSalt = Util.bytes(salt); //where the salt is a String

But when I create my SaltedAuthenticationInfo it doesn't auth.

I think my problem is from my convert method :

private String byteArrayToHexString(byte[] bArray){

        StringBuffer buffer = new StringBuffer();

        for(byte b : bArray) {
            buffer.append(Integer.toHexString(b));
            buffer.append(" ");
        }

 return buffer.toString().toUpperCase();    
}

Thanks for your help.

like image 880
Fred37b Avatar asked Sep 19 '12 14:09

Fred37b


1 Answers

As mentioned in the excellent answer https://stackoverflow.com/a/20206115/603901, Shiro's DefaultPasswordService already generates unique salts for each password.

However, there is no need to implement a custom PasswordService to add a private salt (sometimes called "pepper") to the per-user salts. Private salt can be configured in shiro.ini:

[main]
hashService = org.apache.shiro.crypto.hash.DefaultHashService
hashService.hashIterations = 500000
hashService.hashAlgorithmName = SHA-256
hashService.generatePublicSalt = true
# privateSalt needs to be base64-encoded in shiro.ini but not in the Java code
hashService.privateSalt = myVERYSECRETBase64EncodedSalt
passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher

passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
passwordService.hashService = $hashService
passwordMatcher.passwordService = $passwordService

Java code for generating a matching password hash:

DefaultHashService hashService = new DefaultHashService();
hashService.setHashIterations(HASH_ITERATIONS); // 500000
hashService.setHashAlgorithmName(Sha256Hash.ALGORITHM_NAME);
hashService.setPrivateSalt(new SimpleByteSource(PRIVATE_SALT)); // Same salt as in shiro.ini, but NOT base64-encoded.
hashService.setGeneratePublicSalt(true);

DefaultPasswordService passwordService = new DefaultPasswordService();
passwordService.setHashService(hashService);
String encryptedPassword = passwordService.encryptPassword("PasswordForThisUser");

The resulting hash looks like this:

$shiro1$SHA-256$500000$An4HRyqMJlZ58utACtyGDQ==$nKbIY9Nd9vC89G4SjdnDfka49mZiesjWgDsO/4Ly4Qs=

The private salt is not stored in the database, which makes it harder to crack the passwords if an adversary gains access to a database dump.

This example was created using shiro-1.2.2

Thanks to https://github.com/Multifarious/shiro-jdbi-realm/blob/master/src/test/resources/shiro.ini for help with the syntax for shiro.ini

like image 57
Mikael Falkvidd Avatar answered Sep 27 '22 19:09

Mikael Falkvidd