Android 采用keyStore的方式非对称加密,配合Rxjava2更好用
来源:互联网 发布:手机淘宝取消 私人定制 编辑:程序博客网 时间:2024/05/17 22:35
加密的代码如下
public class RxSecureStorage { private static final String AndroidKeyStore = "AndroidKeyStore"; private Context context; private String alias; private KeyStore keyStore; private RxSharedPreferences sharedPreferences; public RxSecureStorage(Context context, String alias) { this.context = context.getApplicationContext(); this.alias = alias; SharedPreferences prefs = context.getSharedPreferences( String.format("%s-%s", context.getPackageName(), alias), Context.MODE_PRIVATE); this.sharedPreferences = RxSharedPreferences.create(prefs); } public static RxSecureStorage create(Context context, String alias) { return new RxSecureStorage(context, alias); } private void initIfNecessary() throws Exception { if (keyStore != null) { return; } try { keyStore = KeyStore.getInstance(AndroidKeyStore); keyStore.load(null); if (!keyStore.containsAlias(alias)) { // Generate a key pair for encryption Calendar start = Calendar.getInstance(); Calendar end = Calendar.getInstance(); end.add(Calendar.YEAR, 30); KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context.getApplicationContext()) .setAlias(alias) .setSubject(new X500Principal("CN=" + alias)) .setSerialNumber(BigInteger.TEN) .setStartDate(start.getTime()) .setEndDate(end.getTime()) .build(); KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", AndroidKeyStore); kpg.initialize(spec); kpg.generateKeyPair(); } } catch (Exception e) { throw new Exception("Failed to initialize this RxSecureStorage instance.", e); } } public Single<byte[]> encrypt(final byte[] data) { return Single.fromCallable( new Callable<byte[]>() { @Override public byte[] call() throws Exception { initIfNecessary(); ByteArrayOutputStream outputStream = null; CipherOutputStream cipherOutputStream = null; try { KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, null); PublicKey publicKey = privateKeyEntry.getCertificate().getPublicKey(); Cipher input = getCipher(); input.init(Cipher.ENCRYPT_MODE, publicKey); outputStream = new ByteArrayOutputStream(); cipherOutputStream = new CipherOutputStream(outputStream, input); cipherOutputStream.write(data); closeQuietely(cipherOutputStream); return outputStream.toByteArray(); } catch (Exception e) { throw new Exception("Failed to encrypt data with alias" + alias, e); } finally { closeQuietely(cipherOutputStream); closeQuietely(outputStream); } } }) .observeOn(Schedulers.computation()); } public Single<String> encryptString(String text) { byte[] textBytes; try { textBytes = text.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { return Single.error(new Exception("Failed convert text to bytes.", e)); } return encrypt(textBytes) .map( new Function<byte[], String>() { @Override public String apply(byte[] encryptedData) throws Exception { return Base64.encodeToString(encryptedData, Base64.DEFAULT); } }) .observeOn(Schedulers.computation()); } public Single<byte[]> decrypt(final byte[] encryptedData) { return Single.fromCallable( new Callable<byte[]>() { @Override public byte[] call() throws Exception { initIfNecessary(); CipherInputStream cipherInputStream = null; ByteArrayOutputStream bos = null; try { KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, null); PrivateKey privateKey = privateKeyEntry.getPrivateKey(); Cipher output = getCipher(); output.init(Cipher.DECRYPT_MODE, privateKey); cipherInputStream = new CipherInputStream(new ByteArrayInputStream(encryptedData), output); bos = new ByteArrayOutputStream(); byte[] buffer = new byte[512]; int read; while ((read = cipherInputStream.read(buffer)) != -1) { bos.write(buffer, 0, read); } return bos.toByteArray(); } catch (Exception e) { throw new Exception("Failed to decrypt data with " + alias, e); } finally { closeQuietely(cipherInputStream); closeQuietely(bos); } } }) .observeOn(Schedulers.computation()); } public Single<String> decryptString(String encryptedText) { byte[] textBytes = new byte[0]; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.FROYO) { textBytes = Base64.decode(encryptedText, Base64.DEFAULT); } return decrypt(textBytes) .map( new Function<byte[], String>() { @Override public String apply(byte[] encryptedData) throws Exception { return new String(encryptedData, 0, encryptedData.length); } }) .observeOn(Schedulers.computation()); } public Observable<byte[]> getBytes(String name) { return sharedPreferences .getString(name) .asObservable() .map( new Function<String, byte[]>() { @Override public byte[] apply(String base64Value) throws Exception { byte[] encryptedValue = Base64.decode(base64Value, Base64.DEFAULT); return decrypt(encryptedValue).blockingGet(); } }); } public Single<Boolean> putBytes(final String name, @Nullable byte[] value) { if (value == null) { sharedPreferences.getString(name).delete(); return Single.just(false); } return encrypt(value) .map( new Function<byte[], Boolean>() { @Override public Boolean apply(byte[] encryptedData) throws Exception { String encryptedString = Base64.encodeToString(encryptedData, Base64.DEFAULT); sharedPreferences.getString(name).set(encryptedString); return true; } }); } public Observable<String> getString(String name) { return sharedPreferences .getString(name) .asObservable() .map( new Function<String, String>() { @Override public String apply(String encryptedValue) throws Exception { if (encryptedValue == null || encryptedValue.trim().isEmpty()) { return null; } return decryptString(encryptedValue).blockingGet(); } }); } public Single<Boolean> putString(final String name, @Nullable String value) { if (value == null) { sharedPreferences.getString(name).delete(); return Single.just(false); } return encryptString(value) .map( new Function<String, Boolean>() { @Override public Boolean apply(String encryptedValue) throws Exception { sharedPreferences.getString(name).set(encryptedValue); return true; } }); } public void dispose() { this.context = null; this.alias = null; this.keyStore = null; this.sharedPreferences = null; } private static Cipher getCipher() { try { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { // below android m // error in android 6: InvalidKeyException: Need RSA private or public key return Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); } else { // error in android 5: NoSuchProviderException: Provider not available: AndroidKeyStoreBCWorkaround return Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidKeyStoreBCWorkaround"); } } catch (Exception exception) { throw new RuntimeException("getCipher: Failed to get an instance of Cipher", exception); } } private static void closeQuietely(Closeable c) { try { c.close(); } catch (Throwable ignored) { } }}
使用
1,初始化
RxSecureStorage secureStorage = RxSecureStorage.create(this, "alias_name")
2,加密
secureStorage .encryptString("string to encrypt") .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { // Use the resulting string }, error -> { // Handle error });
3,解密
secureStorage .decryptString("9yIfhiwf3eDENxI1XG/XWYZOPc5RH6B9ez9y7I7BtEsig==") .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { // Use the resulting string }, error -> { // Handle error });
4,保存一些隐私数据
secureStorage.putString("key", "hello, world!").subscribe();
获取隐私数据
secureStorage .getString("key") .subscribe( latest -> { // preference was changed, here's the latest decryped value });
阅读全文
0 0
- Android 采用keyStore的方式非对称加密,配合Rxjava2更好用
- Android与服务器交互的方式中的对称加密和非对称加密
- spring-cloud-config 非对称加密 keystore 文件加载异常
- Android与服务器交互方式中的对称加密和非对称加密
- Android的非对称加密与MD5加密
- Android的非对称加密与MD5加密
- 以DH的方式实现非对称加密
- 以RSA的方式实现非对称加密
- Android安全加密:非对称加密
- Android安全加密:非对称加密
- Android安全加密:非对称加密
- 密码学---非对称密码的加密解密采用公钥还是密钥
- Java Web 登录采用非对称加密(RSA算法)
- Java Web 登录采用非对称加密(RSA算法)
- Java Web 登录采用非对称加密(RSA算法)
- android Java语言非对称加密的实现
- 加密方式-非对称加密(RSA加密与签名)
- Android安全-对称加密和非对称加密
- Android增量更新
- org.apache.spark.shuffle.MetadataFetchFailedException:Missing an output location for shuffle 5
- oracle表分区(转)
- kubernetes代码编译
- 2017年第二十一届中国国际宠物水族用品展览会(CIPS2017)会刊(参展商名录)
- Android 采用keyStore的方式非对称加密,配合Rxjava2更好用
- 定期存款转消费卡项目需求书
- n元语法
- 【设计模式】模板模式(Template Pattern)
- nats.uno
- 黑盒测试用例设计
- 深入理解ArrayList 和 LinkedList 区别
- Redis 学习笔记(十四)Redis Cluster介绍与搭建
- 2017-12月