Validate certificate inputs for cert signing (#5191)

## Summary
- validate required certificate inputs before loading keystores to
prevent null dereferences
- surface clear errors for missing PEM, PKCS12/PFX, and JKS uploads
during PDF signing
- add a unit test covering the missing PKCS12/PFX keystore scenario

## Testing
- ./gradlew :stirling-pdf:test --tests
stirling.software.SPDF.controller.api.security.CertSignControllerTest

------
[Codex
Task](https://chatgpt.com/codex/tasks/task_b_6934c8803d648328bf76b72a4f689c60)
This commit is contained in:
Anthony Stirling
2025-12-13 17:42:12 +00:00
committed by GitHub
parent 5f54308d2b
commit 371d816ce7
2 changed files with 52 additions and 2 deletions
@@ -191,6 +191,12 @@ public class CertSignController {
switch (certType) {
case "PEM":
privateKeyFile =
validateFilePresent(
privateKeyFile, "PEM private key", "private key file is required");
certFile =
validateFilePresent(
certFile, "PEM certificate", "certificate file is required");
ks = KeyStore.getInstance("JKS");
ks.load(null);
PrivateKey privateKey = getPrivateKeyFromPEM(privateKeyFile.getBytes(), password);
@@ -200,10 +206,16 @@ public class CertSignController {
break;
case "PKCS12":
case "PFX":
p12File =
validateFilePresent(
p12File, "PKCS12 keystore", "PKCS12/PFX keystore file is required");
ks = KeyStore.getInstance("PKCS12");
ks.load(p12File.getInputStream(), password.toCharArray());
break;
case "JKS":
jksfile =
validateFilePresent(
jksfile, "JKS keystore", "JKS keystore file is required");
ks = KeyStore.getInstance("JKS");
ks.load(jksfile.getInputStream(), password.toCharArray());
break;
@@ -251,6 +263,17 @@ public class CertSignController {
GeneralUtils.generateFilename(pdf.getOriginalFilename(), "_signed.pdf"));
}
private MultipartFile validateFilePresent(
MultipartFile file, String argumentName, String errorDescription) {
if (file == null || file.isEmpty()) {
throw ExceptionUtils.createIllegalArgumentException(
"error.invalidArgument",
"Invalid argument: {0}",
argumentName + " - " + errorDescription);
}
return file;
}
private PrivateKey getPrivateKeyFromPEM(byte[] pemBytes, String password)
throws IOException, OperatorCreationException, PKCSException {
try (PEMParser pemParser =