Java AES:没有安装的提供程序支持此密钥:javax.crypto.spec.SecretKeySpec

2022-01-10 00:00:00 encryption cryptography aes secret-key java

我正在尝试设置 128 位 AES 加密,但我的 Cipher.init 出现异常:

没有安装的提供者支持这个密钥:javax.crypto.spec.SecretKeySpec

我正在使用以下代码在客户端生成密钥:

私钥生成器 kgen;尝试 {kgen = KeyGenerator.getInstance("AES");} 捕捉(NoSuchAlgorithmException e){//TODO 自动生成的 catch 块e.printStackTrace();}kgen.init(128);}SecretKey skey = kgen.generateKey();

然后,此密钥作为标头传递给服务器.它是使用此函数进行 Base64 编码的:

public String secretKeyToString(SecretKey s) {Base64 b64 = 新 Base64();byte[] bytes = b64.encodeBase64(s.getEncoded());返回新字符串(字节);}

服务器拉头,然后做

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,密钥);//这是失败的地方数据 = cipher.doFinal(data);返回数据;}私有静态 SecretKey b64EncodedStringToSecretKey(String base64encodedKey) {密钥密钥 = 空;尝试 {byte[] temp = Base64.decodeBase64(base64encodedKey.getBytes());密钥 = 新的 SecretKeySpec(临时,SYMMETRIC_ALGORITHM);} 捕捉(异常 e){//没做什么}返回键;}

为了调试它,我在客户端的密钥生成之后和服务器端的 cipher.init 之前都放置了断点.根据 Netbeans 的说法,组成 SecretKey 的字节是相同的,长度为 16 个字节(事实上,据我所知,对象是相同的).

我知道无限强度的 JCE 东西,但我并不认为我需要它来实现 128 位 AES.

客户端:java版本1.6.0_26"

服务器端:java 版本1.6.0_20"

有什么想法吗?

解决方案

我以不同的方式运行您的代码,包括:Java 1.{5,6,7}(使用 AES);不同的 Base64 编解码器(Apache Commons Codec、DatatypeConverted、Base64);不同的字符集;在不同的 JVM 之间(通过套接字) …无济于事.我没有错误.

为了缩小问题范围,您可以在两端运行以下代码吗?

静态{System.out.println(System.getProperty("java.version"));对于(提供者提供者:Security.getProviders())System.out.println(提供者);}公共静态 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);}

(我知道您已经说明了您正在使用的 JDK 版本等内容,但不会有什么坏处.)

鉴于在您将密钥从客户端传输到服务器(或者可能是反向传输)时密钥没有损坏,那么如果:

  • 客户端抛出,但服务器没有——错误在客户端;
  • 客户端不会抛出,但服务器会抛出——错误在服务器端;
  • 客户端和服务器都抛出或都不抛出——需要进一步调查.

在任何情况下,如果抛出错误,请将整个堆栈跟踪发布到某处.错误 No installed provider supports this key: javax.crypto.spec.SecretKeySpec 告诉我们什么都没有(至少对我来说没有,而且我也无法重现这个特定的错误).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).

相关文章