What "SecretKeyFactory not available" does mean?

47,183

Solution 1

This is a verified java bug. See https://bugs.openjdk.java.net/browse/JDK-7022467

EDIT: Different java versions support different algorithms, you can also extend it with custom providers and so on. Oracle has a list for java 6 here http://docs.oracle.com/javase/6/docs/technotes/guides/security/SunProviders.html . For KeyFactory this is DSA.

Solution 2

You don't really need to use SecretKeyFactory. You can create an AES key with the following;

byte[] keyData = ........ 
SecretKeySpec key = new SecretKeySpec(keyData, "AES");

If you want to do password based encryption (PBE) then simply choose a secure hashing algorithm that gives you a hash the same size as the required key. For example, if you want a 256 bit key for AES, here is a method to build the key;

private Key buildKey(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
  MessageDigest digester = MessageDigest.getInstance("SHA-256");
  digester.update(password.getBytes("UTF-8"));
  byte[] key = digester.digest();
  SecretKeySpec spec = new SecretKeySpec(key, "AES");
  return spec;
}

Edit:
I would recommend against using MD5 and DES unless this is a play project, both have weaknesses and are considered obsolete.

Solution 3

Not all versions of Java provide a SecretKeyFactory for "AES" in their default providers.

If you want to generate a new key, choose the desired number of bits (128, 192, or 256) from a SecureRandom instance, and use that random number to initialize a SecretKeySpec instance.

If you are using password-based encryption, create a SecretKeyFactory for the "PBKDF2WithHmacSHA1" algorithm, and use it to initialize a SecretKeySpec instance as illustrated here.

Share:
47,183
yegor256
Author by

yegor256

Lab director at Huawei, co-founder at Zerocracy, blogger at yegor256.com, author of Elegant Objects book; architect of Zold.

Updated on July 22, 2022

Comments

  • yegor256
    yegor256 almost 2 years

    What's wrong with this?

    for (Object obj : java.security.Security.getAlgorithms("Cipher")) {
      System.out.println(obj);
    }
    javax.crypto.SecretKeyFactory.getInstance("AES");
    

    This is the output (JDK 1.6 on Mac OS 10.6):

    BLOWFISH
    ARCFOUR
    PBEWITHMD5ANDDES
    RC2
    RSA
    PBEWITHMD5ANDTRIPLEDES
    PBEWITHSHA1ANDDESEDE
    DESEDE
    AESWRAP
    AES
    DES
    DESEDEWRAP
    PBEWITHSHA1ANDRC2_40
    
    java.security.NoSuchAlgorithmException: AES SecretKeyFactory not available
     at javax.crypto.SecretKeyFactory.<init>(DashoA13*..)
     at javax.crypto.SecretKeyFactory.getInstance(DashoA13*..)
     ...
    
  • yegor256
    yegor256 over 12 years
    I'm getting the same exception for almost all algorithms from the list (only DES works).
  • brady
    brady almost 12 years
    Simply hashing the password is not a secure way to derive a password. Use a recognized key derivation algorithm (also provided by JCA) to convert text to a secret key.
  • Tom
    Tom about 11 years
    @erickson But the final 'evaluation' of the relevant issue (linked in the answer below) suggests to me that the above solution is the recommended solution for AES. How could we improve the above solution, without going back to SecretKeyFactory which is not going to support AES.
  • brady
    brady about 11 years
    @tom The final evaluation doesn't suggest using a single round of hashing to perform password-based encryption. Please see my answer for safely following the evaluation's guidance.
  • Tom
    Tom over 10 years
    Be careful about that combination - big android bug fixed in 4.4 means that pre & post 4.4 produce different results. android-developers.blogspot.ca/2013/12/…
  • brady
    brady over 10 years
    Don't be careful with PBKDF2WithHmacSHA1; it's the algorithm you should use, and decrypts messages encrypted with SunJCE. If you have to work with data that was encrypted using the old, buggy version of Android, then you'll have to be aware of the non-standard 8bit algorithm. If you are using SunJCE to decrypt messages encrypted with buggy Android implementations, you'll need to set the upper 8 bits of each char in the password to zero yourself, as it doesn't provide an algorithm with this behavior.
  • Tom
    Tom over 10 years
    I didn't say don't use it - I just said to take care, and since there is an issue with Android (and BouncyCastle too, I believe) I don't think that is unwarranted.
  • brady
    brady over 10 years
    That makes sense. I'm stressing the point because the leading answer has a horrible security flaw, simply using a hash function to derive a key.
  • VGR
    VGR over 2 years
  • jontro
    jontro over 2 years
    @VGR feel free to edit the answer!