Java AES:没有安装的提供程序支持此密钥:javax.crypto.spec.SecretKeySpec
我正在尝试设置 128 位 AES 加密,但在 Cipher.init 上抛出异常:
没有安装的提供程序支持此密钥:javax.crypto.spec.SecretKeySpec
我使用以下代码在客户端生成密钥:
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();
然后将该密钥作为标头传递到服务器。它是使用此函数进行 Base64 编码的:
public String secretKeyToString(SecretKey s) {
Base64 b64 = new Base64();
byte[] bytes = b64.encodeBase64(s.getEncoded());
return new String(bytes);
}
服务器提取标头,并执行
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;
}
为了调试此功能,我在客户端的密钥生成之后和服务器端的 cipher.init 之前放置了断点。根据 Netbeans 的说法,组成 SecretKey 的字节是相同的,长度为 16 个字节(事实上,据我所知,这些对象是相同的)。
我知道 JCE 的强度无限,但我并不认为 128 位 AES 需要它。
客户端:java 版本“1.6.0_26”
服务器端:java 版本“1.6.0_20”
有什么想法吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我以不同的方式运行您的代码,使用:Java 1.{5,6,7}(使用 AES);不同的 Base64 编解码器(Apache Commons Codec、DatatypeConverted、Base64);不同的字符集;在不同的 JVM 之间(通过套接字)……无济于事。我没有任何错误。
为了缩小问题范围,您可以在两端运行以下代码吗?
(我知道您已经说明了您正在使用的 JDK 版本等内容,但这不会有什么坏处。)
考虑到密钥在从客户端传输到客户端时不会被损坏服务器(或者可能相反),那么如果:
无论如何,如果抛出错误,请将整个堆栈跟踪发布到某处。错误
没有安装的提供程序支持此密钥:javax.crypto.spec.SecretKeySpec
没有告诉我们任何信息(至少对我来说没有,而且我也无法重现此特定错误)。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?
(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:
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).此错误可能表明您需要安装 JCE(Java 加密扩展)。
下载此文件(或更新版本)并将 jar 复制到 JDK_FOLDER/jre/lib/security
http://www.oracle.com /technetwork/pt/java/javase/downloads/jce-6-download-429243.html
This error could indicate that you need to install JCE (Java Cryptography Extension).
Download this file (or newer version) and copy jars to JDK_FOLDER/jre/lib/security
http://www.oracle.com/technetwork/pt/java/javase/downloads/jce-6-download-429243.html
当我向
SecretKeySpec
构造函数提供不正确的密钥时,就会发生此错误。This error happens with me, when providing an incorrect key to
SecretKeySpec
constructor.