Java连续符号导致SignatureException?
我不能连续两次签东西。。。这是一个已知的Java加密问题吗 我的简化测试用例Java连续符号导致SignatureException?,java,security,cryptography,digital-signature,smartcard,Java,Security,Cryptography,Digital Signature,Smartcard,我不能连续两次签东西。。。这是一个已知的Java加密问题吗 我的简化测试用例 public class Test { private X509Certificate cert = null; private PrivateKey pk = null; public Test(X509Certificate cert, Key pk) { this.cert = cert; this.pk = (PrivateKey) pk; }
public class Test {
private X509Certificate cert = null;
private PrivateKey pk = null;
public Test(X509Certificate cert, Key pk) {
this.cert = cert;
this.pk = (PrivateKey) pk;
}
public byte[] sign(byte[] data) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature rsa = Signature.getInstance("SHA1withRSA");
rsa.initSign(pk);
rsa.update(data);
return rsa.sign();
}
public static void main(String[] args) throws Exception {
// Load your cert here
//X509Certificate cert ...
String data = "Hello World";
KeyStore ks = KeyStore.getInstance("Windows-MY");
ks.load(null, null);
Key pk = ks.getKey(cert.getAlias(), null);
Test test = new Test(cert, pk);
// Signing once
Logger.debug(test.sign(data.getBytes()));
// Signing twice
Logger.debug(test.sign(data.getBytes()));
}
}
第一个签名操作按预期进行,但第二个签名操作引发以下异常:
Exception in thread "main" java.security.SignatureException:
The card cannot be accessed because the wrong PIN was presented.
at sun.security.mscapi.RSASignature.signHash(Native Method)
at sun.security.mscapi.RSASignature.engineSign(RSASignature.java:386)
at java.security.Signature$Delegate.engineSign(Signature.java:1207)
at java.security.Signature.sign(Signature.java:579)
at ca.carillon.piv.signer.SignWorker.sign(SignWorker.java:48)
at ca.carillon.piv.signer.SignWorker.sign(SignWorker.java:39)
at ca.carillon.piv.signer.SignWorker.main(SignWorker.java:75)
现在的问题是,第二次签名操作,它甚至从未提示我输入PIN
有人能告诉我怎么了吗?我很确定我的代码是正确的
更新:
如果您使用软件证书运行上述代码,那么它将签署罚款。似乎只有在处理带有PIN的硬件证书时才会出错
如果我将代码更改为以下内容,那么它将进行第二次签名,但是,由于它必须重新加载密钥库,因此会增加显著的延迟量
KeyStore ks = KeyStore.getInstance("Windows-MY");
ks.load(null, null);
Test test = new Test(cert.getCertificate(),
ks.getKey(cert.getAlias(), null));
Logger.debug(test.sign(test));
// if I reload it like this
ks.load(null, null);
Logger.debug(test.sign(test));
如果其他人对此有更多的见解或更好的解决方法,那就太好了。请让我知道 您可能需要为此配置某种回调处理程序或
Key pk=ks.getKey(cert.getAlias(),null)
提供任何PIN码,也不调用Key pk=ks.getKey(cert.getAlias(),null)代码>两次(只是为了确定)。您可以尝试这样添加PIN吗?您不提供PIN,它会提示您。sunmsapi.jar似乎有一个bug,如果我在签名之前重新加载密钥库,它就会工作。我肯定至少会尝试我的解决方案。请注意,如果卡在每次RSA私钥操作之前需要PIN码,或者只需要一次PIN码,则它们之间存在差异。很可能是软件CAPI实现没有向sunmscapi提供所需的信息,因此我不会过早地责怪该库-这可能是正确的。@MaartenBodewes我在这里发布之前就尝试过你的方法。我创建了两个新的Test
对象实例,它们在这两种情况下都执行getKey
。我唯一一次让它“工作”是在更新中提到我的解决方法,通过重新加载密钥库,见鬼,我甚至不需要为后续签名获取密钥。但这是一个糟糕的解决方法…您可能需要为此配置某种回调处理程序
或Key pk=ks.getKey(cert.getAlias(),null)
提供任何PIN码,也不调用Key pk=ks.getKey(cert.getAlias(),null)代码>两次(只是为了确定)。您可以尝试这样添加PIN吗?您不提供PIN,它会提示您。sunmsapi.jar似乎有一个bug,如果我在签名之前重新加载密钥库,它就会工作。我肯定至少会尝试我的解决方案。请注意,如果卡在每次RSA私钥操作之前需要PIN码,或者只需要一次PIN码,则它们之间存在差异。很可能是软件CAPI实现没有向sunmscapi提供所需的信息,因此我不会过早地责怪该库-这可能是正确的。@MaartenBodewes我在这里发布之前就尝试过你的方法。我创建了两个新的Test
对象实例,它们在这两种情况下都执行getKey
。我唯一一次让它“工作”是在更新中提到我的解决方法,通过重新加载密钥库,见鬼,我甚至不需要为后续签名获取密钥。但这是一个糟糕的解决办法。。。