我正在使用 DSS 库使用 PAdES-LT 级别对 PDF 进行签名。我已经尝试过 B 级和 T 级,效果很好。一开始我遇到了 LT 级别的问题,因为它仅使用在线验证器验证为 T,所以我试图找到问题,但没有运气。我使用外部服务器进行哈希签名以及 TSA。
List<CertificateResponse> certificateResponses = client.getCertificateChain();
List<Certificate> certificates = new ArrayList<>();
for (CertificateResponse certificateResponse : certificateResponses) {
byte[] certificate = Base64.getDecoder().decode(certificateResponse.certificate());
X509Certificate cert = (X509Certificate) CertificateFactory
.getInstance("X.509").generateCertificate(new ByteArrayInputStream(certificate));
certificates.add(cert);
}
List<CertificateToken> certificateTokens = certificates.stream()
.map(c -> new CertificateToken((X509Certificate) c)).toList();
CommonCertificateVerifier certificateVerifier = new CommonCertificateVerifier();
CommonTrustedCertificateSource certificateSource = new CommonTrustedCertificateSource();
for (CertificateToken certificateToken : certificateTokens) {
certificateSource.addCertificate(certificateToken);
}
OnlineCRLSource onlineCRLSource = new OnlineCRLSource();
onlineCRLSource.setDataLoader(new CommonsDataLoader());
certificateVerifier.setCrlSource(onlineCRLSource);
OnlineOCSPSource onlineOCSPSource = new OnlineOCSPSource();
onlineOCSPSource.setDataLoader(new OCSPDataLoader());
onlineOCSPSource.setNonceSource(new SecureRandomNonceSource());
certificateVerifier.setOcspSource(onlineOCSPSource);
certificateVerifier.setTrustedCertSources(certificateSource);
certificateVerifier.setRevocationDataVerifier(RevocationDataVerifier.createDefaultRevocationDataVerifier());
certificateVerifier.setCheckRevocationForUntrustedChains(true);
PAdESService service = new PAdESService(certificateVerifier);
service.setTspSource(tspSource);
DSSDocument toSignDocument = new InMemoryDocument(pdf);
PAdESSignatureParameters parameters = new PAdESSignatureParameters();
parameters.setDigestAlgorithm(DigestAlgorithm.SHA256);
parameters.setSignatureLevel(SignatureLevel.PAdES_BASELINE_LT);
parameters.setGenerateTBSWithoutCertificate(false);
parameters.setSigningCertificate(certificateTokens.get(0));
parameters.setCertificateChain(certificateTokens);
parameters.setCheckCertificateRevocation(true);
ToBeSigned dataToSign = service.getDataToSign(toSignDocument, parameters);
final SigningRequest signingRequest = new SigningRequest();
signingRequest.setHashSignatures(List.of(new HashSignature("id-1", Hasher.hash(dataToSign.getBytes()).bytes())));
final SigningResult signingResult = client.sign(signingRequest);
SignatureValue signatureValue = new SignatureValue(SignatureAlgorithm.RSA_SHA256,
Base64.getDecoder().decode(signingResult.signature()));
DSSDocument signedDocument = service.signDocument(toSignDocument, parameters, signatureValue);
我收到以下错误:
2023-08-24T17:43:04.200+02:00 WARN 38245 --- [ main] e.e.e.d.s.x.SignatureIntegrityValidator : Determining signing certificate from certificate candidates list failed: [Best candidate validation failed : Unable to validate CMS Signature : can't create content verifier: exception on setup: java.security.InvalidKeyException: Supplied key (null) is not a RSAPublicKey instance]
eu.europa.esig.dss.exception.IllegalInputException: Signing certificate token was not found! Unable to verify its validity range. Use method setSignWithNotYetValidCertificate(true) to skip the check.
at eu.europa.esig.dss.signature.SignatureRequirementsChecker.assertSigningCertificateIsYetValid(SignatureRequirementsChecker.java:104)
at eu.europa.esig.dss.signature.SignatureRequirementsChecker.assertSigningCertificateIsValid(SignatureRequirementsChecker.java:88)
at eu.europa.esig.dss.cades.signature.CAdESLevelBaselineT.extendSignerInformation(CAdESLevelBaselineT.java:99)
at eu.europa.esig.dss.cades.signature.CAdESLevelBaselineT.extendCMSSignatures(CAdESLevelBaselineT.java:84)
at eu.europa.esig.dss.cades.signature.CAdESSignatureExtension.extendCMSSignatures(CAdESSignatureExtension.java:170)
at eu.europa.esig.dss.cades.signature.CAdESSignatureExtension.extendCMSSignatures(CAdESSignatureExtension.java:122)
at eu.europa.esig.dss.cades.signature.CAdESLevelBaselineT.extendCMSSignatures(CAdESLevelBaselineT.java:52)
at eu.europa.esig.dss.pades.signature.ExternalCMSService.buildCMSSignedData(ExternalCMSService.java:202)
at eu.europa.esig.dss.pades.signature.PAdESService.generateCMSSignedData(PAdESService.java:246)
at eu.europa.esig.dss.pades.signature.PAdESService.signDocument(PAdESService.java:209)
签名中似乎没有添加证书。以前有人遇到过同样的问题吗?我也希望有一个 LT 级别的工作示例。
我也有 DSS 集成问题,我们可以联系吗?