Anonymous
Проверка PDF не прошла
Сообщение
Anonymous » 17 янв 2025, 14:05
Я использую iText для цифровой подписи PDF-файлов, и мы используем не популярный во всем мире алгоритм под названием SM3WITHSM2. Однако сейчас невозможно проверить подписанный файл, и я не уверен, в чем проблема.
Код: Выделить всё
public DeferredSignResult machineSign(MachineSignParam machineSignParam) throws Exception {
CipherMachineService provider = getProvider();
URL pdfUrl = machineSignParam.getPdfUrl();
URL sealUrl = machineSignParam.getSealUrl();
Rectangle rectangle = machineSignParam.getRectangle();
int page = machineSignParam.getPage();
int containerNum = machineSignParam.getContainerNum();
Certificate[] certificates = machineSignParam.getCertificates();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PdfReader pdfReader = new PdfReader(pdfUrl);
PdfStamper pdfSigner = PdfStamper.createSignature(pdfReader, byteArrayOutputStream, '\0', null, true);
PdfSignatureAppearance pdfSignatureAppearance = pdfSigner.getSignatureAppearance();
Image imageData = Image.getInstance(sealUrl);
pdfSignatureAppearance.setReason("");
pdfSignatureAppearance.setLocation("");
pdfSignatureAppearance.setContact("");
pdfSignatureAppearance.setLayer2Text("");
pdfSignatureAppearance.setLayer4Text("");
pdfSignatureAppearance.setSignatureCreator("");
pdfSignatureAppearance.setOpacity(1F);
pdfSignatureAppearance.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);
pdfSignatureAppearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
pdfSignatureAppearance.setImage(imageData);
pdfSignatureAppearance.setVisibleSignature(rectangle, page, IdUtil.fastSimpleUUID());
ExternalSignatureContainer externalSignatureContainer;
if (provider instanceof Fisherman) {
externalSignatureContainer = new FisherManSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED,
containerNum, certificates);
} else if (provider instanceof Sinocipher) {
externalSignatureContainer = new SinoChipherSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED,
containerNum, certificates);
} else {
throw new SystemException(1000, "未知的签章容器");
}
MakeSignature.signExternalContainer(pdfSignatureAppearance, externalSignatureContainer, 8192);
byte[] buffer = byteArrayOutputStream.toByteArray();
// 计算hash
InputStream inputStreamHash = pdfSignatureAppearance.getRangeStream();
BouncyCastleDigest bouncyCastleDigest = new BouncyCastleDigest();
byte[] hash = DigestAlgorithms.digest(inputStreamHash, bouncyCastleDigest.getMessageDigest(HASH_ALGORITHM));
PdfPKCS7 pkcs7 = new PdfPKCS7(null, certificates, HASH_ALGORITHM, null, bouncyCastleDigest, false);
pkcs7.setExternalDigest(hash, null, ENCRYPTION_ALGORITHM);
byte[] sh = pkcs7.getEncodedPKCS7(hash, pdfSignatureAppearance.getSignDate(), null, null, null, null, MakeSignature.CryptoStandard.CMS);
pdfReader.close();
DeferredSignResult deferredSignResult = new DeferredSignResult();
deferredSignResult.setDeferredPdfInputStream(new ByteArrayInputStream(buffer));
deferredSignResult.setPkcs1(hash);
deferredSignResult.setPkcs7(sh);
pdfReader.close();
return deferredSignResult;
}
public class FisherManSignatureContainer implements ExternalSignatureContainer {
/**
* 加密机容器号
*/
private final int containerNum;
private final Fisherman fisherman;
private final Certificate[] certChain;
/**
* hash算法
*/
private final String hashAlgorithm;
/**
* 加密算法
*/
private final String encryptAlgorithm;
private Calendar signingTime = Calendar.getInstance();
public FisherManSignatureContainer(PdfName filter, PdfName subFilter, int containerNum, Certificate[] certChain) {
PdfDictionary pdfDictionary = new PdfDictionary();
pdfDictionary.put(PdfName.FILTER, filter);
pdfDictionary.put(PdfName.SUBFILTER, subFilter);
this.containerNum = containerNum;
fisherman = new Fisherman();
this.certChain = certChain;
String algorithmGroup = CertUtils.getCertificateAlgorithmGroup(certChain[0]);
String[] parsedAlgorithmGroup = CertUtils.parseAlgorithmGroup(algorithmGroup);
hashAlgorithm = parsedAlgorithmGroup[0];
encryptAlgorithm = parsedAlgorithmGroup[1];
}
@Override
public byte[] sign(InputStream inputStream) throws GeneralSecurityException {
try {
BouncyCastleDigest digest = new BouncyCastleDigest();
byte[] hash = DigestAlgorithms.digest(inputStream, digest.getMessageDigest(hashAlgorithm));
PdfPKCS7 pkcs7 = new PdfPKCS7(null, certChain, hashAlgorithm, null, new BouncyCastleDigest(), false);
byte[] sh = pkcs7.getAuthenticatedAttributeBytes(hash, signingTime, null, null, MakeSignature.CryptoStandard.CMS);
byte[] sign;
if ("SM3".equalsIgnoreCase(hashAlgorithm)) {
sign = fisherman.sign(sh, containerNum);
} else {
sign = fisherman.signRSA(sh, containerNum);
}
return getP7(hash,sign);
} catch (Exception e) {
log.error("渔翁加密机签章失败:{}", e.getMessage());
throw new SystemException(1000, "渔翁加密机签章失败!");
}
}
@Override
public void modifySigningDictionary(PdfDictionary pdfDictionary) {
pdfDictionary.putAll(pdfDictionary);
}
byte[] getP7(byte[] plaintext,byte[] signValue) throws Exception {
BouncyCastleDigest bouncyCastleDigest = new BouncyCastleDigest();
PdfPKCS7 pdfPKCS7 = new PdfPKCS7(null, certChain, hashAlgorithm, null, bouncyCastleDigest, false);
pdfPKCS7.setExternalDigest(signValue, null, encryptAlgorithm);
return pdfPKCS7.getEncodedPKCS7(plaintext, signingTime,null,"sinoCipher",null,null, MakeSignature.CryptoStandard.CMS);
}
}
Вот адрес моего подписанного PDF-файла
https://drive.google.com/file/d/ 1pCX6ikFxwyY-dPd4M6hm0JqTA4B04V8T/view?usp=sharing
Подробнее здесь:
https://stackoverflow.com/questions/793 ... d-not-pass
1737111932
Anonymous
Я использую iText для цифровой подписи PDF-файлов, и мы используем не популярный во всем мире алгоритм под названием SM3WITHSM2. Однако сейчас невозможно проверить подписанный файл, и я не уверен, в чем проблема. [code] public DeferredSignResult machineSign(MachineSignParam machineSignParam) throws Exception { CipherMachineService provider = getProvider(); URL pdfUrl = machineSignParam.getPdfUrl(); URL sealUrl = machineSignParam.getSealUrl(); Rectangle rectangle = machineSignParam.getRectangle(); int page = machineSignParam.getPage(); int containerNum = machineSignParam.getContainerNum(); Certificate[] certificates = machineSignParam.getCertificates(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); PdfReader pdfReader = new PdfReader(pdfUrl); PdfStamper pdfSigner = PdfStamper.createSignature(pdfReader, byteArrayOutputStream, '\0', null, true); PdfSignatureAppearance pdfSignatureAppearance = pdfSigner.getSignatureAppearance(); Image imageData = Image.getInstance(sealUrl); pdfSignatureAppearance.setReason(""); pdfSignatureAppearance.setLocation(""); pdfSignatureAppearance.setContact(""); pdfSignatureAppearance.setLayer2Text(""); pdfSignatureAppearance.setLayer4Text(""); pdfSignatureAppearance.setSignatureCreator(""); pdfSignatureAppearance.setOpacity(1F); pdfSignatureAppearance.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED); pdfSignatureAppearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION); pdfSignatureAppearance.setImage(imageData); pdfSignatureAppearance.setVisibleSignature(rectangle, page, IdUtil.fastSimpleUUID()); ExternalSignatureContainer externalSignatureContainer; if (provider instanceof Fisherman) { externalSignatureContainer = new FisherManSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED, containerNum, certificates); } else if (provider instanceof Sinocipher) { externalSignatureContainer = new SinoChipherSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED, containerNum, certificates); } else { throw new SystemException(1000, "未知的签章容器"); } MakeSignature.signExternalContainer(pdfSignatureAppearance, externalSignatureContainer, 8192); byte[] buffer = byteArrayOutputStream.toByteArray(); // 计算hash InputStream inputStreamHash = pdfSignatureAppearance.getRangeStream(); BouncyCastleDigest bouncyCastleDigest = new BouncyCastleDigest(); byte[] hash = DigestAlgorithms.digest(inputStreamHash, bouncyCastleDigest.getMessageDigest(HASH_ALGORITHM)); PdfPKCS7 pkcs7 = new PdfPKCS7(null, certificates, HASH_ALGORITHM, null, bouncyCastleDigest, false); pkcs7.setExternalDigest(hash, null, ENCRYPTION_ALGORITHM); byte[] sh = pkcs7.getEncodedPKCS7(hash, pdfSignatureAppearance.getSignDate(), null, null, null, null, MakeSignature.CryptoStandard.CMS); pdfReader.close(); DeferredSignResult deferredSignResult = new DeferredSignResult(); deferredSignResult.setDeferredPdfInputStream(new ByteArrayInputStream(buffer)); deferredSignResult.setPkcs1(hash); deferredSignResult.setPkcs7(sh); pdfReader.close(); return deferredSignResult; } public class FisherManSignatureContainer implements ExternalSignatureContainer { /** * 加密机容器号 */ private final int containerNum; private final Fisherman fisherman; private final Certificate[] certChain; /** * hash算法 */ private final String hashAlgorithm; /** * 加密算法 */ private final String encryptAlgorithm; private Calendar signingTime = Calendar.getInstance(); public FisherManSignatureContainer(PdfName filter, PdfName subFilter, int containerNum, Certificate[] certChain) { PdfDictionary pdfDictionary = new PdfDictionary(); pdfDictionary.put(PdfName.FILTER, filter); pdfDictionary.put(PdfName.SUBFILTER, subFilter); this.containerNum = containerNum; fisherman = new Fisherman(); this.certChain = certChain; String algorithmGroup = CertUtils.getCertificateAlgorithmGroup(certChain[0]); String[] parsedAlgorithmGroup = CertUtils.parseAlgorithmGroup(algorithmGroup); hashAlgorithm = parsedAlgorithmGroup[0]; encryptAlgorithm = parsedAlgorithmGroup[1]; } @Override public byte[] sign(InputStream inputStream) throws GeneralSecurityException { try { BouncyCastleDigest digest = new BouncyCastleDigest(); byte[] hash = DigestAlgorithms.digest(inputStream, digest.getMessageDigest(hashAlgorithm)); PdfPKCS7 pkcs7 = new PdfPKCS7(null, certChain, hashAlgorithm, null, new BouncyCastleDigest(), false); byte[] sh = pkcs7.getAuthenticatedAttributeBytes(hash, signingTime, null, null, MakeSignature.CryptoStandard.CMS); byte[] sign; if ("SM3".equalsIgnoreCase(hashAlgorithm)) { sign = fisherman.sign(sh, containerNum); } else { sign = fisherman.signRSA(sh, containerNum); } return getP7(hash,sign); } catch (Exception e) { log.error("渔翁加密机签章失败:{}", e.getMessage()); throw new SystemException(1000, "渔翁加密机签章失败!"); } } @Override public void modifySigningDictionary(PdfDictionary pdfDictionary) { pdfDictionary.putAll(pdfDictionary); } byte[] getP7(byte[] plaintext,byte[] signValue) throws Exception { BouncyCastleDigest bouncyCastleDigest = new BouncyCastleDigest(); PdfPKCS7 pdfPKCS7 = new PdfPKCS7(null, certChain, hashAlgorithm, null, bouncyCastleDigest, false); pdfPKCS7.setExternalDigest(signValue, null, encryptAlgorithm); return pdfPKCS7.getEncodedPKCS7(plaintext, signingTime,null,"sinoCipher",null,null, MakeSignature.CryptoStandard.CMS); } [/code] } Вот адрес моего подписанного PDF-файла https://drive.google.com/file/d/ 1pCX6ikFxwyY-dPd4M6hm0JqTA4B04V8T/view?usp=sharing Подробнее здесь: [url]https://stackoverflow.com/questions/79364337/the-verification-of-the-pdf-did-not-pass[/url]