mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-06-10 17:45:02 +00:00

# Description of Changes Please provide a summary of the changes, including: This PR refactors multiple instances of type casting throughout the codebase by replacing them with Java's pattern matching for `instanceof`. This approach eliminates redundant type casting, improves code readability, and reduces the chances of `ClassCastException`. The changes primarily affect authentication handling, PDF processing, and certificate validation. ### Key Changes: - Replaced traditional `instanceof` checks followed by explicit casting with pattern matching. - Improved readability and maintainability of type-related operations. - Applied changes across security modules, PDF utilities, and image processing functions. This refactor does not introduce new functionality but enhances the robustness and clarity of the existing code. pending until #2818 is published --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details.
144 lines
5.1 KiB
Java
144 lines
5.1 KiB
Java
package stirling.software.SPDF.service;
|
|
|
|
import java.io.*;
|
|
import java.security.KeyStore;
|
|
import java.security.KeyStoreException;
|
|
import java.security.cert.*;
|
|
import java.util.*;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import io.github.pixee.security.BoundedLineReader;
|
|
|
|
import jakarta.annotation.PostConstruct;
|
|
|
|
@Service
|
|
public class CertificateValidationService {
|
|
private KeyStore trustStore;
|
|
|
|
@PostConstruct
|
|
private void initializeTrustStore() throws Exception {
|
|
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
trustStore.load(null, null);
|
|
loadMozillaCertificates();
|
|
}
|
|
|
|
private void loadMozillaCertificates() throws Exception {
|
|
try (InputStream is = getClass().getResourceAsStream("/certdata.txt")) {
|
|
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
|
String line;
|
|
StringBuilder certData = new StringBuilder();
|
|
boolean inCert = false;
|
|
int certCount = 0;
|
|
|
|
while ((line = BoundedLineReader.readLine(reader, 5_000_000)) != null) {
|
|
if (line.startsWith("CKA_VALUE MULTILINE_OCTAL")) {
|
|
inCert = true;
|
|
certData = new StringBuilder();
|
|
continue;
|
|
}
|
|
if (inCert) {
|
|
if ("END".equals(line)) {
|
|
inCert = false;
|
|
byte[] certBytes = parseOctalData(certData.toString());
|
|
if (certBytes != null) {
|
|
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
X509Certificate cert =
|
|
(X509Certificate)
|
|
cf.generateCertificate(
|
|
new ByteArrayInputStream(certBytes));
|
|
trustStore.setCertificateEntry("mozilla-cert-" + certCount++, cert);
|
|
}
|
|
} else {
|
|
certData.append(line).append("\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private byte[] parseOctalData(String data) {
|
|
try {
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
String[] tokens = data.split("\\\\");
|
|
for (String token : tokens) {
|
|
token = token.trim();
|
|
if (!token.isEmpty()) {
|
|
baos.write(Integer.parseInt(token, 8));
|
|
}
|
|
}
|
|
return baos.toByteArray();
|
|
} catch (Exception e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public boolean validateCertificateChain(X509Certificate cert) {
|
|
try {
|
|
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
|
|
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
List<X509Certificate> certList = Arrays.asList(cert);
|
|
CertPath certPath = cf.generateCertPath(certList);
|
|
|
|
Set<TrustAnchor> anchors = new HashSet<>();
|
|
Enumeration<String> aliases = trustStore.aliases();
|
|
while (aliases.hasMoreElements()) {
|
|
Object trustCert = trustStore.getCertificate(aliases.nextElement());
|
|
if (trustCert instanceof X509Certificate x509Cert) {
|
|
anchors.add(new TrustAnchor(x509Cert, null));
|
|
}
|
|
}
|
|
|
|
PKIXParameters params = new PKIXParameters(anchors);
|
|
params.setRevocationEnabled(false);
|
|
validator.validate(certPath, params);
|
|
return true;
|
|
} catch (Exception e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public boolean validateTrustStore(X509Certificate cert) {
|
|
try {
|
|
Enumeration<String> aliases = trustStore.aliases();
|
|
while (aliases.hasMoreElements()) {
|
|
Object trustCert = trustStore.getCertificate(aliases.nextElement());
|
|
if (trustCert instanceof X509Certificate && cert.equals(trustCert)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
} catch (KeyStoreException e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public boolean isRevoked(X509Certificate cert) {
|
|
try {
|
|
cert.checkValidity();
|
|
return false;
|
|
} catch (CertificateExpiredException | CertificateNotYetValidException e) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public boolean validateCertificateChainWithCustomCert(
|
|
X509Certificate cert, X509Certificate customCert) {
|
|
try {
|
|
cert.verify(customCert.getPublicKey());
|
|
return true;
|
|
} catch (Exception e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public boolean validateTrustWithCustomCert(X509Certificate cert, X509Certificate customCert) {
|
|
try {
|
|
// Compare the issuer of the signature certificate with the custom certificate
|
|
return cert.getIssuerX500Principal().equals(customCert.getSubjectX500Principal());
|
|
} catch (Exception e) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|