14

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?

Cody S
  • 4,744
  • 8
  • 33
  • 64
  • 2
    What providers do you have installed on the server? `for (Provider p : Security.getProviders()) System.out.println(p.getName());` – erickson Dec 02 '11 at 20:34
  • Also, what is the definition of `SYMMETRIC_ALGORITHM`? – erickson Dec 02 '11 at 20:35
  • @erickson Dangit, I tried to replace the SYMMETRIC_ALGORITHM strings. They are final Strings defined (both on server and client) as "AES". I will try the provider code you showed me and get back to you – Cody S Dec 02 '11 at 20:46
  • @erickson Output: `SUN SunRsaSign SunJSSE SunJCE SunJGSS SunSASL XMLDSig SunPCSC SunPKCS11-NSS ` – Cody S Dec 02 '11 at 20:52
  • Have you installed the policy files for unlimited crypto from Oracle? Can you try with them installed? – Maarten Bodewes Dec 04 '11 at 23:54
  • @owlstead I haven't tried them. Because we are doing crypto elsewhere on the server with 128bit AES keys successfully without them, I assumed that I didn't need them. As a troubleshooting step, I can try it though. I don't believe my company would be too stoked to have to add them permanently. I'll give it a shot and report back. – Cody S Dec 05 '11 at 19:03
  • I think it's not required either, but it's a pretty simple step to take, and we are talking about javax.crypto.Cipher here, so installing them makes sense anyway (otherwise you decide to use 256 bit keys and run into trouble later on). – Maarten Bodewes Dec 05 '11 at 21:33
  • As another step, could you try and use SecretKeyFactory and feed it the SecretKeySpec? It would be interesting to see what error would be returned, (if any). BTW, as there is a SunPKCS11 provider installed, it might be that someone has been mucking with Java security to get things working. Sorry, no direct answers, this is basically troubleshooting as it *is* an odd situation. – Maarten Bodewes Dec 05 '11 at 21:47
  • Have you tried the SecretKeyFactory step yet? You can see from the one "answer" that this is - as expected - an entirely strange situation. – Maarten Bodewes Dec 17 '11 at 15:57
  • @CodyS It would be nice to know if the problem is solved or it still persist. – Kohányi Róbert Jan 10 '12 at 06:08
  • @KohányiRóbert The problem neither persists, nor was it solved. It sort of just went away for the time being. We'll see if it crops back up later down the line. – Cody S Jan 11 '12 at 00:56

3 Answers3

9

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

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

shoover
  • 3,071
  • 1
  • 29
  • 40
9

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

Kohányi Róbert
  • 9,791
  • 4
  • 52
  • 81
  • Sorry. I asked this question seemingly forever ago...and since then, the problem has been resolved. While I don't recall your answer being a part of the solution...It is still a good answer. Thanks for helping out :) – Cody S Apr 10 '12 at 17:18
  • @CodyS You've actually also forgot the fact that you've already made a response similar to this in the comment section of the question. :D No biggie tho'! – Kohányi Róbert Apr 10 '12 at 17:40
  • I have the same problem, and your code I get the same error. Although I'm trying to use AES_192/GCM/NoPadding. – Thayne Jul 19 '19 at 19:06
  • @Thayne Well, hard to tell with only the information you gave. Which JDK? Which platform? What's the *exact* error? What's the *exact* code you've used? – Kohányi Róbert Jul 21 '19 at 10:54
1

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

Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56