Java - PKCS11和MSKeyStore

时间:2011-11-10 13:59:15

标签: java security keystore pkcs#11

我正在尝试使用MS-KeyStore中的不同证书签署一个字符串。 但是,我知道MS-Keystore中的令牌中有导入的密钥。 所以,我的问题是 - 如果我通过Keystore并尝试使用一个引用pkcs11的证书进行签名,我会弹出一个输入pkcs11密码。 如何检查证书是否来自我的令牌?

提前致谢!!!

这是我现在的代码:

  String alias;
    byte[] data = "test".getBytes();
    char[] pin = "pass".toCharArray();

    try {


        KeyStore ks = KeyStore.getInstance("Windows-MY");
        ks.load(null, pin);
        System.out.println("Provider: "+ks.getProvider());
        System.out.println("KS size: " + ks.size());

        Enumeration enumeration = ks.aliases();

        while (enumeration.hasMoreElements()) {
            alias = (String) enumeration.nextElement();

            PrivateKey privateKey = (PrivateKey) ks.getKey(alias, null);
            Certificate certificate = ks.getCertificate(alias);

            Provider provider = ks.getProvider();
            Signature signature = Signature.getInstance("SHA1withRSA", provider);
            try {
                signature.initSign(privateKey);
                signature.update(data);

                byte[] signedSignature = signature.sign();
                System.out.println("\tGenerated signature for " + alias);

                signature.initVerify(certificate);
                signature.update(data);
                if (signature.verify(signedSignature)) {
                    System.out.println("\tSignature verifified for " + alias);
                } else {
                    System.out.println("\tCould not verify signature for " + alias);
                }
            } catch (Exception ex) {
                System.out.println("\tError for " + alias);
            }

        }

    } catch (KeyStoreException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (CertificateException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (FileNotFoundException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (IOException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    } catch (UnrecoverableKeyException e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    }

2 个答案:

答案 0 :(得分:0)

我担心您无法可靠地告知证书来源,至少在MS CAPI提供商的Java级别上是这样。但这是设计的一部分 - MS CAPI或多或少打算封装和隐藏证书/密钥的来源。

告知您的密钥/证书来自PKCS#11设备的安全方法是使用SUN PKCS#11 provider。但是,这样做的缺点是您需要静态地指定本机PKCS#11库的路径(在java.security文件中,您可以静态配置提供程序)或动态请求它作为用户输入。

如果在您的情况下使用PKCS#11提供程序太麻烦,我建议实施一个证书选择对话框来筛选合适的证书。通过将MSCAPI限制为源自PKCS#11的证书,安全性没有立即获益 - 可能有充足的理由使您的用户安装了其他证书/密钥(通常以PKCS#12文件的形式)。您应该只检查(并帮助用户已经过滤了重新符合此标准的证书)最终选择的证书/密钥符合您的标准:正确的密钥用法(例如数字签名),声音扩展密钥用法,可接受或已知的策略证书等。

在欧盟,我们正逐渐朝着安全签名创建设备上的合格证书的概念发展,并且#34;。这意味着在此类设备(例如智能卡)上提供的证书将包含特殊策略,禁止CA将这些策略用于任何其他证书,例如软件证书。因此,这将有效地允许您确保证书来自安全的硬件设备。您可以检查所涉及的证书是否支持此功能。此ETSI document列出了您必须查找的相应OID。

答案 1 :(得分:0)

在Java密钥库中,应链接密钥和证书的别名。基本上,私钥条目是私钥+证书链。所以证书应该始终来自密钥库。如果证书来自实际令牌,那么当然是关键存储的实现。检查它们是否实际来自令牌的唯一方法是使用不同的方法检索它们(例如,直接从令牌读取证书的字节)。如果您正在使用证书,则没有链接返回存储设备的证书。

当然,检查完整的证书链直到根证书是有意义的。如果根证书不经常更改,您可以考虑将证书或哈希值存储在随应用程序提供的资源中的根证书上,或者将其分发到标准Java密钥库中。