2013-11-02 45 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