道客优

1234
android在AES加密时出现:no such provider: Crypto 的问题
2019-03-03 阅读:964

根本就没存进去,具体的代码出错在下面这个方法中:

    @SuppressLint("TrulyRandom")    private static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = null;        if (android.os.Build.VERSION.SDK_INT >= 17) {
            sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
        } else {
            sr = SecureRandom.getInstance("SHA1PRNG");
        }
        sr.setSeed(seed);
        kgen.init(128, sr); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();        byte[] raw = skey.getEncoded();        return raw;
    }

原来android7.0中已经没有了“Crypto”,网上有人说

把上面的方法做如下替换

sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");

替换为

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

那么getRawKey方法就变成以下的了:

    @SuppressLint("TrulyRandom")    
    private static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = null;        
        if (android.os.Build.VERSION.SDK_INT >= 17) {
            sr = SecureRandom.getInstance("SHA1PRNG", new CryptoProvider());
        } else {
            sr = SecureRandom.getInstance("SHA1PRNG");
        }
        sr.setSeed(seed);
        kgen.init(128, sr); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();        byte[] raw = skey.getEncoded();        return raw;
    }

这样还没完,我们需要自己写一个CryptoProvider类,CryptoProvider.java代码如下:

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

亲测,这种方法根本不能解决问题,按照官网的说法不能通过getInstance的方法获取实例,只能new一个新的对象。

public static byte[] getRawKey(byte[] seed) throws Exception {

        KeyGenerator kgen = KeyGenerator.getInstance(AES);

        //for android

        SecureRandom sr = new SecureRandom();

        sr.setSeed(seed);

        kgen.init(128, sr); //256 bits or 128 bits,192bits

        //AES中128位密钥版本有10个加密循环,192比特密钥版本有12个加密循环,256比特密钥版本则有14个加密循环。

        SecretKey skey = kgen.generateKey();

        byte[] raw = skey.getEncoded();

        return raw;

    }

但是这样在解密时生成key,和加密时的不同造成无法解密。最后只能生成key把key的值写死到代码里。

推荐阅读: