1

A user run my application in Android Pie, he got the crash.There was fix for Android N (fix from varotariya vajsi):

SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", new CryptoProvider());
...

public final class CryptoProvider extends Provider { /** * Creates a Provider and puts parameters */ public CryptoProvider() { super("Crypto", 1.0, "HARMONY (SHA1 digest; SecureRandom; SHA1withDSA signature)"); put("SecureRandom.SHA1PRNG", "org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl"); put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); } But it gives error for Android Pie: java.security.NoSuchAlgorithmException: class configured for SecureRandom (provider: Crypto) cannot be found.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Vadim Star
  • 57
  • 1
  • 5

3 Answers3

0

Here is a solution for compatibility in Android Pie.

This could be considered as last method for compatibility if you need to decrypt something encrypted before.

From the method from Jabari https://stackoverflow.com/a/12039611/5330492 First, get the string from SecretKey on machines below Pie

SecretKey secretKey;
String stringKey;

try {secretKey = KeyGenerator.getInstance("AES").generateKey();}
catch (NoSuchAlgorithmException e) {/* LOG YOUR EXCEPTION */}

if (secretKey != null) {
    stringKey = Base64.encodeToString(secretKey.getEncoded(), Base64.DEFAULT);
    Log.i(TAG, "stringKey = " + stringKey);
  }

With the SecretKey string from above, the final code is

SecretKey secretKey;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        String stringKey = "string got from machines below Pie";
        byte[] encodedKey     = Base64.decode(stringKey, Base64.DEFAULT);
        secretKey= new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
} else {
    /* get the SecretKey as before Pie */
}
/* Continue the decryption process */
WeiHung
  • 109
  • 2
  • 10
0

I am using a code decrypt, how to convert compile with android PIE :

 KeyGenerator kgen = KeyGenerator.getInstance("AES");
        // SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        SecureRandom sr;
        if (Build.VERSION.SDK_INT >= 24) {
            sr = SecureRandom.getInstance("SHA1PRNG", new CryptoProvider());
        } else {
            sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
        }
        sr.setSeed(seed);
        kgen.init(128, sr); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();

Thanks HieuHD

0

I also encountered this problem in the actual process.

Google explanation of this issue

If you specify the provider by name or by instance—for example, Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC") or Cipher.getInstance("AES/CBC/PKCS7PADDING", Security.getProvider("BC"))—the behavior you get in Android P will depend on what API level your application targets. For apps targeting an API level before P, the call will return the BC implementation and log a warning in the application log. For apps targeting Android P or later, the call will throw NoSuchAlgorithmException.

To resolve this, you should stop specifying a provider and use the default implementation.

before

public static byte[] getAESKey(){
    String seed = UUID.randomUUID().toString();
    try{
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        String SHA1PRNG = "SHA1PRNG";
        SecureRandom sr;
        CryptoProvider provider = new CryptoProvider();
        sr = SecureRandom.getInstance(SHA1PRNG, provider);
        sr.setSeed(seed.getBytes());
        int keyLength = 128;
        kgen.init(keyLength,sr);
        SecretKey sKey = kgen.generateKey();
        byte[] aesKey = sKey.getEncoded();
        return aesKey;
    }catch(Exception e){
        e.printStackTrace();
    }
    return null;
}

after

public static byte[] getAESKey(){
    String seed = UUID.randomUUID().toString();
    try{
        KeyGenerator kGen = KeyGenerator.getInstance("AES");
        SecureRandom sr;
        sr = new SecureRandom();
        sr.setSeed(seed.getBytes());
        int keyLength = 128;
        kGen.init(keyLength,sr);
        SecretKey sKey = kGen.generateKey();
        return sKey.getEncoded();
    }catch(Exception e){
        e.printStackTrace();
    }
    return null;
}

and it's work for me

  • I actually use `Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding", "BC")` , and didn't notice any crash when using it. Should I use `Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding")` when on P and above? How come no exception is thrown? – android developer Sep 11 '19 at 13:00