我正在做一个项目,我需要使用基于USB的数字签名来签署pdf。我已经在本地尝试了以下代码,并且能够对pdf进行签名。我的问题是天气,以下代码将在基于客户端服务器的senerio中工作。
我的代码是:
import com.lowagie.text.DocumentException; import com.lowagie.text.pdf.PdfReader; import com.lowagie.text.pdf.PdfSignatureAppearance; import com.lowagie.text.pdf.PdfStamper; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Security; import java.security.UnrecoverableKeyException; import java.security.cert.CRL; import java.security.cert.Certificate; import java.security.cert.CertificateException; import javax.servlet.RequestDispatcher; import org.bouncycastle.jce.provider.BouncyCastleProvider; import sun.security.mscapi.SunMSCAPI; public class Testing { private static boolean resFlag; public static void main (String args[]) { try { BouncyCastleProvider providerBC = new BouncyCastleProvider(); Security.addProvider(providerBC); SunMSCAPI providerMSCAPI = new SunMSCAPI(); Security.addProvider(providerMSCAPI); KeyStore ks = KeyStore.getInstance("Windows-MY"); ks.load(null, null); String alias = (String)ks.aliases().nextElement(); PrivateKey pk = (PrivateKey)ks.getKey(alias, null); Certificate[] chain = ks.getCertificateChain(alias); // //String e = request.getParameter("digiFile"); // KeyStore ks = KeyStore.getInstance("pkcs12"); // String f10 = CommonUtil.getRealPath(); // String str8 = f10 + "/DigiFiles/"; // //System.out.println("str8-->>>>>>>>" + str8 + e); // ks.load(new FileInputStream("F:/DigiFiles/Anurag Goel.pfx"), "123".toCharArray()); // // // System.out.println("The actual path is " + str8); // String alias = (String)ks.aliases().nextElement(); // PrivateKey key = (PrivateKey)ks.getKey(alias, "123".toCharArray()); // Certificate[] chain = ks.getCertificateChain(alias); PdfReader reader = new PdfReader("F:/test.pdf"); FileOutputStream os = new FileOutputStream("F:/SampleOutPut61.pdf"); PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0',null,true); PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); appearance.setCrypto(pk, chain, (CRL[])null, PdfSignatureAppearance.VERISIGN_SIGNED); appearance.setReason("elicense project"); appearance.setLocation("Assam"); appearance.setVisibleSignature("hi"); stamper.close(); } catch (KeyStoreException var27) { var27.printStackTrace(); resFlag = false; } catch (NoSuchAlgorithmException var28) { var28.printStackTrace(); resFlag = false; } catch (CertificateException var29) { var29.printStackTrace(); resFlag = false; } catch (FileNotFoundException var30) { var30.printStackTrace(); resFlag = false; } catch (IOException var31) { var31.printStackTrace(); resFlag = false; } catch (UnrecoverableKeyException var32) { var32.printStackTrace(); resFlag = false; } catch (DocumentException var33) { var33.printStackTrace(); resFlag = false; } catch (Exception var34) { var34.printStackTrace(); resFlag = false; } finally { RequestDispatcher rd; } } }
请给我建议。谢谢大家
虽然您的代码理论上可以在服务器上工作,但是我看到很多原因,为什么在客户端/服务器环境中使用在独立计算机上运行的代码不是明智的决定。有太多实际问题(例如身份验证,速度,iText版本错误等)会使您的项目出错。对于您的问题,该代码是否可以在客户端/服务器方案中运行,我将回答“否”。
更新:
在对我的答案的评论中,表明您的服务器是Linux服务器。很明显,在Linux服务器上使用“ Windows- MY”将永远无效。您必须使用PKCS#11而不是Windows-MY与存储令牌的硬件设备通信。这是一个代码示例,可用于SafeNet的Luna SA。如您所见,它使用PKCS#11:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Provider; import java.security.Security; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Properties; import org.bouncycastle.jce.provider.BouncyCastleProvider; import sun.security.pkcs11.SunPKCS11; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Rectangle; import com.itextpdf.text.log.LoggerFactory; import com.itextpdf.text.log.SysoLogger; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfSignatureAppearance; import com.itextpdf.text.pdf.PdfStamper; import com.itextpdf.text.pdf.security.BouncyCastleDigest; import com.itextpdf.text.pdf.security.CertificateUtil; import com.itextpdf.text.pdf.security.CrlClient; import com.itextpdf.text.pdf.security.CrlClientOnline; import com.itextpdf.text.pdf.security.DigestAlgorithms; import com.itextpdf.text.pdf.security.ExternalDigest; import com.itextpdf.text.pdf.security.ExternalSignature; import com.itextpdf.text.pdf.security.MakeSignature; import com.itextpdf.text.pdf.security.OcspClient; import com.itextpdf.text.pdf.security.OcspClientBouncyCastle; import com.itextpdf.text.pdf.security.PrivateKeySignature; import com.itextpdf.text.pdf.security.TSAClient; import com.itextpdf.text.pdf.security.TSAClientBouncyCastle; import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard; public class C4_01_SignWithPKCS11HSM { public static final String SRC = "/home/itext/hello.pdf"; public static final String PROPS = "/home/itext/key.properties"; public static final String DEST = "/home/itext/hello_hsm.pdf"; public void sign(String src, String dest, Certificate[] chain, PrivateKey pk, String digestAlgorithm, String provider, CryptoStandard subfilter, String reason, String location, Collection<CrlClient> crlList, OcspClient ocspClient, TSAClient tsaClient, int estimatedSize) throws GeneralSecurityException, IOException, DocumentException { // Creating the reader and the stamper PdfReader reader = new PdfReader(src); FileOutputStream os = new FileOutputStream(dest); PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0'); // Creating the appearance PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); appearance.setReason(reason); appearance.setLocation(location); appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig"); // Creating the signature ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider); ExternalDigest digest = new BouncyCastleDigest(); MakeSignature.signDetached(appearance, digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter); } public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException { LoggerFactory.getInstance().setLogger(new SysoLogger()); Properties properties = new Properties(); properties.load(new FileInputStream(PROPS)); char[] pass = properties.getProperty("PASSWORD").toCharArray(); String pkcs11cfg = properties.getProperty("PKCS11CFG"); BouncyCastleProvider providerBC = new BouncyCastleProvider(); Security.addProvider(providerBC); FileInputStream fis = new FileInputStream(pkcs11cfg); Provider providerPKCS11 = new SunPKCS11(fis); Security.addProvider(providerPKCS11); KeyStore ks = KeyStore.getInstance("PKCS11"); ks.load(null, pass); String alias = (String)ks.aliases().nextElement(); PrivateKey pk = (PrivateKey)ks.getKey(alias, pass); Certificate[] chain = ks.getCertificateChain(alias); OcspClient ocspClient = new OcspClientBouncyCastle(); TSAClient tsaClient = null; for (int i = 0; i < chain.length; i++) { X509Certificate cert = (X509Certificate)chain[i]; String tsaUrl = CertificateUtil.getTSAURL(cert); if (tsaUrl != null) { tsaClient = new TSAClientBouncyCastle(tsaUrl); break; } } List<CrlClient> crlList = new ArrayList<CrlClient>(); crlList.add(new CrlClientOnline(chain)); C4_01_SignWithPKCS11HSM app = new C4_01_SignWithPKCS11HSM(); app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, providerPKCS11.getName(), CryptoStandard.CMS, "HSM test", "Ghent", crlList, ocspClient, tsaClient, 0); } }
使用的配置文件的内容如下所示:
Name = Luna library = /usr/lunasa/lib/libCryptoki2_64.so slot = 1
请注意,根据so您的情况,可能在另一个目录中,并且您的证书可能在另一个插槽中。我还使用属性文件来存储证书的密码。显然,我不会共享密码;-)
so
此示例已在GlobalSign拥有的服务器上使用GlobalSign证书进行了测试。