In this example we will use Password-Based Key Derivation Function 2 (Pbkdf2) which is a pretty easy slow-hashing function that performs an HMAC(Hashed Message Authentication Code) as many times as specified by an iterations argument.
The Pbkdf2 has the brilliant feature of having a configurable strength. This means that as computers increase in strength, we can slow down the algorithm by changing the inputs.
We will need to create 2 simple models for request body as below. One is used for hashing data and the other one is used for checking raw data and hashed data.
packagecom.springboot.security.hash.app.service;importcom.springboot.security.hash.app.model.HashConfigProperties;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importjavax.crypto.SecretKeyFactory;importjavax.crypto.spec.PBEKeySpec;importjavax.xml.bind.DatatypeConverter;importjava.nio.charset.StandardCharsets;importjava.security.MessageDigest;@ServicepublicclassPbkdf2Service{privatestaticfinalStringHASH_ALGORITHM_PBKDF2_512=SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA512.name();@AutowiredprivateHashConfigPropertieshashConfigProperties;publicStringhashPbkdf2(Stringdata){try{byte[]hash=this.hash(data);returnDatatypeConverter.printHexBinary(hash);}catch(Exceptionex){thrownewRuntimeException("Can not hash Data",ex);}}publicbooleanisPbkdf2Match(Stringdata,StringhashedData){byte[]digested=DatatypeConverter.parseHexBinary(hashedData);byte[]reHashData=this.hash(data);returnMessageDigest.isEqual(digested,reHashData);}privatebyte[]hash(Stringdata){try{PBEKeySpecpbeKeySpec=newPBEKeySpec(data.toCharArray(),hashConfigProperties.getPbkdf2().getSalt().getBytes(StandardCharsets.UTF_8),hashConfigProperties.getPbkdf2().getIterations(),hashConfigProperties.getPbkdf2().getHashWidth());SecretKeyFactorysecretKeyFactory=SecretKeyFactory.getInstance(HASH_ALGORITHM_PBKDF2_512);returnsecretKeyFactory.generateSecret(pbeKeySpec).getEncoded();}catch(Exceptionex){thrownewRuntimeException("Can not hash Data",ex);}}publicenumSecretKeyFactoryAlgorithm{PBKDF2WithHmacSHA1,PBKDF2WithHmacSHA256,PBKDF2WithHmacSHA512}}
In Spring Boot we don't need to add more any dependency to do the Hashing with Pbkdf2, we will use SecretKeyFactory with hash algorithm is PBKDF2WithHmacSHA512 that Spring Boot provided.
There are 3 hash algorithms that we can use for SecretKeyFactory with Pbkdf2:
> - PBKDF2WithHmacSHA1
> - PBKDF2WithHmacSHA256
> - PBKDF2WithHmacSHA512
After you have initialized the SecretKeyFactory, Then you need to create a PBEKeySpec with 4 parameters as below:
Param 1: the byte array of your data.
Param 2: the byte array of salt
Param 3: the number of iterations (185000 or more)
Param 4: the number of hash length (128, 256, 1024)
The salt, iterations and hashWidth will be load from the application.yml into the HashConfigProperties component using @ConfigurationProperties. The Salt will be any string, see the example below.
Now, run the Spring Boot project and try to call api v1/cipher/hash/pbkdf2 for testing hasing data. Then you will receive the result as below
Then with the hash result above, we will use it to check with the original data by calling api v1/cipher/hash/pbkdf2/check. Then you will see the original data and hashed data are matched.
Now let's try to change a single character in original data and check again with hashed data. Then you will see the api return failed.