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

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

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”

有任何想法吗?

我用不同的方式运行你的代码: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没有告诉我们(至少对我来说它没有,我也无法重现这个特定的错误)。

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

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

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