Android RSA加密对象数据
前几天说了手头项目用MD5和双向加密DES来进行加密的,因为产品是在不断的改造中完善的。考虑到DES和MD5加解密还是会存下一定的风险,于是产品一拍,不行,听你们说MD5加密是不安全的,咱们产品以后做大了的话肯定会有人对我们的产品进行攻击,所以我们还是用更安全一点的加解密方法吧。于是。。。。。
在接下来的几个小时里面,在针对各种加密方法的安全性和方案的可行性分析后,项目组确定用RSA算法对项目的IO数据进行加解密。于是又用到了一种加解密方法,于是又将它记下来,供大家分享和指正。
废话不多说,首先来跟度娘唠唠嗑。
度娘说:“1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫做RSA算法。从那时直到现在,RSA算法一直是最广为使用的"非对称加密算法"。毫不夸张地说,只要有计算机网络的地方,就有RSA算法。这种算法非常可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全。” 。。。。好了够了,度娘,你这么啰嗦,我只是一名小小码农,不要跟我说质数相乘,不要跟我说欧拉定理,不要跟我说费马定理!!!!我只想安安静静的给我的数据加密和解密。
于是在Google大哥上面找了些代码片段,再经过同事们的整合,将传过去一大堆乱七八糟的字母解密成明文后,我知道,这礼拜六不用加班了。
上代码!Base64Utils.java:这个类的作用是将加密后的数据再进行一层加密,通过http传输进行前后台的数据IO。
- public class Base64Utils
- {
- private static char[] base64EncodeChars = new char[]
- { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
- 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
- '6', '7', '8', '9', '+', '/' };
- /**
- * 加密
- *
- * @param data
- * @return
- */
- public static String encode(byte[] data)
- {
- StringBuffer sb = new StringBuffer();
- int len = data.length;
- int i = 0;
- int b1, b2, b3;
- while (i < len)
- {
- b1 = data[i++] & 0xff;
- if (i == len)
- {
- sb.append(base64EncodeChars[b1 >>> 2]);
- sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
- sb.append("==");
- break;
- }
- b2 = data[i++] & 0xff;
- if (i == len)
- {
- sb.append(base64EncodeChars[b1 >>> 2]);
- sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
- sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
- sb.append("=");
- break;
- }
- b3 = data[i++] & 0xff;
- sb.append(base64EncodeChars[b1 >>> 2]);
- sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
- sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]);
- sb.append(base64EncodeChars[b3 & 0x3f]);
- }
- return sb.toString();
- }
- /**
- * 解密
- *
- * @param str
- * @return
- */
- public static byte[] decode(String str)
- {
- try
- {
- return decodePrivate(str);
- } catch (UnsupportedEncodingException e)
- {
- e.printStackTrace();
- }
- return new byte[]
- {};
- }
- private static byte[] decodePrivate(String str) throws UnsupportedEncodingException
- {
- StringBuffer sb = new StringBuffer();
- byte[] data = null;
- data = str.getBytes("US-ASCII");
- int len = data.length;
- int i = 0;
- int b1, b2, b3, b4;
- while (i < len)
- {
- do
- {
- b1 = base64DecodeChars[data[i++]];
- } while (i < len && b1 == -1);
- if (b1 == -1)
- break;
- do
- {
- b2 = base64DecodeChars[data[i++]];
- } while (i < len && b2 == -1);
- if (b2 == -1)
- break;
- sb.append((char) ((b1 << 2) | ((b2 & 0x30) >>> 4)));
- do
- {
- b3 = data[i++];
- if (b3 == 61)
- return sb.toString().getBytes("iso8859-1");
- b3 = base64DecodeChars[b3];
- } while (i < len && b3 == -1);
- if (b3 == -1)
- break;
- sb.append((char) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));
- do
- {
- b4 = data[i++];
- if (b4 == 61)
- return sb.toString().getBytes("iso8859-1");
- b4 = base64DecodeChars[b4];
- } while (i < len && b4 == -1);
- if (b4 == -1)
- break;
- sb.append((char) (((b3 & 0x03) << 6) | b4));
- }
- return sb.toString().getBytes("iso8859-1");
- }
- }
其次就是RSAUtils.java类,这个类支持对字符串进行加密以及对某一个对象里面的所有属性通过遍历和反射机制进行加密。
- public class RSAUtil {
- private static final String PUBLIC = ".***.***";//公钥文件名(约定以此结尾,作者对此部分进行了隐藏显示。ex:Android端对应的公钥文件名为android.public.***)
- private static final String PRIVATE = ".****.***";// 私钥文件名
- private static final String ENCRYPTKEY = PUBLIC;
- private static final String DECRYPTKEY = PUBLIC;
- private static String RSA = "RSA";
- private static final String ALGORITHM = "RSA/ECB/PKCS1Padding";
- //读取的公钥私钥缓存
- private static Map<String, Key> keyCache = new ConcurrentHashMap<String, Key>();
- //微型缓冲池
- private static Map<String, Cipher> cipherCache = new ConcurrentHashMap<String, Cipher>();
- private String client="android";
- private Context context;
- private Cipher encryptCipher;//由于Cipher是线程非安全,不能作为静态变量
- private Cipher decryptCipher;
- /**
- * 从字符串中加载私钥<br>
- * 加载时使用的是PKCS8EncodedKeySpec(PKCS#8编码的Key指令)。
- *
- * @param privateKeyStr
- * @return
- * @throws Exception
- */
- private PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
- byte[] buffer = Base64Utils.decode(privateKeyStr);
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
- KeyFactory keyFactory = KeyFactory.getInstance(RSA);
- return keyFactory.generatePrivate(keySpec);
- }
- /**
- * 从字符串中加载公钥
- *
- * @param publicKeyStr
- * 公钥数据字符串
- * @throws Exception
- * 加载公钥时产生的异常
- */
- private static PublicKey getPublicKey(String publicKeyStr) throws Exception {
- byte[] buffer = Base64Utils.decode(publicKeyStr);
- KeyFactory keyFactory = KeyFactory.getInstance(RSA);
- X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
- return keyFactory.generatePublic(keySpec);
- }
- private String getKeyString(String keyName) throws Exception {
- InputStream is = context.getAssets().open(keyName);
- BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
- String temp = null;
- StringBuffer sb = new StringBuffer();
- while ((temp = br.readLine()) != null) {
- sb.append(temp);
- }
- String keyString = sb.toString().replaceAll("-+[^-]+KEY-+", "");
- br.close();
- return keyString;
- }
- private Key getKey(String client, String type) throws Exception {
- String keyName = client + type;
- Key key = keyCache.get(keyName);
- if (key == null) {
- synchronized (RSAUtil.class) {
- key = keyCache.get(keyName);
- if (key == null) {
- String keyString = getKeyString(keyName);
- if (type.equals(PRIVATE)) {
- key = getPrivateKey(keyString);
- } else {
- key = getPublicKey(keyString);
- }
- keyCache.put(keyName, key);
- }
- }
- }
- return key;
- }
- public RSAUtil(Context context) {
- this.context = context;
- }
- public void destroy() {
- if (encryptCipher != null) {
- synchronized (RSAUtil.class) {
- String cipherName = client + ".encryptCipher";
- cipherCache.put(cipherName, encryptCipher);
- }
- }
- if (decryptCipher != null) {
- synchronized (RSAUtil.class) {
- String cipherName = client + ".decryptCipher";
- cipherCache.put(cipherName, decryptCipher);
- }
- }
- }
- protected void finalize() throws Throwable {
- destroy();
- super.finalize();
- }
- public byte[] encryptData(byte[] data) throws Exception {
- if (data == null) return null;
- //lazy init
- if (encryptCipher == null) {
- //try to load cache
- synchronized (RSAUtil.class) {
- String cipherName = client + ".encryptCipher";
- encryptCipher = cipherCache.get(cipherName);
- cipherCache.remove(cipherName);
- }
- if (encryptCipher == null) {
- Key key = getKey(client, ENCRYPTKEY);
- encryptCipher = Cipher.getInstance(ALGORITHM);
- encryptCipher.init(Cipher.ENCRYPT_MODE, key);
- }
- }
- int blockSize = encryptCipher.getBlockSize();
- int outputSize = encryptCipher.getOutputSize(0);
- if (blockSize == 0) {//SunJCE returns 0
- blockSize = 117;
- outputSize = 128;
- }
- int pieces = (data.length - 1) / blockSize + 1;
- int rest = data.length % blockSize;
- byte[] result = new byte[pieces * outputSize];
- for (int p = 0; p < pieces; p++) {
- //last piece length = rest or blockSize
- int length = ((p == pieces - 1) && rest != 0) ? rest : blockSize;
- encryptCipher.doFinal(data, p * blockSize, length, result, p * outputSize);
- }
- return result;
- }
- public byte[] decryptData(byte[] data) throws Exception {
- if (data == null) return null;
- //lazy init
- if (decryptCipher == null) {
- //try to load cache
- synchronized (RSAUtil.class) {
- String cipherName = client + ".decryptCipher";
- decryptCipher = cipherCache.get(cipherName);
- cipherCache.remove(cipherName);
- }
- if (decryptCipher == null) {
- Key key = getKey(client, DECRYPTKEY);
- decryptCipher = Cipher.getInstance(ALGORITHM);
- decryptCipher.init(Cipher.DECRYPT_MODE, key);
- }
- }
- int blockSize = decryptCipher.getBlockSize();
- if (blockSize == 0) {//SunJCE returns 0
- blockSize = 128;
- }
- int pieces = data.length / blockSize;
- if (pieces == 0) throw new Exception("encrypted data is too short");
- ByteArrayOutputStream result = new ByteArrayOutputStream();
- for (int p = 0; p < pieces; p++) {
- result.write(decryptCipher.doFinal(data, p * blockSize, blockSize));
- }
- return result.toByteArray();
- }
- //字符串加密
- public String encryptString(String param) throws Exception {
- if (param == null) return null;
- byte[] encryptedByte = encryptData(param.getBytes("UTF-8"));
- return Base64Utils.encode(encryptedByte);
- }
- //字符串解密
- public String decryptString(String param) throws Exception {
- if (param == null) return null;
- byte[] decryptedByte = decryptData(Base64Utils.decode(param));
- return new String(decryptedByte, "UTF-8");
- }
- //对某一个对象进行加解密操作
- private <T> T opearteObject(T object, boolean encrypt, boolean withSuperClass) throws Exception {
- if (object == null) return null;
- Class<?> clazz = object.getClass();
- Field[] allFields = clazz.getDeclaredFields();
- while (withSuperClass && (clazz = clazz.getSuperclass()) != null) {
- Field[] newFields = clazz.getDeclaredFields();
- if (newFields.length == 0) continue;
- Field[] fields = allFields;
- allFields = new Field[fields.length + newFields.length];
- System.arraycopy(fields, 0, allFields, 0, fields.length);
- System.arraycopy(newFields, 0, allFields, fields.length, newFields.length);
- }
- for (Field field : allFields) {
- if (field.getType().equals(String.class)) {
- field.setAccessible(true);
- String value = (String) field.get(object);
- if (encrypt) {
- value = encryptString(value);
- } else {
- value = decryptString(value);
- }
- field.set(object, value);
- } else if (field.getType().equals(String[].class)) {
- field.setAccessible(true);
- String[] value = (String[]) field.get(object);
- for (int i = 0; i < value.length; i++) {
- if (encrypt) {
- value[i] = encryptString(value[i]);
- } else {
- value[i] = decryptString(value[i]);
- }
- }
- }
- }
- return object;
- }
- public <T> T encryptObject(T object) throws Exception {
- return opearteObject(object, true, false);
- }
- public <T> T decryptObject(T object) throws Exception {
- return opearteObject(object, false, false);
- }
- public <T> T encryptObjectWithSuperClass(T object) throws Exception {
- return opearteObject(object, true, true);
- }
- public <T> T decryptObjectWithSuperClass(T object) throws Exception {
- return opearteObject(object, false, true);
- }
- }
然后,就是在客户端使用这个加密方法了:
- RSAUtil rsa=new RSAUtil(mContext);
- try {
- rsa.encryptObject(request);
- rsa.destroy();
- } catch (Exception e) {
- e.printStackTrace();
- }
对的,就是介么一小段代码,对request对象里所有的String类型的数据进行了加密操作。最后,还对改对象进行了一个destroy操作,以免占用太多的缓存。
然而,悲催的是,bob并不知道介个公钥和私钥是怎么产生的啊!!!在改代码的时候有见到客户端的私钥,但是公钥说是不给我。。我介么善良的一个银你觉得我会泄露秘钥么。。。算啦,再去其他地方找找秘钥的生成吧。
Android RSA加密对象数据的更多相关文章
- Android RSA加密解密
概述 RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困 难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数 ...
- android -------- RSA加密解密算法
RSA加密算法是一种非对称加密算法.在公开密钥加密和电子商业中RSA被广泛使用 RSA公开密钥密码体制.所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计 ...
- PHP使用OPENSSL RSA加密解密数据
加密数据有很多种方法,今天我们来看一下OPENSSL RSA的加密办法. 1.首先得安装php的openssl扩展 php -m | grep openssl 执行以上命令,确保已经安装了openss ...
- IOS, Android, Java Web Rest : RSA 加密和解密问题
IOS, Android, Java Web Rest : RSA 加密和解密问题 一对公钥私钥可以使用 OpenSSL创建, 通常 1024位长度够了. 注意: 1. 公钥私钥是BASE64编码的 ...
- 使用X.509数字证书加密解密实务(三)-- 使用RSA证书结合对称加密技术加密长数据
一. 使用证书结合对称加密算法加.解密长数据 上一章节讨论了如何使用RSA证书加密数据,文中提到:“Dotnet的RSA实现有个特点,它必须要在明文中添加一些随机数,所以明文不能把128字节占满,实 ...
- RSA 加密
iOS开发教程-iOS中的RSA加解密 在移动应用开发中常常遇到数据传输安全性的问题,尤其是在账户安全以及支付场景中的订单数据.或支付信息的传输中,正规的公司一定会要求对数据进行加密,当然有创业初期的 ...
- RSA Android加密的数据服务器上无法解密?
一.android加密的数据服务器上无法解密? "算法/模式/填充" android的rsa加密方式是--------RSA/ECB/NoPadding或者RSA/None/NoP ...
- Android数据加密之Rsa加密
前言: 最近无意中和同事交流数据安全传输的问题,想起自己曾经使用过的Rsa非对称加密算法,闲下来总结一下. 其他几种加密方式: Android数据加密之Rsa加密 Android数据加密之Aes加密 ...
- android 客户端 RSA加密 要注意的问题
针对java后端进行的RSA加密,android客户端进行解密,结果是部分乱码的问题:注意两点,编码问题和客户端使用的算法问题 即:都使用UTF-8编码,Base64使用一致,另外,使用下面的代码在后 ...
随机推荐
- css 嵌套 元素所属类别
元素所属类别 Metadata content(元数据元素)(8) base,link,meta,noscript,script,style,template, title Flow content( ...
- 好用的log
Log.getStackTraceString(new Throwable())
- CSS控制鼠标滑过时的效果
用css控制鼠标样式的语法如下:<span style="cursor:*">文本或其它页面元素</span>把 * 换成如下15个效果的一种: 下面是对这 ...
- C#堆栈原理(我有两个例子测试你到底会不会)
背景 上次写了一篇文章关于try finnally的一些疑问(被我用windows live覆盖了,草),后来经过大神们解释,我明白了在我理解了try.finnally运行原理后,还欠缺的就是关于值类 ...
- X-Plane数据交互
要用X-Plane进行二次开发,免不了需要进行参数的传递,下面我们来看看与X-Plane进行数据交互都有哪些方式. 与FSX和Flightgear基本一样,X-Plane支持插件,自然也支持通过插件进 ...
- Struts2中使用execAndWait后,在 Action中调用getXXX()方法报告java.lang.NullPointerException异常的原因和解决方法
使用 Struts2 编写页面,遇到一个要长时间运行的接口,因此增加了一个execAndWait ,结果在 Action 中调用 getContext()的时候报告异常 ActionContext c ...
- 封装cookie组件
var Cookie = { // 读取 get: function(name){ var cookieStr = "; "+document.cookie+"; &qu ...
- PhotoSwipe.js 相册展示插件学习
PhotoSwipe.js官网:http://photoswipe.com/,在这个网站上可以下载到PhotoSwipe的文件以及相关的例子. 这个组件主要是用来展示图片.相册用的,还是很实用的. 一 ...
- 面试小结(java基础)
一个.java源文件中可以有多个类吗?(内部类除外)有什么条件?带着这个疑惑,动手建几个测试类, 揭开心中的疑惑.以下是解开疑惑过程: package test;/** * 一个.java源文件中可以 ...
- web一点小结
1, AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 不是新的编程语言,而是一种使用现有标准的新方法. AJAX ...