117 lines
4.5 KiB
Java
117 lines
4.5 KiB
Java
package com.billpaymentservice.bbps.util;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Base64;
|
|
import java.util.zip.CRC32;
|
|
|
|
import javax.crypto.Cipher;
|
|
import javax.crypto.spec.IvParameterSpec;
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.stereotype.Component;
|
|
|
|
@Component
|
|
public class EncryptionUtil {
|
|
private static final Logger LOGGER = LoggerFactory.getLogger(EncryptionUtil.class);
|
|
|
|
/**
|
|
* Encrypts plaintext using AES/CBC/PKCS5Padding.
|
|
* If the provided key length is not 16/24/32 bytes it will be adjusted to 16 bytes (padded/truncated).
|
|
*/
|
|
public String encryptMData(String plaintext, String encryptKey) {
|
|
try {
|
|
byte[] keyBytes = normalizeKey(encryptKey);
|
|
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
|
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
|
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
|
|
|
|
byte[] ivBytes = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
|
|
byte[] encryptedData = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
|
|
|
|
byte[] combinedBytes = new byte[ivBytes.length + encryptedData.length];
|
|
System.arraycopy(ivBytes, 0, combinedBytes, 0, ivBytes.length);
|
|
System.arraycopy(encryptedData, 0, combinedBytes, ivBytes.length, encryptedData.length);
|
|
return Base64.getEncoder().encodeToString(combinedBytes);
|
|
} catch (Exception e) {
|
|
LOGGER.error("Exception in encrypt() : encryptMData- {} : Message- {}", encryptKey, e.getMessage());
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private byte[] normalizeKey(String encryptKey) {
|
|
if (encryptKey == null) {
|
|
encryptKey = "";
|
|
}
|
|
byte[] bytes = encryptKey.getBytes(StandardCharsets.UTF_8);
|
|
int targetLen = 16; // AES-128
|
|
if (bytes.length == targetLen || bytes.length == 24 || bytes.length == 32) {
|
|
return bytes;
|
|
}
|
|
byte[] normalized = new byte[targetLen];
|
|
for (int i = 0; i < targetLen; i++) {
|
|
if (i < bytes.length) {
|
|
normalized[i] = bytes[i];
|
|
} else {
|
|
normalized[i] = 0; // pad with zeros
|
|
}
|
|
}
|
|
return normalized;
|
|
}
|
|
|
|
/**
|
|
* Decrypts data encrypted by encryptMData: Base64(iv + ciphertext) with AES/CBC/PKCS5Padding
|
|
*/
|
|
public String decryptMData(String base64Payload, String encryptKey) {
|
|
if (base64Payload == null) return null;
|
|
try {
|
|
byte[] combined = Base64.getDecoder().decode(base64Payload);
|
|
// IV is first 16 bytes for AES
|
|
if (combined.length < 16) {
|
|
LOGGER.warn("Encrypted payload too short to contain IV");
|
|
return null;
|
|
}
|
|
byte[] iv = new byte[16];
|
|
System.arraycopy(combined, 0, iv, 0, 16);
|
|
byte[] cipherText = new byte[combined.length - 16];
|
|
System.arraycopy(combined, 16, cipherText, 0, cipherText.length);
|
|
|
|
byte[] keyBytes = normalizeKey(encryptKey);
|
|
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
|
|
|
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
|
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
|
|
|
|
byte[] plain = cipher.doFinal(cipherText);
|
|
return new String(plain, StandardCharsets.UTF_8);
|
|
} catch (Exception ex) {
|
|
LOGGER.error("Error decrypting payload: {}", ex.getMessage());
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Compute CRC32 checksum value for the provided input string and return the numeric value as String
|
|
*/
|
|
public String getChecksumCRC32(String input) {
|
|
if (input == null) input = "";
|
|
try (InputStream is = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8))) {
|
|
CRC32 crc = new CRC32();
|
|
byte[] buffer = new byte[1024];
|
|
int len;
|
|
while ((len = is.read(buffer)) != -1) {
|
|
crc.update(buffer, 0, len);
|
|
}
|
|
long value = crc.getValue();
|
|
LOGGER.debug("Computed CRC32: {} for input: {}", value, input);
|
|
return String.valueOf(value);
|
|
} catch (IOException e) {
|
|
LOGGER.error("Error computing CRC32: {}", e.getMessage());
|
|
return null;
|
|
}
|
|
}
|
|
} |