Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 265
Cody S Avatar asked Dec 02 '11 20:12

Cody S


1 Answers

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

like image 99
Kohányi Róbert Avatar answered Oct 27 '22 00:10

Kohányi Róbert