安卓中,不管是内网还是外网,数据的传输首要考虑就是安全问题,尤其是用户信息,以及各种密码等敏感信息。
所以说,对数据的加密是很有必要的,尤其是当下物联网蓬勃发展的今天,数据安全尤为重要。

因此本人总结了一下安卓中几种加密方式的实现:

① MD5:一种不可逆的加密算法,常用于只需加密无需解密的数据上,比如用户密码,也常用来保证数据的完整性,因为数据被篡改后,其加密后的MD5也会随之改变,对比篡改前的MD5可确定数据是否完整;

public final static String getMD5String(String s) {final char HEX_DIGITS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8','9', 'A', 'B', 'C', 'D', 'E', 'F' };if (s == null)return null;try {MessageDigest mdInst = MessageDigest.getInstance("MD5");mdInst.update(s.getBytes());byte[] md = mdInst.digest();int len = md.length;StringBuilder buf = new StringBuilder(len * 2);for (int j = 0; j < len; j++) {buf.append(HEX_DIGITS[(md[j] >> 4) & 0x0f]);buf.append(HEX_DIGITS[md[j] & 0x0f]);}return buf.toString();} catch (Exception e) {e.printStackTrace();}return null;}

② DES:对称加密算法;

 /*** 返回可逆算法DES的密钥** @param key 前8字节将被用来生成密钥。* @return 生成的密钥* @throws Exception*/public static Key getDESKey(byte[] key) throws Exception {DESKeySpec des = new DESKeySpec(key);SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");return keyFactory.generateSecret(des);}/*** 根据指定的密钥及算法,将字符串进行解密。** @param data      要进行解密的数据,它是由原来的byte[]数组转化为字符串的结果。* @param key       密钥。* @param algorithm 算法--"DES/CBC/PKCS5Padding"* @return 解密后的结果。它由解密后的byte[]重新创建为String对象。如果解密失败,将返回null。* @throws Exception*/public static String decrypt(String data, Key key, String algorithm)throws Exception {Cipher cipher = Cipher.getInstance(algorithm);cipher.init(Cipher.DECRYPT_MODE, key);String result = new String(cipher.doFinal(StringUtils.hexStringToByteArray(data)), "utf8");return result;}/*** 根据指定的密钥及算法对指定字符串进行可逆加密。** @param data      要进行加密的字符串。* @param key       密钥。* @param algorithm 算法。* @return 加密后的结果将由byte[]数组转换为16进制表示的数组。如果加密过程失败,将返回null。*/public static String encrypt(String data, Key key, String algorithm)throws Exception {Cipher cipher = Cipher.getInstance(algorithm);cipher.init(Cipher.ENCRYPT_MODE, key);return StringUtils.byteArrayToHexString(cipher.doFinal(data.getBytes("utf8")));}/*** byte[]数组转换为16进制的字符串** @param data 要转换的字节数组* @return 转换后的结果*/public static final String byteArrayToHexString(byte[] data) {StringBuilder sb = new StringBuilder(data.length * 2);for (byte b : data) {int v = b & 0xff;if (v < 16) {sb.append('0');}sb.append(Integer.toHexString(v));}return sb.toString().toUpperCase(Locale.getDefault());}/*** 16进制表示的字符串转换为字节数组** @param s 16进制表示的字符串* @return byte[] 字节数组*/public static byte[] hexStringToByteArray(String s) {int len = s.length();byte[] d = new byte[len / 2];for (int i = 0; i < len; i += 2) {// 两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个进制字节d[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));}return d;}

③ AES:对称加密算法,为了防止网络(包含内网和外网)传递AES加密的秘文时导致的数据丢失(last block incomplete in decryption),一般需对秘文做base64处理,加密时候需要添加一个类似bcprov-jdk的库和两个policy文件,解密则不需要,
由于客户端携带了密钥,静态的密钥存在于客户端总是不安全的,那么可以考虑ECDH公钥交换协商随机密钥,基点或者全部逻辑加密算法写在加壳的SO里,此随机密钥可作为数据aes加密的密钥,这样可保证安全,当然亦可考虑使用非对称加密算法。
AES128和AES256主要区别是密钥长度不同(分别是128bits,256bits)、加密处理轮数不同(分别是10轮,14轮),后者强度高于前者;

 /** * 密钥算法 * java6支持56位密钥,bouncycastle支持64位 * */ public static final String KEY_ALGORITHM="AES";  /** * 加密/解密算法/工作模式/填充方式 *  * JAVA6 支持PKCS5PADDING填充方式 * Bouncy castle支持PKCS7Padding填充方式 * */ public static final String CIPHER_ALGORITHM="AES/ECB/PKCS7Padding";  /** *  * 生成密钥,java6只支持56位密钥,bouncycastle支持64位密钥 * @return byte[] 二进制密钥 * */ public static byte[] initkey() throws Exception{  return new byte[] { 0x08, 0x08, 0x04, 0x0b, 0x02, 0x0f, 0x0b, 0x0c,0x01, 0x03, 0x09, 0x07, 0x0c, 0x03, 0x07, 0x0a, 0x04, 0x0f,0x06, 0x0f, 0x0e, 0x09, 0x05, 0x01, 0x0a, 0x0a, 0x01, 0x09,0x06, 0x07, 0x09, 0x0d };}//Base64:byte[]→Stringpublic static String encryptBASE64(byte[] key) throws Exception {return (new BASE64Encoder()).encodeBuffer(key);}//Base64:String→byte[]public static byte[] decryptBASE64(String key) throws Exception {return (new BASE64Decoder()).decodeBuffer(key);}/** * 转换密钥 * @param key 二进制密钥 * @return Key 密钥 * */ public static Key toKey(byte[] key) throws Exception{ //生成密钥  SecretKey secretKey=new SecretKeySpec(key,KEY_ALGORITHM);  return secretKey;  }  /** * 加密数据 * @param data 待加密数据 * @param key 密钥 * @return byte[] 加密后的数据 * */ public static byte[] encrypt(byte[] data,byte[] key) throws Exception{  //还原密钥  Key k=toKey(key);  /** * 实例化 * 使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现 * Cipher.getInstance(CIPHER_ALGORITHM,"BC") */ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM, "BC");  //初始化,设置为加密模式  cipher.init(Cipher.ENCRYPT_MODE, k);  //执行操作  return cipher.doFinal(data);  }/** * 解密数据 * @param data 待解密数据 * @param key 密钥 * @return byte[] 解密后的数据 * */ public static byte[] decrypt(byte[] data,byte[] key) throws Exception{  //欢迎密钥  Key k =toKey(key);  /** * 实例化 * 使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现 * Cipher.getInstance(CIPHER_ALGORITHM,"BC") */ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM);  //初始化,设置为解密模式cipher.init(Cipher.DECRYPT_MODE, k);  //执行操作  return cipher.doFinal(data);  } 

④ RSA:非对称加密算法,RSA的安全性依赖于大数的分解,公钥和私钥都是两个大素数(大于100的十进制位)的函数。公钥对数据进行加密后传输,接收方用私钥进行解密,而从一个公钥和密文推断出明文的难度等同于分解两个大素数的积。由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论是软件还是硬件实现。速度一直是RSA的缺陷。一般来说只用于少量数据加密。

// 密钥对private KeyPair keyPair = null;/*** 初始化密钥对*/public RSAUtil() {try {this.keyPair = this.generateKeyPair();} catch (Exception e) {e.printStackTrace();}}/*** 生成密钥对* * @return KeyPair* @throws Exception*/private KeyPair generateKeyPair() throws Exception {try {KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());// 这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低final int KEY_SIZE = 1024; //1024-bit密钥----目前较流行keyPairGen.initialize(KEY_SIZE, new SecureRandom());KeyPair keyPair = keyPairGen.genKeyPair();return keyPair;} catch (Exception e) {throw new Exception(e.getMessage());}}/*** 生成公钥* * @param modulus* @param publicExponent* @return RSAPublicKey* @throws Exception*/private RSAPublicKey generateRSAPublicKey(byte[] modulus,byte[] publicExponent) throws Exception {KeyFactory keyFac = null;try {keyFac = KeyFactory.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());} catch (NoSuchAlgorithmException ex) {throw new Exception(ex.getMessage());}RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent));try {return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);} catch (InvalidKeySpecException ex) {throw new Exception(ex.getMessage());}}/*** 生成私钥* * @param modulus* @param privateExponent* @return RSAPrivateKey* @throws Exception*/private RSAPrivateKey generateRSAPrivateKey(byte[] modulus,byte[] privateExponent) throws Exception {KeyFactory keyFac = null;try {keyFac = KeyFactory.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());} catch (NoSuchAlgorithmException ex) {throw new Exception(ex.getMessage());}RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent));try {return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);} catch (InvalidKeySpecException ex) {throw new Exception(ex.getMessage());}}/*** 加密* * @param key*            加密的密钥* @param data*            待加密的明文数据* @return 加密后的数据* @throws Exception*/public String encrypt(Key key, byte[] data) throws Exception {try {Cipher cipher = Cipher.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());cipher.init(Cipher.ENCRYPT_MODE, key);// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024 加密块大小为127// byte,加密后为128个byte;// 因此共有2个加密块,第一个127 byte第二个为1个byteint blockSize = cipher.getBlockSize();int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小int leavedSize = data.length % blockSize;int blocksSize = leavedSize != 0 ? data.length / blockSize + 1: data.length / blockSize;byte[] raw = new byte[outputSize * blocksSize];int i = 0;while (data.length - i * blockSize > 0) {if (data.length - i * blockSize > blockSize)cipher.doFinal(data, i * blockSize, blockSize, raw, i* outputSize);elsecipher.doFinal(data, i * blockSize, data.length - i* blockSize, raw, i * outputSize);// 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到ByteArrayOutputStream中// ,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了OutputSize所以只好用dofinal方法。i++;}return encryptBASE64(raw);} catch (Exception e) {throw new Exception(e.getMessage());}}/*** 解密* * @param key*            解密的密钥* @param raw*            已经加密的数据* @return 解密后的明文* @throws Exception*/public byte[] decrypt(Key key, String enRsaStr) throws Exception {byte[]raw = decryptBASE64(enRsaStr);try {Cipher cipher = Cipher.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());cipher.init(cipher.DECRYPT_MODE, key);int blockSize = cipher.getBlockSize();ByteArrayOutputStream bout = new ByteArrayOutputStream(64);int j = 0;while (raw.length - j * blockSize > 0) {bout.write(cipher.doFinal(raw, j * blockSize, blockSize));j++;}return bout.toByteArray();} catch (Exception e) {throw new Exception(e.getMessage());}}/*** 返回公钥* * @return* @throws Exception*/public RSAPublicKey getRSAPublicKey() throws Exception {// 获取公钥RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();// 获取公钥系数(字节数组形式)byte[] pubModBytes = pubKey.getModulus().toByteArray();// 返回公钥公用指数(字节数组形式)byte[] pubPubExpBytes = pubKey.getPublicExponent().toByteArray();// 生成公钥RSAPublicKey recoveryPubKey = this.generateRSAPublicKey(pubModBytes,pubPubExpBytes);return recoveryPubKey;}//key to Base64Stringpublic static String getBase64Key(Key key)throws Exception {return encryptBASE64(key.getEncoded());}//byte[]→Stringpublic static String encryptBASE64(byte[] key) throws Exception {return (new BASE64Encoder()).encodeBuffer(key);}//String→byte[]public static byte[] decryptBASE64(String key) throws Exception {return (new BASE64Decoder()).decodeBuffer(key);}/*** 获取私钥* * @return* @throws Exception*/public RSAPrivateKey getRSAPrivateKey() throws Exception {// 获取私钥RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();// 返回私钥系数(字节数组形式)byte[] priModBytes = priKey.getModulus().toByteArray();// 返回私钥专用指数(字节数组形式)byte[] priPriExpBytes = priKey.getPrivateExponent().toByteArray();// 生成私钥RSAPrivateKey recoveryPriKey = this.generateRSAPrivateKey(priModBytes,priPriExpBytes);return recoveryPriKey;}/*** 得到公钥* @param key 密钥字符串(经过base64编码)* @throws Exception*/public static PublicKey getPublicKey(String key) throws Exception {byte[] keyBytes;keyBytes = (new BASE64Decoder()).decodeBuffer(key);X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(keySpec);return publicKey;}/*** 得到私钥* @param key 密钥字符串(经过base64编码)* @throws Exception*/public static PrivateKey getPrivateKey(String key) throws Exception {byte[] keyBytes;keyBytes = (new BASE64Decoder()).decodeBuffer(key);PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(keySpec);return privateKey;}

具体到项目中需根据服务端具体情况进行修改,关于数据加密的总结就这么多。

Android 数据加密算法总结相关推荐

  1. Android 数据加密算法 Des,Base64详解

    一,DES加密: 首先网上搜索了一个DES加密算法工具类: import java.security.*; import javax.crypto.*; public class DesHelper ...

  2. Android开发笔记(七十二)数据加密算法

    编码算法 URL编码 URL编码其实并非加解密算法,只是对特殊字符进行字符转义,从而方便在URL中传输参数.URL编码有两种方式,一种是狭义的URL编码,另一种是广义的URL编码. 狭义的URL编码指 ...

  3. Android数据存储安全实践

    0x00 数据安全 Android操作系统自问世以来凭借其开放性和易用性成为当前智能手机的主流操作系统之一,作为与人们关系最密切的智能设备,越来越多的通讯录.短信.视频等隐私数据以明文的方式保存在手机 ...

  4. 一种基于随机数组so库的Android数据资源硬加密方法 草稿

    一种基于随机数组so库的Android数据资源硬加密方法 作者:AniO软件咨询服务,天涯来客-Leemboy 摘要:本文提供一种简洁的Android数据资源硬加密方案,利用随机数组so静态库,对An ...

  5. Android数据持久化:SharePreference

    SharePreference:作为Android数据持久化的一种,具有一定的便捷性,适合存储一些体积小的数据. 存储数据方式:键值对的方式,类似于Map: 利用SharePreference.Edi ...

  6. Android数据存储——2.文件存储_B_资源文件

    今天学习Android数据存储--文件存储_资源文件 把资源文件mybook.txt放入项目目录下的res资源文件夹下的raw文件夹下(没有则新建),PS:mybook.txt存为UTF-8编码. X ...

  7. Android数据存储——2.文件存储_C_DOM解析XML文档

    今天学习Android数据存储--文件存储_DOM解析XML文档 位于org.w3c.dom操作XML会比较简单,就是将XML看做是一颗树,DOM就是对这颗树的一个数据结构的描述,但对大型XML文件效 ...

  8. Android数据存储之GreenDao 3.0 详解

    前言: 今天一大早收到GreenDao 3.0 正式发布的消息,自从2014年接触GreenDao至今,项目中一直使用GreenDao框架处理数据库操作,本人使用数据库路线 Sqlite----> ...

  9. < Android数据存储> 任务二 应用程序数据文件夹里的文件读写

    :zh]Android中提供了两个方法用来打开应用程序的数据文件夹IO流. 1.FileInputStream openFileInput(String name):参数name表示某个文件名,该方法 ...

最新文章

  1. python【蓝桥杯vip练习题库】ALGO-141 P1102(学生信息)
  2. 谁说只有VGG才能做风格迁移,ResNet也可以
  3. 通过php获取文件后缀名怎么改,【转】PHP获取文件后缀名的几种方法
  4. 【正一专栏】儿时的夏天——似水流年
  5. Pivotal发布Spring Cloud Data Flow 1.5版本
  6. 特征工程(2):特征构建
  7. echarts4离线使用文档_适合写API接口文档的管理工具有哪些?
  8. 普通html和vue单选框的样式,vue2实现自定义样式radio单选框
  9. VS调试时断点无法进入或命中的原因及解决方法(PDB引发的)
  10. OpenCV基本函数使用--Python
  11. java做h5小游戏服务端_神藏西游H5游戏源码服务端+客户端+搭建教程
  12. 视频时帧率达到15,人眼就感觉是连续的
  13. Android11 WAPI证书安装流程
  14. [转载]千古真人张三丰
  15. vlc播放器linux编译,linux安装vlc视频播放器
  16. python笔记(一) 数据类型 函数
  17. linux中文件夹的作用
  18. 树莓派调用百度API实现果蔬识别部署
  19. 开源 | 携程机票BDD UI Testing框架 - Flybirds
  20. ESP8266占空比测试

热门文章

  1. 空间存储公链的5G商用路径-共建TB级大数据存储商机
  2. 对载荷谱进行雨流计数的几个主要步骤(以四点雨流计数为例)
  3. 7-17 最长对称子串
  4. 两行代码引发的血案-代笔司徒老师
  5. mysql反删除恢复软件下载_MySQL Recovery(MySQL恢复软件)下载 v4.1官方版-下载啦
  6. 【转】Endnote中英文混排及输出作者全名的解决办法
  7. Echarts广东省福建省地图修正
  8. NGFF、M.2、mSATA、miniPCI-e基础知识入门
  9. Android: Jetpack Compose如何禁用涟漪(水波纹)效果
  10. mediasoup json 通信协议2--room.js和router.cpp信令