Android使用KeyStore对数据进行加密的示例代码
谈到Android安全性话题,AndroidDevelopers官方网站给出了许多很好的建议和讲解,涵盖了存储数据、权限、网络、处理凭据、输入验证、处理用户数据、加密等方方面面
密钥的保护以及网络传输安全应该是移动应用安全最关键的内容。Android提供大量用来保护数据的加密算法,例如Cipher类中提供了AES和RSA算法,再例如安全随机数生成器SecureRandom给KeyGenerator提供了更加可靠的初始化参数,避免离线攻击等等。
而如果需要存储密钥以供重复使用,Android提供了KeyStore等可以长期存储和检索加密密钥的机制,AndroidKeyStore系统特别适合于存储加密密钥。”AndroidKeyStore”是KeyStore的一个子集,存进AndroidKeyStore的key将受到签名保护,并且这些key是存在系统里的,而不是在App的data目录下,依托于硬件的KeyChain存储,可以做到privatekey一旦存入就无法取出,总之,每个App自己创建的key,别的应用是访问不到的。
KeyStore提供了两个能力:
有了这两个能力,我们的密钥保护就变得很容易了,你只需要:
在应用安装后第一次运行时,生成一个随机密钥,并存入KeyStore
当你想存储一个数据,便从KeyStore中取出之前生成的随机密钥,对你的数据进行加密,加密完成后,已完成加密的数据可以随意存储在任意地方,比如SharePreferences,此时即使它被他人读取到,也无法解密出你的原数据,因为他人取不到你的密钥
当你需要拿到你的原数据,只需要从SharePreferences中读取你加密后的数据,并从KeyStore取出加密密钥,使用加密密钥对“加密后的数据”进行解密即可
其中加密算法可以使用CipherAES来保证安全性,不要使用自己创造的加密算法。
这就是使用KeyStore的一整套流程,另外KeyStore还可以用来做数据签名和签名验证,就像一个黑匣子一样,具体可以自行搜索了解。
KeyStore适于存储运行时生产获取到的数据,比如运行时,用户输入的密码,或者服务端传下来的token,但无法用于存储我们需要预设在App内的APIkey/secret,对于这类需要预设的固定密钥,我将介绍一种十分安全、难破解的保护方式。
加密:
publicStringencryptString(StringneedEncryptWord,Stringalias){ if(!"".equals(alias)&&!"".equals(needEncryptWord)){ if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN_MR2){ initKeyStore(alias); } StringencryptStr=""; byte[]vals=null; try{ KeyStore.PrivateKeyEntryprivateKeyEntry=(KeyStore.PrivateKeyEntry)keyStore.getEntry(alias,null); //RSAPublicKeypublicKey=(RSAPublicKey)privateKeyEntry.getCertificate().getPublicKey(); if(needEncryptWord.isEmpty()){ //Toast.makeText(this,"Entertextinthe'InitialText'widget",Toast.LENGTH_LONG).show(); returnencryptStr; } //CipherinCipher=Cipher.getInstance("RSA/ECB/PKCS1Padding","AndroidOpenSSL"); CipherinCipher=Cipher.getInstance("RSA/ECB/PKCS1Padding"); //inCipher.init(Cipher.ENCRYPT_MODE,publicKey); inCipher.init(Cipher.ENCRYPT_MODE,privateKeyEntry.getCertificate().getPublicKey()); ByteArrayOutputStreamoutputStream=newByteArrayOutputStream(); CipherOutputStreamcipherOutputStream=newCipherOutputStream( outputStream,inCipher); cipherOutputStream.write(needEncryptWord.getBytes("UTF-8")); cipherOutputStream.close(); vals=outputStream.toByteArray(); }catch(Exceptione){ e.printStackTrace(); } returnBase64.encodeToString(vals,Base64.DEFAULT); } return""; }
解密:
publicStringdecryptString(StringneedDecryptWord,Stringalias){ if(!"".equals(alias)&&!"".equals(needDecryptWord)){ if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN_MR2){ initKeyStore(alias); } StringdecryptStr=""; try{ KeyStore.PrivateKeyEntryprivateKeyEntry=(KeyStore.PrivateKeyEntry)keyStore.getEntry(alias,null); //RSAPrivateKeyprivateKey=(RSAPrivateKey)privateKeyEntry.getPrivateKey(); //Cipheroutput=Cipher.getInstance("RSA/ECB/PKCS1Padding","AndroidOpenSSL"); Cipheroutput=Cipher.getInstance("RSA/ECB/PKCS1Padding"); //output.init(Cipher.DECRYPT_MODE,privateKey); output.init(Cipher.DECRYPT_MODE,privateKeyEntry.getPrivateKey()); CipherInputStreamcipherInputStream=newCipherInputStream( newByteArrayInputStream(Base64.decode(needDecryptWord,Base64.DEFAULT)),output); ArrayList<Byte>values=newArrayList<>(); intnextByte; while((nextByte=cipherInputStream.read())!=-1){ values.add((byte)nextByte); } byte[]bytes=newbyte[values.size()]; for(inti=0;i<bytes.length;i++){ bytes[i]=values.get(i).byteValue(); } decryptStr=newString(bytes,0,bytes.length,"UTF-8"); }catch(Exceptione){ e.printStackTrace(); } returndecryptStr; } return""; }
源码下载地址,我已经将加密解密封装进了工具类,并对Android7.0的兼容也处理了
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。