2013-11-02 44 views
1

我试图使用从密钥库加载的DES密钥来加密和我得到:集和java.security.KeyStore中的PKCS11获得DES密钥

Exception in thread "main" java.security.InvalidKeyException: No installed provider supports this key: sun.security.pkcs11.P11Key$P11SecretKey 
    at javax.crypto.Cipher.chooseProvider(Cipher.java:878) 
    at javax.crypto.Cipher.init(Cipher.java:1213) 
    at javax.crypto.Cipher.init(Cipher.java:1153) 

,这是我的代码:

public static void main(String[] args) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchPaddingException, IOException, CertificateException { 
     Provider provider = new sun.security.pkcs11.SunPKCS11(DesSaveLoad.class.getClassLoader().getResourceAsStream("pkcs11.cfg")); 
     Security.removeProvider(provider.getName()); 
     Security.insertProviderAt(provider, 1); 
     KeyStore keyStore = KeyStore.getInstance("PKCS11", provider); 
     keyStore.load(null, null); 
     SecretKey desKey = desGenerateKey(); 
     keyStore.setKeyEntry("t1", desKey, null, null); 
     SecretKey t1 = (SecretKey) keyStore.getKey("t1", null); 
     byte[] messageBytes = "message".getBytes(); 
     desEncrypt(messageBytes, 0, messageBytes.length, desKey); 
     desEncrypt(messageBytes, 0, messageBytes.length, t1); //Exception is thrown here 
    } 

    public static SecretKey desGenerateKey() throws NoSuchAlgorithmException { 
     KeyGenerator keygenerator = null; 
     keygenerator = KeyGenerator.getInstance("DES"); 
     return keygenerator.generateKey(); 
    } 

    public static byte[] desEncrypt(byte[] plainText, int offset, int size, SecretKey key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { 
     Cipher cipher; 
     if (size % 8 != 0) { 
      cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); 
     } else { 
      cipher = Cipher.getInstance("DES/ECB/NoPadding"); 
     } 
     cipher.init(Cipher.ENCRYPT_MODE, key); 
     return cipher.doFinal(plainText, offset, size); 
    } 

正如你所看到的,使用生成的DES密钥进行加密时不会引发异常。

+0

当你插入一个供应商的第一个,你可以隐藏默认的Java供应商。这可能是有利的,并会导致像观察到的那样的错误。你是否真的需要在提供者列表的开头插入你的自定义提供者? – Jk1

+0

@ Jk1不正确,那不是自定义提供程序,并且它在延迟提供程序选择方面表现良好(实际上,它触发了延迟提供程序选择)。 –

+0

@owlstead,感谢您的注意。这是一个普通的老式SunPKCS11,我的太糟糕了 – Jk1

回答

2

如果您使用HSM,则加密过程在HSM内进行,而不是在软件进行加密。 Cipher本身没有实现加密过程。在PKCS#11提供的用于Cipher底层CipherSpi使用延迟提供商选择根据呼叫到init()期间给出的键选择的。因此,尽管desEncrypt()函数似乎执行相同的操作,但实际上功能取决于提供者,在您的情况下,取决于PKCS#11包装器,库和HSM。

现在PKCS#11是一种接口规范;并非PKCS#11中的所有机制都将在每个令牌中实施。很可能某些加密算法太模糊或太不安全。后者可能是DES ECB的情况,因为该算法非常不安全。这并不意味着DES密钥一般不能使用 - 它们仍然可以在例如MAC计算。因此,如果支持DES ECB(在当前设置中),请检查HSM的文档。

通过将-Djava.security.debug=sunpkcs11添加到您对Java解释器(javajavaw)的调用中,可以获得有关PKCS#11方法调用的更多信息。如果DES不起作用,请尝试更安全和更普遍的"AES/CBC/PKCS5Padding"或三重DES机制。

+0

谢谢。你知道提供商应该提供什么服务,所以我可以使用KeyStore保存DES密钥? – Mab

+1

那么,如果你的PKCS#11 lib不接受它,你可以尝试[JCEKS](http://stackoverflow.com/a/3027528/589259)(看来) –

-1

看看this后帮助

要么关键是不正确(更可能)或给定的密钥不被提供者所支持。

KeyStore.getInstance("PKCS11", provider); 

PS:您是否使用自定义提供程序?

+0

我正在使用sun.security.pkcs11.SunPKCS11(oracle's)。我试图了解提供者是否支持DES密钥,但我没有找到任何东西。 – Mab

+0

@MaziarAb - 或许我过早地在你的问题上发布了'答案'。密钥库用于存储公钥对(不对称)。我应该先问你的。如果你想生成一个DES密钥[this](http://www.mkyong.com/java/jce-encryption-data-encryption-standard-des-tutorial/)应该会有更好的帮助。 –

+0

我想使用KeyStore存储和检索DES密钥。例如,我知道可以使用KeyStore.getInstance(“JKS”),但在我的情况下,我需要使用“PKCS11”作为KeyStore类型。 – Mab