1

一个用户在 Android Pie 中运行我的应用程序,他遇到了崩溃。Android N 有修复(来自 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"); }

但它给 Android Pie 带来了错误: java.security.NoSuchAlgorithmException: class configured for SecureRandom (provider: Crypto) cannot be found.

4

3 回答 3

0

我在实际过程中也遇到过这个问题。

谷歌对此问题的解释

如果您按名称或实例指定提供程序,例如 Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC") 或 Cipher.getInstance("AES/CBC/PKCS7PADDING", Security.getProvider("BC" ))——您在 Android P 中获得的行为将取决于您的应用程序所针对的 API 级别。对于针对 P 之前的 API 级别的应用程序,调用将返回 BC 实现并在应用程序日志中记录警告。对于面向 Android P 或更高版本的应用,调用将抛出 NoSuchAlgorithmException。

要解决此问题,您应该停止指定提供程序并使用默认实现。

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;
}

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;
}

这对我有用

于 2018-10-25T03:09:53.237 回答
0

我正在使用代码解密,如何使用 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();

谢谢 HieuHD

于 2018-10-16T03:58:47.060 回答
0

这是 Android Pie 兼容性的解决方案。

如果您需要解密之前加密的内容,这可以被视为兼容性的最后一种方法。

从 Jabari https://stackoverflow.com/a/12039611/5330492的方法 首先,在 Pie 下面的机器上从 SecretKey 获取字符串

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);
  }

使用上面的 SecretKey 字符串,最终代码是

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 */
于 2018-10-10T12:00:17.443 回答