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


我正在尝试设置128位AES加密,并且我在Cipher.init上抛出一个异常:

No installed provider supports this key: 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的说法,构成SecretKeys的字节是相同的,长度为16个字节(实际上,据我所知,对象是相同的)。

我知道无限强度JCE的东西,但我不会觉得我需要128位AES。

客户端:java版“1.6.0_26”

服务器端:java版“1.6.0_20”

有任何想法吗?


936
2017-12-02 20:30


起源

您在服务器上安装了哪些提供商? for (Provider p : Security.getProviders()) System.out.println(p.getName()); - erickson
另外,定义是什么 SYMMETRIC_ALGORITHM? - erickson
@erickson Dangit,我试图替换SYMMETRIC_ALGORITHM字符串。它们是最终的字符串(在服务器和客户端上)定义为“AES”。我将尝试您向我展示的提供商代码并回复您 - Cody S
@erickson输出: SUN SunRsaSign SunJSSE SunJCE SunJGSS SunSASL XMLDSig SunPCSC SunPKCS11-NSS - Cody S
您是否安装了Oracle无限加密的策略文件?你可以尝试安装它们吗? - Maarten Bodewes


答案:


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

要缩小问题范围,可以运行以下代码吗?  结束?

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);
}

(我知道你已经说过你正在使用的JDK版本和东西,但它不会受到伤害。)

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

  • 客户端抛出,但服务器没有 - 错误在客户端;
  • 客户端不抛出,但服务器确实 - 错误在服务器端;
  • 客户端和服务器都抛出或两者都不需要进一步调查。

在任何情况下,如果抛出错误,请发布 整个 堆栈跟踪某处。错误 No installed provider supports this key: javax.crypto.spec.SecretKeySpec 没有告诉我们(至少对我来说它没有,我也无法重现这个特殊的错误)。


7
2017-12-17 09:01



抱歉。我似乎永远问过这个问题......从那时起,问题就解决了。虽然我不记得你的答案是解决方案的一部分......但它仍然是一个很好的答案。谢谢你帮忙:) - Cody S
@CodyS你实际上也忘记了你已经在问题的评论部分做出类似回应的事实。 :D没什么大不了的! - Kohányi Róbert


此错误可能表示您需要安装JCE(Java Cryptography Extension)。

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


6
2017-08-20 11:51





提供错误的密钥时,我会发生此错误 SecretKeySpec 构造函数。


1
2018-04-19 13:12