Java AES:没有安装的提供程序支持这个键:javax.crypto.spec.SecretKeySpec

时间:2021-09-25 18:34:37

I'm trying to set up 128 bit AES encryption, and I'm getting an exception thrown on my Cipher.init:

我正在尝试设置128位AES加密,我的密码被抛出了一个异常。

No installed provider supports this key: javax.crypto.spec.SecretKeySpec

没有安装的提供程序支持这个键: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:

然后将此键作为头传递给服务器。它是用这个函数编码的Base64:

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).

为了调试这个问题,我在客户端上的密钥生成和密码之前都放置了断点。在服务器端初始化。根据Netbeans的说法,组成秘钥的字节是相同的,并且长度是16字节(实际上,据我所知,对象是相同的)。

I am aware of the unlimited strength JCE stuff, but I'm not under the impression I needed it for 128 bit AES.

我知道JCE的力量是无限的,但是我并没有觉得我需要128比特的AES。

Client Side: java version "1.6.0_26"

客户端:java版本“1.6.0_26”

Server Side: java version "1.6.0_20"

服务器端:java版本“1.6.0_20”

Any Ideas?

什么好主意吗?

3 个解决方案

#1


7  

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.

我以不同的方式运行您的代码:Java 1。{ 5 6 7 }(使用AES);不同的Base64 codecs (Apache Commons Codec, datatypecon, Base64);不同的字符集;在不同的jvm之间(通过套接字)…没有作用。我没有错误。

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.)

(我知道您已经说明了正在使用的JDK版本和其他东西,但这不会有什么坏处。)

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).

在任何情况下,如果抛出错误,请将整个堆栈跟踪贴在某处。没有安装的提供程序支持这个键:javax.crypto.spec。SecretKeySpec没有告诉我们任何东西(至少对我来说没有,而且我也不能重现这个特定的错误)。

#2


6  

This error could indicate that you need to install JCE (Java Cryptography Extension).

这个错误可能表明您需要安装JCE (Java加密扩展)。

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

下载此文件(或更新版本)并将jar复制到JDK_FOLDER/jre/lib/security http://www.oracle.com/technetwork/pt/java/javase/downloads/jce-6-download-429243.html

#3


0  

This error happens with me, when providing an incorrect key to SecretKeySpec constructor.

当向SecretKeySpec构造函数提供不正确的键时,我就会出现这个错误。

#1


7  

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.

我以不同的方式运行您的代码:Java 1。{ 5 6 7 }(使用AES);不同的Base64 codecs (Apache Commons Codec, datatypecon, Base64);不同的字符集;在不同的jvm之间(通过套接字)…没有作用。我没有错误。

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.)

(我知道您已经说明了正在使用的JDK版本和其他东西,但这不会有什么坏处。)

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).

在任何情况下,如果抛出错误,请将整个堆栈跟踪贴在某处。没有安装的提供程序支持这个键:javax.crypto.spec。SecretKeySpec没有告诉我们任何东西(至少对我来说没有,而且我也不能重现这个特定的错误)。

#2


6  

This error could indicate that you need to install JCE (Java Cryptography Extension).

这个错误可能表明您需要安装JCE (Java加密扩展)。

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

下载此文件(或更新版本)并将jar复制到JDK_FOLDER/jre/lib/security http://www.oracle.com/technetwork/pt/java/javase/downloads/jce-6-download-429243.html

#3


0  

This error happens with me, when providing an incorrect key to SecretKeySpec constructor.

当向SecretKeySpec构造函数提供不正确的键时,我就会出现这个错误。