I have a simple Hash class used to learn the ins-outs of the Password4j library.
However, I seem to be getting different results with the same inputs--I call Password.hash(...) with same clear text, one time with autogenerated salt that I save, the next time what that saved salt, but the hashed password bytes differ.
If anyone's had experience with this library and using it for Argon2 hashing, I'd really appreciate pointers/thoughts/etc so I can figure out what I'm doing wrong.
ps24j.properties (I've verified that these values are being used by the library):
# Uncomment when everything's working
#global.banner=false
# Silly, I know. But let's have some fun. Let your hair down a little, huh?!
global.pepper=NowIsTheTimeForAllGoodMenToComeToTheAidOfTheirCountry
global.random.strong=false
# Amount of memory (in kibibytes) to use.
# 64 mb
hash.argon2.memory=65536
# Number of iterations to perform.
hash.argon2.iterations=3
# Degree of parallelism (number of threads to be used in the computation).
hash.argon2.parallelism=4
# Desired length of the final derived key. Using 16 for easier manual visual compare
hash.argon2.length=16
# Desired type of the algorithm. Possible values are d for Argon2d, i for Argon2i, or id for Argon2id.
hash.argon2.type=id
# Defines the version of the algorithm to use.
hash.argon2.version=19
Code used to generate a Hash with random salt, and to reproduce results by specifying salt (I've verified that 'pepper' is what I have in the properties file; HashResults just contains byte[] for hash and salt):
public HashResults generateHash( String clearText )
{
String pepper = PepperGenerator.get();
Hash hash = Password
.hash( clearText )
.addRandomSalt()
.addPepper( pepper )
.withArgon2();
return new HashResults()
.setSaltBytes( hash.getSaltBytes() )
.setHashBytes( hash.getResultAsBytes() );
}
public HashResults generateHash( String clearText, byte[] salt )
{
String pepper = PepperGenerator.get();
Hash hash = Password
.hash( clearText )
.addSalt( salt )
.addPepper( pepper )
.withArgon2();
return new HashResults()
.setSaltBytes( hash.getSaltBytes() )
.setHashBytes( hash.getResultAsBytes() );
}
Quickie test:
HashResults hashResults = hashing.generateHash( "b00ya" );
System.out.println("HASH0: " + Arrays.toString( hashResults.getHashBytes() ) );
System.out.println("SALT0: " + Arrays.toString( hashResults.getSaltBytes() ) );
HashResults hashResults2 = hashing.generateHash( "b00ya", hashResults.getSaltBytes() );
System.out.println("HASH1: " + Arrays.toString( hashResults2.getHashBytes() ) );
System.out.println("SALT1: " + Arrays.toString( hashResults2.getSaltBytes() ) );
Results (I know, kinda silly to post these byte arrays here, but figured why not):
HASH0: [36, 97, 114, 103, 111, 110, 50, 105, 100, 36, 118, 61, 49, 57, 36, 109, 61, 54, 53, 53, 51, 54, 44, 116, 61, 51, 44, 112, 61, 52, 36, 86, 69, 98, 51, 90, 111, 114, 114, 73, 102, 107, 66, 48, 119, 115, 83, 65, 86, 113, 57, 119, 89, 116, 72, 81, 98, 117, 112, 75, 122, 53, 111, 101, 122, 71, 109, 56, 66, 48, 101, 108, 121, 85, 98, 112, 104, 68, 47, 69, 106, 88, 57, 116, 71, 81, 78, 51, 78, 43, 110, 53, 82, 105, 114, 106, 114, 107, 69, 82, 120, 52, 74, 80, 112, 43, 120, 56, 83, 77, 71, 107, 107, 98, 67, 103, 103, 36, 49, 83, 81, 54, 78, 50, 68, 113, 79, 109, 43, 99, 101, 97, 84, 111, 77, 80, 82, 50, 79, 65]
HASH1: [36, 97, 114, 103, 111, 110, 50, 105, 100, 36, 118, 61, 49, 57, 36, 109, 61, 54, 53, 53, 51, 54, 44, 116, 61, 51, 44, 112, 61, 52, 36, 86, 69, 98, 118, 118, 55, 49, 109, 55, 55, 43, 57, 55, 55, 43, 57, 73, 101, 43, 47, 118, 81, 72, 118, 118, 55, 48, 76, 69, 103, 70, 97, 55, 55, 43, 57, 55, 55, 43, 57, 55, 55, 43, 57, 82, 48, 72, 118, 118, 55, 51, 118, 118, 55, 48, 114, 80, 109, 104, 55, 77, 101, 43, 47, 118, 101, 43, 47, 118, 82, 48, 101, 55, 55, 43, 57, 74, 82, 118, 118, 118, 55, 48, 81, 55, 55, 43, 57, 69, 106, 88, 118, 118, 55, 51, 118, 118, 55, 49, 107, 68, 101, 43, 47, 118, 100, 43, 110, 55, 55, 43, 57, 71, 79, 43, 47, 118, 101, 43, 47, 118, 101, 43, 47, 118, 81, 82, 72, 72, 103, 107, 43, 55, 55, 43, 57, 55, 55, 43, 57, 55, 55, 43, 57, 73, 119, 98, 118, 118, 55, 49, 71, 119, 111, 73, 36, 112, 104, 48, 54, 105, 74, 112, 82, 88, 117, 118, 66, 89, 121, 67, 82, 113, 51, 69, 89, 116, 65]
SALT0: [84, 70, -17, -65, -67, 102, -17, -65, -67, -17, -65, -67, 33, -17, -65, -67, 1, -17, -65, -67, 11, 18, 1, 90, -17, -65, -67, -17, -65, -67, -17, -65, -67, 71, 65, -17, -65, -67, -17, -65, -67, 43, 62, 104, 123, 49, -17, -65, -67, -17, -65, -67, 29, 30, -17, -65, -67, 37, 27, -17, -65, -67, 16, -17, -65, -67, 18, 53, -17, -65, -67, -17, -65, -67, 100, 13, -17, -65, -67, -33, -89, -17, -65, -67, 24, -17, -65, -67, -17, -65, -67, -17, -65, -67, 4, 71, 30, 9, 62, -17, -65, -67, -17, -65, -67, -17, -65, -67, 35, 6, -17, -65, -67, 70, -62, -126]
SALT1: [84, 70, -17, -65, -67, 102, -17, -65, -67, -17, -65, -67, 33, -17, -65, -67, 1, -17, -65, -67, 11, 18, 1, 90, -17, -65, -67, -17, -65, -67, -17, -65, -67, 71, 65, -17, -65, -67, -17, -65, -67, 43, 62, 104, 123, 49, -17, -65, -67, -17, -65, -67, 29, 30, -17, -65, -67, 37, 27, -17, -65, -67, 16, -17, -65, -67, 18, 53, -17, -65, -67, -17, -65, -67, 100, 13, -17, -65, -67, -33, -89, -17, -65, -67, 24, -17, -65, -67, -17, -65, -67, -17, -65, -67, 4, 71, 30, 9, 62, -17, -65, -67, -17, -65, -67, -17, -65, -67, 35, 6, -17, -65, -67, 70, -62, -126]
I think this behaviour is fixed in 1.8.1: https://github.com/Password4j/password4j/issues/143