Android数据加密的方式,按加密的内容是否可以还原,可以分为可逆加密和非可逆加密。
非可逆加密: 加密后的数据不能还原成原来的数据,如MD5,sha1。
可逆加密: 可逆加密有一个公钥和一个私钥,通过公钥加密,私钥解密。常用的有:RSA,AES。
MD5
-
使用场景:
1.一致性验证,比如下载某个文件,不知道文件是否下载完成,可以MD5进行校验。加密文件比较耗时,应放到子线程中。
2.密码的存储,如登陆注册这些,账号密码会保存到sp中,如果直接保存账号密码的MD5值。 -
代码实现:
/*** 使用md5方式进行加密* @return*/public static String digest(String content){StringBuilder builder = new StringBuilder();try {MessageDigest msgDitest = MessageDigest.getInstance("MD5");msgDitest.update(content.getBytes());byte[] digests = msgDitest.digest();//将每个字节转为16进制for (int i=0;i<digests.length;i++){builder.append(Integer.toHexString(digests[i] & 0xff +8));//+8为加盐操作}} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return builder.toString();}
RSA
- 加密原理:
1、随机选择两个大的质数P和Q,P不等于Q,计算出结果:N = PQ;
2、选择一个大于1,小于N的自然数E,E必须和(P-1)(Q-1)互素;
3、用公式计算出D:DE = mod(P-1)(Q-1);
4、销毁P和Q。最终得到的N,E就是公钥,D就是私钥了。 - 使用场景:
项目中一些敏感的数据,比如身份证号,银行卡号,支付密码等相关敏感信息可以加密后再传输到服务端,服务端使用私钥进行解密。
-密钥对的生成:
/*初始化KeyPairGenerator类,并获取到公钥和私钥*/byte[] publicKeyByte;byte[] prvateKtyByte;public void getKey() {try {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(“RSA”);//KeyPairGenerator类是java专门提供生成密钥对的一个类。keyPairGenerator.initialize(1024); //设置密钥对的大小KeyPair keyPair = keyPairGenerator.generateKeyPair();PrivateKey privateKey = keyPair.getPrivate();//获取私钥PublicKey publicKey = keyPair.getPublic();//获取公钥prvateKtyByte = privateKey.getEncoded();//私钥对应的字节数组publicKeyByte = publicKey.getEncoded(); //公钥对应的字节数组} catch (NoSuchAlgorithmException e) {e.printStackTrace();}}
-公钥加密:
public byte[] encryption(String content) {byte[] result = null;try {Cipher cipher = Cipher.getInstance("RSA");X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);cipher.init(Cipher.ENCRYPT_MODE, publicKey);result = cipher.doFinal(content.getBytes());} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeySpecException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();}return result;}
- 私钥解密:
public void decryption() {Cipher cipher = null;try {cipher = Cipher.getInstance("RSA");//私钥需要通过PKCS8EncodedKeySpec来读取PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(prvateKtyByte);KeyFactory keyFactory = KeyFactory.getInstance("RSA");//生成私钥PrivateKey privateKey = keyFactory.generatePrivate(keySpec);cipher.init(Cipher.DECRYPT_MODE, privateKey);//String content = "123456";byte[] input = encryption("123456");byte[] result = cipher.doFinal(input);} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (InvalidKeySpecException e) {e.printStackTrace();}}
AES
-
使用场景:AES是对称加密,加解密都是使用一个key,在项目中将一些敏感数据保存在本地,要使用时再取出来解密。
-
代码实现:
public class AesUtils {/*** @param* @return AES加密算法加密*/public static String encrypt(String seed, String key)throws Exception {byte[] rawKey = getRawKey(key.getBytes());byte[] result = encrypt(seed.getBytes("utf-8"), rawKey);return toHex(result);}public static byte[] encryptByte(String seed, String key)throws Exception {byte[] rawKey = getRawKey(key.getBytes());return encrypt(seed.getBytes("utf-8"), rawKey);}public static String decryptString(byte[] byteData, byte[] byteKey) throws Exception {byte[] rawKey = getRawKey(byteKey);byte[] result = decrypt(byteData, rawKey);return new String(result, "UTF8");}/**** AES加密算法加密* @param byteData 数据* @param byteKey key*/private static byte[] encrypt(byte[] byteData, byte[] byteKey) throws Exception {return Ase(byteData, byteKey, Cipher.ENCRYPT_MODE);}/**** AES加密算法解密* @param byteData 数据* @param byteKey key*/private static byte[] decrypt(byte[] byteData, byte[] byteKey) throws Exception {return Ase(byteData, byteKey, Cipher.DECRYPT_MODE);}/***** @param byteData* @param byteKey* @param opmode*/private static byte[] Ase(byte[] byteData, byte[] byteKey, int opmode) throws Exception {Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");SecretKeySpec skeySpec = new SecretKeySpec(byteKey, "AES");cipher.init(opmode, skeySpec);byte[] decrypted = cipher.doFinal(byteData);return decrypted;}private static byte[] getRawKey(byte[] seed) throws Exception {KeyGenerator kgen = KeyGenerator.getInstance("AES");SecureRandom sr = null;int sdk_version = android.os.Build.VERSION.SDK_INT;if (sdk_version > 23) { // Android 6.0 以上sr = SecureRandom.getInstance("SHA1PRNG", new CryptoProvider());} else if (sdk_version >= 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 availableSecretKey skey = kgen.generateKey();byte[] raw = skey.getEncoded();return raw;}public static 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");}}private static String toHex(byte[] buf) {final String HEX = "0123456789ABCDEF";if (buf == null)return "";StringBuffer result = new StringBuffer(2 * buf.length);for (int i = 0; i < buf.length; i++) {result.append(HEX.charAt((buf[i] >> 4) & 0x0f)).append(HEX.charAt(buf[i] & 0x0f));}return result.toString();}private static byte[] toByte(String hexString) {int len = hexString.length() / 2;byte[] result = new byte[len];for (int i = 0; i < len; i++)result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),16).byteValue();return result;}
}