我有一个JAR,该JAR的类应该对PDF文件签名,并且还创建一个分离的PKCS7签名。但是,问题是我使用了两种不同的加密提供程序:JCP(用于创建附加的PDF签名的俄罗斯提供程序)和BC,分别用于创建分离的提供程序。
代码如下:
public void signPdf(InputStream is, String folder, String fileNameWoExtension) throws Exception
{
// private key and certificate
PrivateKey key = keyStore.getPrivateKey();
Certificate[] chain = new Certificate[1];
chain[0] = keyStore.getCertificate();
X509Certificate cert = (X509Certificate)chain[0];
Date notBefore = cert.getNotBefore();
Date notAfter = cert.getNotAfter();
String serial = cert.getSerialNumber().toString(16).toUpperCase();
String subject = PdfPKCS7.getSubjectFields(cert).getField("CN");
String number = fileNameWoExtension.replace("appeal_", "");
// reader and stamper
PdfReader reader = new PdfReader(is);
FileOutputStream fout = new FileOutputStream(folder + File.separator + fileNameWoExtension + ".pdf");
PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
StampsCreator.createEdsStamp(folder, serial, subject, notBefore, notAfter);
StampsCreator.createRegisterStamp(folder, new Date(), number);
PdfContentByte pcb = stp.getOverContent(1);
Image imageEds = Image.getInstance(folder + File.separator + StampsCreator.EDS_STAMP);
imageEds.scaleAbsolute(200, 87);
imageEds.setAbsolutePosition(75, 80);
imageEds.setAnnotation(new Annotation(0, 0, 0, 0, 3));
pcb.addImage(imageEds);
Image imageReg = Image.getInstance(folder + File.separator + StampsCreator.REGNUMBER_STAMP);
imageReg.scaleAbsolute(207, 20);
int height = (int) Math.floor(reader.getPageSize(1).getHeight());
imageReg.setAbsolutePosition(70, height - 130);
imageReg.setAnnotation(new Annotation(0, 0, 0, 0, 3));
pcb.addImage(imageReg);
PdfSignatureAppearance sap = stp.getSignatureAppearance();
sap.setSignDate(new GregorianCalendar());
sap.setCrypto(null, chain, null, null);
sap.setAcro6Layers(true);
sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
PdfSignature dic;
dic = new PdfSignature(PdfName.ADOBE_CryptoProPDF, PdfName.ADBE_PKCS7_DETACHED);
dic.setDate(new PdfDate(sap.getSignDate()));
dic.setName(subject);
dic.setReason("Signed with CryptoPro");
sap.setCryptoDictionary(dic);
int csize = 4000;
HashMap<PdfName,Integer> exc = new HashMap<PdfName,Integer>();
exc.put(PdfName.CONTENTS, new Integer(csize * 2 + 2));
sap.preClose(exc);
System.out.println("preclosed " + key.getClass().getName() + " " + key.getAlgorithm());
System.out.println("1");
X509Certificate signerCert = (X509Certificate)chain[0];
System.out.println("2");
List certList = new ArrayList();
System.out.println("3");
certList.add(signerCert);
System.out.println("4");
Store certs = new JcaCertStore(certList);
System.out.println("5");
// signature
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
System.out.println("6");
ContentSigner signer = new JcaContentSignerBuilder(AlgorithmUtils.getDigestMessageAndAlgorithmsForJcaContentSignerBuilder(signerCert)).setProvider("BC").build(key);
System.out.println("7");
generator.addSignerInfoGenerator(
new JcaSignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
.build(signer, signerCert));
System.out.println("8");
generator.addCertificates(certs);
System.out.println("9");
//generator.addCertificates(new JcaCertStore(Arrays.asList(chain)));
//generator.addSigner(key, (X509Certificate)chain[0], JCP.GOST_EL_DH_OID, JCP.GOST_DIGEST_OID);
/*ArrayList<Certificate> list = new ArrayList<Certificate>();
for (int i = 0; i < chain.length; i++) {
list.add(chain[i]);
}*/
/*CertStore chainStore
= CertStore.getInstance("Collection", new CollectionCertStoreParameters(list), "BC");
generator.addCertificatesAndCRLs(chainStore);*/
CMSSignedData signedData;
System.out.println("9");
signedData = generator.generate(new CMSProcessableByteArray(IOUtils.toByteArray(sap.getRangeStream())), false);
System.out.println("10");
//CMSProcessable content = new CMSProcessableRange(sap);
//signedData = generator.generate(content, false, JCP.PROVIDER_NAME);
byte[] pk = signedData.getEncoded();
System.out.println("p7s data ready.");
byte[] outc = new byte[csize];
PdfDictionary dic2 = new PdfDictionary();
System.arraycopy(pk, 0, outc, 0, pk.length);
dic2.put(PdfName.CONTENTS, new PdfString(outc).setHexWriting(true));
System.out.println("signed ready.");
sap.close(dic2);
FileOutputStream fos = new FileOutputStream(folder + File.separator + fileNameWoExtension + ".p7s");
fos.write(pk);
fos.close();
}
以下是在用于创建签名的证书中定义算法的方法:
public static String getDigestMessageAndAlgorithmsForJcaContentSignerBuilder(X509Certificate cert)
{
switch (cert.getPublicKey().getAlgorithm())
{
case "GOST3410_2012_256":
return JCA_CONTENT_GOST_2012_256; //GOST3411-2012-256WITHECGOST3410-2012-256
case "GOST3410_2012_512":
return JCA_CONTENT_GOST_2012_512; //GOST3411-2012-512WITHECGOST3410-2012-512
case "GOST3410EL":
return JCA_CONTENT_GOST3410EL; //GOST3411withECGOST3410
default:
throw new IllegalArgumentException("Algorithm inside the certificate " + cert.getPublicKey().getAlgorithm() + " is not supported.");
}
}
代码似乎在以下行处停止:
ContentSigner signer = new JcaContentSignerBuilder(AlgorithmUtils.getDigestMessageAndAlgorithmsForJcaContentSignerBuilder(signerCert)).setProvider("BC").build(key);
我发现它是因为当我尝试执行它时,会得到以下输出:
preclosed ru.CryptoPro.JCP.Key.GostExchPrivateKey GOST3410DH_2012_256
1
2
3
4
5
6
那是为什么?与使用不同的加密提供程序有关吗?我的意思是因为PrivateKey
是ru.CryptoPro.JCP.Key.GostExchPrivateKey
类型,而BC需要其他类型?
谢谢。