AES Crypto 在 Android P(Android 9.0) 被删除 解决方案

开发工具:Android Studio

 

项目中若使用 SecureRandom.getInstance("SHA1PRNG", "Crypto") ,会给出以下警告:

The Crypto provider has been deleted in Android P (and was deprecated in Android N), so the code will crash. less... (Ctrl+F1) 
The Crypto provider has been completely removed in Android P (and was deprecated in an earlier release). This means that the code will throw a NoSuchProviderException and the app will crash. Even if the code catches that exception at a higher level, this is not secure and should not be used. 

即:Crypto provider 在 Android N(7.0)中已弃用,在Android P(9.0) 中已删除。

附相关上下文参考代码:

byte[] lSeedBytes = "password".getBytes();
SecureRandom lSecureRandom = SecureRandom.getInstance("SHA1PRNG", "Crypto");
KeyGenerator lKeyGenerator = KeyGenerator.getInstance("AES");
lSecureRandom.setSeed(lSeedBytes);
lKeyGenerator.init(256, lSecureRandom);
SecretKey lSecretKey = lKeyGenerator.generateKey();
byte[] lResultEncoded = lSecretKey.getEncoded();

两种情况:

1, targetSdkVersion < 24 时,在Android P 以上的设备会出现: java.security.NoSuchProviderException: no such provider: Crypto 

2,targetSdkVersion >= 24 时,在Android N 以上的设备会出现: java.security.NoSuchProviderException: no such provider: Crypto

此问题官方已经给出了参考方案: https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html

但只给出了部分示例代码,对于存储,并未提供相关代码,如需要,可参考以下:

private static byte[] mSaltCache;
private static byte[] getSecretKeyEncoded(String password) throws Exception {
    int iterationCount = 1000;
    int saltLength = 32; // bytes; should be the same size as the output (256 / 8 = 32)
    int keyLength = 256; // 256-bits for AES-256, 128-bits for AES-128, etc
    if (mSaltCache == null || mSaltCache.length != saltLength) {
        SharedPreferences lSP = Application.getInstance().getSharedPreferences("crypto_info", Context.MODE_PRIVATE);
        String lSaveStr = lSP.getString("salt", "");
        if (!TextUtils.isEmpty(lSaveStr)) {
            mSaltCache = toArr(lSaveStr);
        }
        if (mSaltCache == null || mSaltCache.length != saltLength) {
            byte[] salt = new byte[saltLength]; // Should be of saltLength
            SecureRandom random = new SecureRandom();
            random.nextBytes(salt);
            lSP.edit().putString("salt", toStr(salt)).commit();
            mSaltCache = salt;
        }
    }
    KeySpec keySpec = new PBEKeySpec(password.toCharArray(), mSaltCache, iterationCount, keyLength);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
    SecretKey key = new SecretKeySpec(keyBytes, "AES");
    return key.getEncoded();
}

工具方法:

public static String toStr(byte[] aBytes) {
    return toStr(aBytes, null);
}

public static String toStr(byte[] aBytes, String aSplit) {
    if (aBytes == null) return null;
    int lLength = aBytes.length;
    if (lLength <= 0) return "";
    if (TextUtils.isEmpty(aSplit)) aSplit = ",";
    StringBuilder lSB = new StringBuilder();
    for (int i = 0; i < lLength; i++) {
        lSB.append(String.valueOf(aBytes[i]));
        if (i != lLength - 1) lSB.append(aSplit);
    }
    return lSB.toString();
}

public static byte[] toArr(String aStr) {
    return toArr(aStr, null, (byte) 0);
}

public static byte[] toArr(String aStr, String aSplit, byte aDefaultValue) {
    if (TextUtils.isEmpty(aStr)) return null;
    if (TextUtils.isEmpty(aSplit)) aSplit = ",";
    String[] lItems = aStr.split(aSplit);
    int lLength = lItems.length;
    byte[] lResult = new byte[lLength];
    for (int i = 0; i < lLength; i++) {
        try {
            lResult[i] = Byte.parseByte(lItems[i]);
        } catch (Exception e) {
            lResult[i] = aDefaultValue;
        }
    }
    return lResult;
}

以上代码在官方示例基础上进行简单修改,仅供参考。

 

其他方案:

网上流传最多的一种方式为:

将: 

SecureRandom.getInstance("SHA1PRNG", "Crypto")

修改为:

SecureRandom.getInstance("SHA1PRNG", new CryptoProvider());
public class CryptoProvider extends Provider {
    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");
    }
}

 

但此方式仅在 24 <= targetSdkVersion < 28 时,在 Android N 到 Android P 之间生效。

 

 

原文地址: https://blog.csdn.net/u011859715/article/details/83784238

尊重原创,转载请声明出处,谢谢!

 

 

 

你可能感兴趣的:(Android,Bug)