Fix for Security “Crypto” on Nougat does not work for Pie

扶醉桌前 提交于 2019-12-23 02:02:45

问题


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.


回答1:


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 */



回答2:


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




回答3:


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



来源:https://stackoverflow.com/questions/51799526/fix-for-security-crypto-on-nougat-does-not-work-for-pie

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!