我正在尝试用智能卡签署pdf。我使用以下代码:
public class SC {
public static final String SRC = "src/test.pdf";
public static final String DEST = "src/test_smartCard.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());
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);
//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));
SC app = new SC();
app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, providerMSCAPI.getName(), CryptoStandard.CMS, "Test", "London",
null, null, tsaClient, 0);
}
}
我对这个外部签名过程感到困惑。我安装了我的读卡器,插入了我的卡,因为我看到它正在使用Windows-MY密钥存储区。所以只要插入卡,我就可以从该密钥存储区调出卡上的证书。当我通过Internet Explorer检查证书时,我可以看到我从互联网上免费获得的证书以及卡上的证书。我不能用私钥从智能卡中导出那些,我知道这是智能卡的全部要点所以这个过程将在外部完成。
我的问题在于,根据我编写的代码,我得到的文件是用我已经制作的证书而不是卡片中的证书签署的,我如何用卡片上的证书签名,还有一个事情是,我从未被要求提供我的智能卡密码。
任何人都可以帮助我,我正在努力解决这个数字签名问题,我知道接下来的事情就是使用PKCS11和dll文件,但我还没有。谢谢
加入:
感谢Robert的回答。你是对的。我列举了WINDOWS-MY密钥库中的alises,事实上我确实使用列出的第一个别名签署了该文档,这是我的非智能卡证书/密钥对。显然,这不是我想要做的,我将如何使用不同的证书/密钥签名,在我的情况下,使用属于智能卡的证书。再次感谢
答案 0 :(得分:1)
用于签名PDF的证书/密钥由别名选择。
在您的代码中,您使用的是第一个可用的别名:
String alias = (String)ks.aliases().nextElement();
看起来这个别名属于非智能卡证书/密钥对。您应该枚举可用别名列表(以及分配的证书),并查看是否属于您的智能卡证书。 如果在此列表中看不到智能卡,则必须通过PKCS#11访问智能卡。请注意,PKCS#11通常为32位 - 在这种情况下,您还必须使用32位JRE。