Android中常用的加密方式
Android面试的时候,尤其是面试一些金融公司的时候经常性的问道:“你会不会加密?”,“加密方式是什么?”,“大概什么样的加密原理呢?”。其实,大多数人都是一脸懵逼,我也懵逼过。痛下决心总结一下,写的不好,大家见笑了。
一、Rsa加密
1、RSA是第一种既可以用于数据加密,也可以用于数字签名的算法;
2、算法原理:
1)、随机产生两个大的质数m、n且m!=n,计算K1=mn;
2)、选择一个大于1小于k1的自然数k2,k2必须与(m-1)(n-1)互为素数;
3)、计算得到d--->d x k2=1(mod(m-1)(n-1));
4)、销毁mn;
最终产生的k1和k2为“公钥”,d为“私钥”,发送方使用k1进行加密,接收方使用d进行解密。
3、注意:
1、RSA的安全性依赖于大数分解,小于1024位的k1被认为是不安全的;
2、RSA的计算速度慢。
4、使用
1、生成密钥对
/** * 随机生成RSA密钥对 * * @param keyLength 密钥长度,范围:512~2048 * 一般1024 * @return */ public static KeyPair generateRSAKeyPair(int keyLength) { try { KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA); kpg.initialize(keyLength); return kpg.genKeyPair(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } }
2、公钥加密
/** * 用公钥对字符串进行加密 * * @param data 原文 */ public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { // 得到公钥 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); KeyFactory kf = KeyFactory.getInstance(RSA); PublicKey keyPublic = kf.generatePublic(keySpec); // 加密数据 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); cp.init(Cipher.ENCRYPT_MODE, keyPublic); return cp.doFinal(data); }
3、私钥加密
/** * 私钥加密 * * @param data 待加密数据 * @param privateKey 密钥 * @return byte[] 加密数据 */ public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception { // 得到私钥 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory kf = KeyFactory.getInstance(RSA); PrivateKey keyPrivate = kf.generatePrivate(keySpec); // 数据加密 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); cipher.init(Cipher.ENCRYPT_MODE, keyPrivate); return cipher.doFinal(data); }
有加密自然也得有解密
1、公钥解密
/** * 公钥解密 * * @param data 待解密数据 * @param publicKey 密钥 * @return byte[] 解密数据 */ public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { // 得到公钥 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); KeyFactory kf = KeyFactory.getInstance(RSA); PublicKey keyPublic = kf.generatePublic(keySpec); // 数据解密 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); cipher.init(Cipher.DECRYPT_MODE, keyPublic); return cipher.doFinal(data); }
2、私钥解密
/** * 使用私钥进行解密 */ public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception { // 得到私钥 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory kf = KeyFactory.getInstance(RSA); PrivateKey keyPrivate = kf.generatePrivate(keySpec); // 解密数据 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); cp.init(Cipher.DECRYPT_MODE, keyPrivate); byte[] arr = cp.doFinal(encrypted); return arr; }
用到的全局变量
// 非对称加密密钥算法 public static final String RSA = "RSA"; //加密填充方式 public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding"; //秘钥默认长度 public static final int DEFAULT_KEY_SIZE = 2048; // 当要加密的内容超过bufferSize,则采用partSplit进行分块加密 public static final byte[] DEFAULT_SPLIT = "#PART#".getBytes(); // 当前秘钥支持加密的最大字节数 public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;
关于加密填充方式:之前以为上面这些操作就能实现rsa加解密,以为万事大吉了,呵呵,这事还没完,悲剧还是发生了,Android这边加密过的数据,服务器端死活解密不了,原来android系统的RSA实现是"RSA/None/NoPadding",而标准JDK实现是"RSA/None/PKCS1Padding"
,这造成了在android机上加密后无法在服务器上解密的原因,所以在实现的时候这个一定要注意。
二、DES加密
1、简单介绍
DES是一种对称加密算法,所谓对称加密算法即:加密和解密使用相同密钥的算法。DES加密算法出自IBM的研究,后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力,24小时内即可被破解。
划重点 :DES不太安全。
2、静态秘钥DES加密方式使用
1)、DES加密代码
/** *DES 加密 * * @param message 原文 * @param key 密钥,长度不能够小于8位 * @return * @throws Exception */ public static String desEncrypt(String message, String key) throws Exception { Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8")); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey secretKey = keyFactory.generateSecret(desKeySpec); IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8")); cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv); byte[] encryptbyte = cipher.doFinal(message.getBytes()); return new String(Base64.encode(encryptbyte, Base64.DEFAULT)).trim(); }
2、DES解密代码
/** * DES解密 * * @param message 密文 * @param key 密钥,长度不能够小于8位 * @return * @throws Exception */ public static String desDecrypt(String message, String key) throws Exception { byte[] bytesrc = Base64.decode(message.getBytes(), Base64.DEFAULT); Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8")); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey secretKey = keyFactory.generateSecret(desKeySpec); IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8")); cipher.init(Cipher.DECRYPT_MODE, secretKey, iv); byte[] retByte = cipher.doFinal(bytesrc); return new String(retByte); }
3、动态秘钥加密方式
1、DES加密常用的常量
private final static String HEX = "0123456789ABCDEF"; //DES是加密方式 CBC是工作模式 PKCS5Padding是填充模式 private final static String TRANSFORMATION = "DES/CBC/PKCS5Padding"; //初始化向量参数,AES 为16bytes. DES 为8bytes. private final static String IVPARAMETERSPEC = "01020304"; //DES是加密方式 private final static String ALGORITHM = "DES"; // SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法 private static final String SHA1PRNG = "SHA1PRNG";
2、动态生成秘钥
/* * 生成随机数,可以当做动态的密钥 加密和解密的密钥必须一致,不然将不能解密 */ public static String generateKey() { try { SecureRandom localSecureRandom = SecureRandom.getInstance(SHA1PRNG); byte[] bytes_key = new byte[20]; localSecureRandom.nextBytes(bytes_key); String str_key = toHex(bytes_key); return str_key; } catch (Exception e) { e.printStackTrace(); } return null; } //二进制转字符 public static String toHex(byte[] buf) { if (buf == null) return ""; StringBuffer result = new StringBuffer(2 * buf.length); for (int i = 0; i < buf.length; i++) { appendHex(result, buf[i]); } return result.toString(); } private static void appendHex(StringBuffer sb, byte b) { sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); }
3、处理秘钥
方式一、
// 对密钥进行处理 private static Key getRawKey(String key) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance(ALGORITHM); //for android SecureRandom sr = null; // 在4.2以上版本中,SecureRandom获取方式发生了改变 if (android.os.Build.VERSION.SDK_INT >= 17) { sr = SecureRandom.getInstance(SHA1PRNG, "Crypto"); } else { sr = SecureRandom.getInstance(SHA1PRNG); } // for Java // secureRandom = SecureRandom.getInstance(SHA1PRNG); sr.setSeed(key.getBytes()); kgen.init(64, sr); //DES固定格式为64bits,即8bytes。 SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return new SecretKeySpec(raw, ALGORITHM); }
方式二
/ 对密钥进行处理 private static Key getRawKey(String key) throws Exception { DESKeySpec dks = new DESKeySpec(key.getBytes()); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); return keyFactory.generateSecret(dks); }
4、加密实现
/** * DES算法,加密 * * @param data 待加密字符串 * @param key 加密私钥,长度不能够小于8位 * @return 加密后的字节数组,一般结合Base64编码使用 */ public static String encode(String key, String data) { return encode(key, data.getBytes()); } /** * DES算法,加密 * * @param data 待加密字符串 * @param key 加密私钥,长度不能够小于8位 * @return 加密后的字节数组,一般结合Base64编码使用 */ public static String encode(String key, byte[] data) { try { Cipher cipher = Cipher.getInstance(TRANSFORMATION); IvParameterSpec iv = new IvParameterSpec(IVPARAMETERSPEC.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, getRawKey(key), iv); byte[] bytes = cipher.doFinal(data); return Base64.encodeToString(bytes, Base64.DEFAULT); } catch (Exception e) { return null; } }
5、解密实现
/** * 获取编码后的值 * * @param key * @param data * @return */ public static String decode(String key, String data) { return decode(key, Base64.decode(data, Base64.DEFAULT)); } /** * DES算法,解密 * * @param data 待解密字符串 * @param key 解密私钥,长度不能够小于8位 * @return 解密后的字节数组 */ public static String decode(String key, byte[] data) { try { Cipher cipher = Cipher.getInstance(TRANSFORMATION); IvParameterSpec iv = new IvParameterSpec(IVPARAMETERSPEC.getBytes()); cipher.init(Cipher.DECRYPT_MODE, getRawKey(key), iv); byte[] original = cipher.doFinal(data); String originalString = new String(original); return originalString; } catch (Exception e) { return null; } }
三、AES加密
1、简单介绍
高级加密标准
2、加密使用方法
1、AES用到的常量
private final static String HEX = "0123456789ABCDEF"; //AES是加密方式 CBC是工作模式 PKCS5Padding是填充模式 private static final String CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding"; //AES 加密 private static final String AES = "AES"; // SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法 private static final String SHA1PRNG="SHA1PRNG";
2、动态生成秘钥
public static String generateKey() { try { SecureRandom localSecureRandom = SecureRandom.getInstance(SHA1PRNG); byte[] bytes_key = new byte[20]; localSecureRandom.nextBytes(bytes_key); String str_key = toHex(bytes_key); return str_key; } catch (Exception e) { e.printStackTrace(); } return null; }
3、对秘钥进行处理
private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance(AES); //for android SecureRandom sr = null; // 在4.2以上版本中,SecureRandom获取方式发生了改变 int sdk_version = android.os.Build.VERSION.SDK_INT; // Android 6.0 以上 if(sdk_version>23){ sr = SecureRandom.getInstance(SHA1PRNG,new CryptoProvider()); //4.2及以上 }else if(android.os.Build.VERSION.SDK_INT >= 17){ sr = SecureRandom.getInstance(SHA1PRNG, "Crypto"); }else { sr = SecureRandom.getInstance(SHA1PRNG); } // for Java // secureRandom = SecureRandom.getInstance(SHA1PRNG); sr.setSeed(seed); //256 bits or 128 bits,192bits kgen.init(128, sr); //AES中128位密钥版本有10个加密循环,192比特密钥版本有12个加密循环,256比特密钥版本则有14个加密循环。 SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; }
4、加密
public static String encrypt(String key, String cleartext) { if (TextUtils.isEmpty(cleartext)) { return cleartext; } try { byte[] result = encrypt(key, cleartext.getBytes()); return new String(Base64.encode(result,Base64.DEFAULT)); } catch (Exception e) { e.printStackTrace(); } return null; }
或者
private static byte[] encrypt(String key, byte[] clear) throws Exception { byte[] raw = getRawKey(key.getBytes()); SecretKeySpec skeySpec = new SecretKeySpec(raw, AES); Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()])); byte[] encrypted = cipher.doFinal(clear); return encrypted; }
5、解密
public static String decrypt(String key, String encrypted) { if (TextUtils.isEmpty(encrypted)) { return encrypted; } try { byte[] enc = Base64.decode(encrypted,Base64.DEFAULT); byte[] result = decrypt(key, enc); return new String(result); } catch (Exception e) { e.printStackTrace(); } return null; }
或者
private static byte[] decrypt(String key, byte[] encrypted) throws Exception { byte[] raw = getRawKey(key.getBytes()); SecretKeySpec skeySpec = new SecretKeySpec(raw, AES); Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING); cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()])); byte[] decrypted = cipher.doFinal(encrypted); return decrypted; }
6、辅助方法
//二进制转字符 public static String toHex(byte[] buf) { if (buf == null) return ""; StringBuffer result = new StringBuffer(2 * buf.length); for (int i = 0; i < buf.length; i++) { appendHex(result, buf[i]); } return result.toString(); } private static void appendHex(StringBuffer sb, byte b) { sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); } // 增加 CryptoProvider 类 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"); } }

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Android开发常用权限设置
加在AndroidManifest.xml 文件中manifest标签以内,application以外 例如:<!--网络权限 --> <uses-permission android:name="android.permission.INTERNET" /> 访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permission.ACCESS_COARSE_LOCATION,通过WiFi或移动基站的方式获取用户错略的经纬度信息,定位精度大概误差在30~1500米 获取精确位置 android.permission.ACCESS_FINE_LOCATION,通过GPS芯片接收卫星的定位信息,定位精度达10米以内 访问定位额外命令 android.permission.ACCESS_LOCATION_EXTRA_COMMANDS,允许程序访问额外的定位提供者指令 获取模拟定位信息 android.permission.ACCESS...
- 下一篇
iOS消息转发小记
消息转发流程图 15277558865032.jpg 如果类接收到无法处理的消息,会触发消息转发机制,一共有三个步骤,接受者在每一步中均有机会处理消息。步骤越往后,处理消息的代价就越大,所以最好再第一步就处理完。 第一道防线 在类里面实现两个方法来处理未知消息。执行动态方法解析之前,先会判断是否曾经有动态解析。 resolveInstanceMethod:处理实例方法 resolveClassMethod:处理类方法 我们来看个Demo,先看调用方代码 TestA *testA = [[TestA alloc] init]; [testA instanceMethod]; [TestA classMethod]; 再来看看TestA的定义。 // TestA.h @interface TestA : NSObject - (void)instanceMethod; + (void)classMethod; @end // TestA.m @implementation TestA - (void)newInstanceMethod { NSLog(@"newInstanceMethod...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Windows10,CentOS7,CentOS8安装Nodejs环境