Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java连续符号导致SignatureException?_Java_Security_Cryptography_Digital Signature_Smartcard - Fatal编程技术网

Java连续符号导致SignatureException?

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; }

我不能连续两次签东西。。。这是一个已知的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 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
。我唯一一次让它“工作”是在更新中提到我的解决方法,通过重新加载密钥库,见鬼,我甚至不需要为后续签名获取密钥。但这是一个糟糕的解决办法。。。