問題描述
我正在嘗試設(shè)置 128 位 AES 加密,但我的 Cipher.init 出現(xiàn)異常:
沒有安裝的提供者支持這個密鑰:javax.crypto.spec.SecretKeySpec
我正在使用以下代碼在客戶端生成密鑰:
私鑰生成器 kgen;嘗試 {kgen = KeyGenerator.getInstance("AES");} 捕捉(NoSuchAlgorithmException e){//TODO 自動生成的 catch 塊e.printStackTrace();}kgen.init(128);}SecretKey skey = kgen.generateKey();
然后,此密鑰作為標(biāo)頭傳遞給服務(wù)器.它是使用此函數(shù)進(jìn)行 Base64 編碼的:
public String secretKeyToString(SecretKey s) {Base64 b64 = 新 Base64();byte[] bytes = b64.encodeBase64(s.getEncoded());返回新字符串(字節(jié));}
服務(wù)器拉頭,然后做
protected static byte[] encrypt(byte[] data, String base64encodedKey) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {密碼密碼;嘗試 {cipher = Cipher.getInstance("AES");} 捕捉(NoSuchAlgorithmException ex){//記錄錯誤} 捕捉(NoSuchPaddingException 前){//記錄錯誤}SecretKey 密鑰 = b64EncodedStringToSecretKey(base64encodedKey);cipher.init(Cipher.ENCRYPT_MODE,密鑰);//這是失敗的地方數(shù)據(jù) = cipher.doFinal(data);返回數(shù)據(jù);}私有靜態(tài) SecretKey b64EncodedStringToSecretKey(String base64encodedKey) {密鑰密鑰 = 空;嘗試 {byte[] temp = Base64.decodeBase64(base64encodedKey.getBytes());密鑰 = 新的 SecretKeySpec(臨時,SYMMETRIC_ALGORITHM);} 捕捉(異常 e){//沒做什么}返回鍵;}
為了調(diào)試它,我在客戶端的密鑰生成之后和服務(wù)器端的 cipher.init 之前都放置了斷點(diǎn).根據(jù) Netbeans 的說法,組成 SecretKey 的字節(jié)是相同的,長度為 16 個字節(jié)(事實(shí)上,據(jù)我所知,對象是相同的).
我知道無限強(qiáng)度的 JCE 東西,但我并不認(rèn)為我需要它來實(shí)現(xiàn) 128 位 AES.
客戶端:java版本1.6.0_26"
服務(wù)器端:java 版本1.6.0_20"
有什么想法嗎?
我以不同的方式運(yùn)行您的代碼,包括:Java 1.{5,6,7}(使用 AES);不同的 Base64 編解碼器(Apache Commons Codec、DatatypeConverted、Base64);不同的字符集;在不同的 JVM 之間(通過套接字) …無濟(jì)于事.我沒有錯誤.
為了縮小問題范圍,您可以在兩端運(yùn)行以下代碼嗎?
靜態(tài){System.out.println(System.getProperty("java.version"));對于(提供者提供者:Security.getProviders())System.out.println(提供者);}公共靜態(tài) void main(String[] args) 拋出異常 {KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");keyGenerator.init(128);SecretKey secretKey = keyGenerator.generateKey();密碼密碼 = Cipher.getInstance("AES");cipher.init(Cipher.ENCRYPT_MODE,secretKey);}
(我知道您已經(jīng)說明了您正在使用的 JDK 版本等內(nèi)容,但不會有什么壞處.)
鑒于在您將密鑰從客戶端傳輸?shù)椒?wù)器(或者可能是反向傳輸)時密鑰沒有損壞,那么如果:
- 客戶端拋出,但服務(wù)器沒有——錯誤在客戶端;
- 客戶端不會拋出,但服務(wù)器會拋出——錯誤在服務(wù)器端;
- 客戶端和服務(wù)器都拋出或都不拋出——需要進(jìn)一步調(diào)查.
在任何情況下,如果拋出錯誤,請將整個堆棧跟蹤發(fā)布到某處.錯誤 No installed provider supports this key: javax.crypto.spec.SecretKeySpec
告訴我們什么都沒有(至少對我來說沒有,而且我也無法重現(xiàn)這個特定的錯誤).p>
I'm trying to set up 128 bit AES encryption, and I'm getting an exception thrown on my Cipher.init:
No installed provider supports this key: javax.crypto.spec.SecretKeySpec
I'm generating the Key on the client side using the following code:
private KeyGenerator kgen;
try {
kgen = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
kgen.init(128);
}
SecretKey skey = kgen.generateKey();
This key is then passed to the server as a header. it is Base64 encoded using this function:
public String secretKeyToString(SecretKey s) {
Base64 b64 = new Base64();
byte[] bytes = b64.encodeBase64(s.getEncoded());
return new String(bytes);
}
The server pulls the header, and does
protected static byte[] encrypt(byte[] data, String base64encodedKey) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher;
try {
cipher = Cipher.getInstance("AES");
} catch (NoSuchAlgorithmException ex) {
//log error
} catch (NoSuchPaddingException ex) {
//log error
}
SecretKey key = b64EncodedStringToSecretKey(base64encodedKey);
cipher.init(Cipher.ENCRYPT_MODE, key); //THIS IS WHERE IT FAILS
data = cipher.doFinal(data);
return data;
}
private static SecretKey b64EncodedStringToSecretKey(String base64encodedKey) {
SecretKey key = null;
try {
byte[] temp = Base64.decodeBase64(base64encodedKey.getBytes());
key = new SecretKeySpec(temp, SYMMETRIC_ALGORITHM);
} catch (Exception e) {
// Do nothing
}
return key;
}
To debug this, I put breakpoints after both the key generation on the client side, and just before the cipher.init on the server side. According to Netbeans, the bytes that make up the SecretKeys are identical and are 16 bytes in length (In fact, as far as I can tell, the objects are identical).
I am aware of the unlimited strength JCE stuff, but I'm not under the impression I needed it for 128 bit AES.
Client Side: java version "1.6.0_26"
Server Side: java version "1.6.0_20"
Any Ideas?
I've run your code in different ways, with: Java 1.{5,6,7} (using AES); different Base64 codecs (Apache Commons Codec, DatatypeConverted, Base64); different character sets; between different JVMs (through sockets) … to no avail. I got no errors.
To narrow down the problem, can you run the following code on both ends?
static {
System.out.println(System.getProperty("java.version"));
for (Provider provider : Security.getProviders())
System.out.println(provider);
}
public static void main(String[] args) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
}
(I know that you've already stated the JDK versions you're using and stuff, but it can't hurt.)
Given that the key doesn't get corrupted while you transfer it from client to server (or maybe in reverse), then if:
- the client throws, but the server doesn't—the error is on the client side;
- the client doesn't throw, but the server does—the error is on the server side;
- the client and server both throws or neither of them—needs further investigation.
In any case, if an error is thrown, please post the whole stack trace somewhere. The error No installed provider supports this key: javax.crypto.spec.SecretKeySpec
tells us nothing (at least for me it doesn't, and I couldn't reproduce this particular error either).
這篇關(guān)于Java AES:沒有安裝的提供程序支持此密鑰:javax.crypto.spec.SecretKeySpec的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!