From 8a50ee11be5038807cd6ac0c95c650199f878747 Mon Sep 17 00:00:00 2001 From: Anover000 <140409886+Anover000@users.noreply.github.com> Date: Fri, 2 Feb 2024 17:19:33 +0530 Subject: [PATCH] [PHEE-554] Auto generate json web test Signature in postman for bulk apis (#91) * basic x-signature util api working * raw body type inclusive * add service layer * cleanup * get private key in headers, sha3->sha --- .../org/apache/fineract/api/UtilityApi.java | 74 +++++++++++++++++++ .../fineract/service/UtilityService.java | 15 ++++ .../fineract/service/UtilityServiceImpl.java | 39 ++++++++++ 3 files changed, 128 insertions(+) create mode 100644 src/main/java/org/apache/fineract/api/UtilityApi.java create mode 100644 src/main/java/org/apache/fineract/service/UtilityService.java create mode 100644 src/main/java/org/apache/fineract/service/UtilityServiceImpl.java diff --git a/src/main/java/org/apache/fineract/api/UtilityApi.java b/src/main/java/org/apache/fineract/api/UtilityApi.java new file mode 100644 index 00000000..2b8b55b6 --- /dev/null +++ b/src/main/java/org/apache/fineract/api/UtilityApi.java @@ -0,0 +1,74 @@ +package org.apache.fineract.api; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.apache.fineract.service.UtilityService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.util.stream.Collectors; + + +@RestController +@SecurityRequirement(name = "auth") +@RequestMapping("/api/v1") +@Tag(name = "Users API") +public class UtilityApi { + + @Autowired + UtilityService utilityService; + + @PostMapping("/util/x-signature") + public ResponseEntity getXSignature( + @RequestHeader("X-CorrelationID") String correlationId, + @RequestHeader("Platform-TenantId") String tenantId, + @RequestHeader("privateKey") String privateKey, + @RequestParam(required = false) MultipartFile data, + @RequestBody(required = false) String rawData + )throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeySpecException, InvalidKeyException, IOException { + + String tobeHashed = ""; + + if(data != null && !data.isEmpty()) { + String fileContent; + try { + fileContent = readInputStreamToString(data.getInputStream()); + } catch (IOException e) { + e.printStackTrace(); + return new ResponseEntity<>("Failed to read file content", HttpStatus.INTERNAL_SERVER_ERROR); + } + tobeHashed = correlationId+":"+tenantId+":"+fileContent; + } + else if(rawData != null && !rawData.isEmpty()){ + tobeHashed = correlationId+":"+tenantId+":"+rawData; + } + else { + return new ResponseEntity<>("No file or raw data provided", HttpStatus.BAD_REQUEST); + } + + return new ResponseEntity<>(utilityService.getSignature(tobeHashed, privateKey), HttpStatus.OK); + } + + private String readInputStreamToString(InputStream inputStream) throws IOException { + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) { + return bufferedReader.lines().collect(Collectors.joining("\n")); + } + } +} diff --git a/src/main/java/org/apache/fineract/service/UtilityService.java b/src/main/java/org/apache/fineract/service/UtilityService.java new file mode 100644 index 00000000..8b94353c --- /dev/null +++ b/src/main/java/org/apache/fineract/service/UtilityService.java @@ -0,0 +1,15 @@ +package org.apache.fineract.service; + +import org.springframework.stereotype.Service; +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; + +@Service +public interface UtilityService { + + String getSignature(String toBeHashed, String privateKeyString)throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException; +} diff --git a/src/main/java/org/apache/fineract/service/UtilityServiceImpl.java b/src/main/java/org/apache/fineract/service/UtilityServiceImpl.java new file mode 100644 index 00000000..11bfc166 --- /dev/null +++ b/src/main/java/org/apache/fineract/service/UtilityServiceImpl.java @@ -0,0 +1,39 @@ +package org.apache.fineract.service; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; +import org.springframework.stereotype.Service; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.spec.EncodedKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; + +@Service +public class UtilityServiceImpl implements UtilityService{ + @Override + public String getSignature(String tobeHashed, String privateKeyString)throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { + String hashData = (new DigestUtils("SHA-256")).digestAsHex(tobeHashed); + + Cipher cipher = Cipher.getInstance("RSA"); + PrivateKey publicKey = getPrivateKeyFromString(privateKeyString); + cipher.init(1, publicKey); + byte[] cipherText = cipher.doFinal(hashData.getBytes(StandardCharsets.UTF_8)); + + return Base64.encodeBase64String(cipherText); + } + + public static PrivateKey getPrivateKeyFromString(String key) throws NoSuchAlgorithmException, InvalidKeySpecException { + byte[] keyBytes = Base64.decodeBase64(key); + EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return keyFactory.generatePrivate(keySpec); + } +}