Skip to content

Example With SHA-256 In Spring Boot#

Example With SHA-256 In Spring Boot#

  • In this example we will use SHA-256, there is a SHA-512 which use newer hashing algorithms and usually used in blockchain, but in require more bandwidth to store and transmit data. So in this example which is not blockchain I recommend we use SHA-256 because in recent It is lightweight and still secure for us.

Controller#

  • Let's create an controller with some apis as below:
Sha256Controller.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.springboot.security.hash.app.controller;

import com.springboot.security.hash.app.model.DataRequest;
import com.springboot.security.hash.app.model.MatchDataRequest;
import com.springboot.security.hash.app.service.HashSha256Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Sha256Controller {

    @Autowired
    private HashSha256Service hashSha256Service;

    @RequestMapping(method = RequestMethod.POST, path = "v1/cipher/hash/sha256", produces = MediaType.TEXT_PLAIN_VALUE)
    public ResponseEntity<String> hashSHA256(@RequestBody DataRequest inputData) {
        return new ResponseEntity<>(this.hashSha256Service.hashSHA256(inputData.getData()), HttpStatus.CREATED);
    }

    @RequestMapping(method = RequestMethod.POST, path = "v1/cipher/hash/sha256/check", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Boolean> checkMatchSha256(@RequestBody MatchDataRequest inputData) {
        return new ResponseEntity<>(this.hashSha256Service.isSHA256Match(inputData.getRawData(), inputData.getHashedData()), HttpStatus.OK);
    }

}
  • 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.
DataRequest.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package com.springboot.security.hash.app.model;

import org.springframework.lang.NonNull;

public class DataRequest {

    private String data;

    @NonNull
    public String getData() {
        return data;
    }

    public void setData(@NonNull String data) {
        this.data = data;
    }

}
MatchDataRequest.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.springboot.security.hash.app.model;

public class MatchDataRequest {

    private String rawData;
    private String hashedData;

    public String getRawData() {
        return rawData;
    }

    public void setRawData(String rawData) {
        this.rawData = rawData;
    }

    public String getHashedData() {
        return hashedData;
    }

    public void setHashedData(String hashedData) {
        this.hashedData = hashedData;
    }
}
  • Then we also need to create a model that loads environment variables into a spring bean using @ConfigurationProperties as below.
HashConfigProperties.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package com.springboot.security.hash.app.model;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "hash")
public class HashConfigProperties {

    private Sha256 sha256;

    public Sha256 getSha256() {
        return sha256;
    }

    public void setSha256(Sha256 sha256) {
        this.sha256 = sha256;
    }
}
Sha256.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package com.springboot.security.hash.app.model;

public class Sha256 {

    private String salt;

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }
}

Service#

  • In Spring Boot we don't need to add more any dependency to do the Hashing with SHA-256, we will use MessageDigest with hash algorithm is SHA-256 that Spring Boot provided. This class provide a method getInstance with input is the name of hash algorithm to create MessageDigest.
  • What is the Message Digest? More information.
  • Now let's create HashSha256Service and add two methods hashSHA256 and isSHA256Match below for hashing data and checking the hashed data with the given hashed by using MessageDigest.isEqual.
HashSha256Service.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.springboot.security.hash.app.service;

import com.springboot.security.hash.app.model.HashConfigProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

@Service
public class HashSha256Service {

    private static final String HASH_ALGORITHM_SHA_256 = "SHA-256";

    @Autowired
    private HashConfigProperties hashConfigProperties;

    public String hashSHA256(String data) {
        byte[] hash = this.hash(data);
        return DatatypeConverter.printHexBinary(hash);
    }

    public boolean isSHA256Match(String data, String hashedData) {
        byte[] digested = DatatypeConverter.parseHexBinary(hashedData);
        byte[] reHashData = this.hash(data);
        return MessageDigest.isEqual(digested, reHashData);
    }

    private byte[] hash(String data) {
        try {
            String dataWithSalt = hashConfigProperties.getSha256().getSalt().concat(data);
            MessageDigest messageDigest = MessageDigest.getInstance(HASH_ALGORITHM_SHA_256);
            return messageDigest.digest(dataWithSalt.getBytes(StandardCharsets.UTF_8));
        } catch (Exception ex) {
            throw new RuntimeException("Can not hash Data", ex);
        }
    }

}
  • Then we will hash the data together with the salt that we load from the application.yml into the HashConfigProperties component using @ConfigurationProperties. The Salt will be any string, see the example below.
application.yml
1
2
3
hash:  
    sha256:  
        salt: 70DD29E1BE48BBA013A2E7EDF6F10861F82DD9C9C0C2A1419C69D3CD74513452

Testing#

  • Now, run the Spring Boot project and try to call api v1/cipher/hash/sha256 for testing hasing data. Then you will receive the result as below

 #zoom

  • Then with the hash result above, we will use it to check with the original data by calling api v1/cipher/hash/sha256/check. Then you will see the original data and hashed data are matched.

 #zoom

  • 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.

 #zoom

See Also#

References#