前几天说了手头项目用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加密对象数据的更多相关文章

  1. Android RSA加密解密

    概述 RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困 难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数 ...

  2. android -------- RSA加密解密算法

    RSA加密算法是一种非对称加密算法.在公开密钥加密和电子商业中RSA被广泛使用 RSA公开密钥密码体制.所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计 ...

  3. PHP使用OPENSSL RSA加密解密数据

    加密数据有很多种方法,今天我们来看一下OPENSSL RSA的加密办法. 1.首先得安装php的openssl扩展 php -m | grep openssl 执行以上命令,确保已经安装了openss ...

  4. IOS, Android, Java Web Rest : RSA 加密和解密问题

    IOS, Android, Java Web Rest :  RSA 加密和解密问题 一对公钥私钥可以使用 OpenSSL创建, 通常 1024位长度够了. 注意: 1. 公钥私钥是BASE64编码的 ...

  5. 使用X.509数字证书加密解密实务(三)-- 使用RSA证书结合对称加密技术加密长数据

    一.  使用证书结合对称加密算法加.解密长数据 上一章节讨论了如何使用RSA证书加密数据,文中提到:“Dotnet的RSA实现有个特点,它必须要在明文中添加一些随机数,所以明文不能把128字节占满,实 ...

  6. RSA 加密

    iOS开发教程-iOS中的RSA加解密 在移动应用开发中常常遇到数据传输安全性的问题,尤其是在账户安全以及支付场景中的订单数据.或支付信息的传输中,正规的公司一定会要求对数据进行加密,当然有创业初期的 ...

  7. RSA Android加密的数据服务器上无法解密?

    一.android加密的数据服务器上无法解密? "算法/模式/填充" android的rsa加密方式是--------RSA/ECB/NoPadding或者RSA/None/NoP ...

  8. Android数据加密之Rsa加密

    前言: 最近无意中和同事交流数据安全传输的问题,想起自己曾经使用过的Rsa非对称加密算法,闲下来总结一下. 其他几种加密方式: Android数据加密之Rsa加密 Android数据加密之Aes加密 ...

  9. android 客户端 RSA加密 要注意的问题

    针对java后端进行的RSA加密,android客户端进行解密,结果是部分乱码的问题:注意两点,编码问题和客户端使用的算法问题 即:都使用UTF-8编码,Base64使用一致,另外,使用下面的代码在后 ...

随机推荐

  1. Java基础知识强化之集合框架笔记22:List集合的三个子类的特点(面试题)

    1. List:(面试题List的子类特点)(1)ArrayList: 底层数据结构是数组,查询快,增删慢. 线程不安全,效率高.(2)Vector: 底层数据结构是数组,查询快,增删慢. 线程安全, ...

  2. 了解php面向对象

    php 三大特性:封装.继承.多态,一直以来只知道其字,却不大了解其意思和具体使用,只是对继承有大概的了 解,优点是代码的重用性,oop概念,记得有一次我去面试,人家问我什么是oop,然后我答了很多什 ...

  3. Axiom3D学习日记 0.Axiom基础知识

    Axiom 3D Engine An open-source, cross-platform, managed 3D rendering engine for DirectX, XNA and Ope ...

  4. Ubuntu Server 14.04 下root无法ssh登陆

    今天安装了Ubuntu Server 14.04   在终端配置了root密码后,使用SecureCRT和putty竟然不能ssh登陆,SecureCRT一直提示密码不对,但是可以肯定输入的密码100 ...

  5. Deep Learning 学习随记(五)Deep network 深度网络

    这一个多周忙别的事去了,忙完了,接着看讲义~ 这章讲的是深度网络(Deep Network).前面讲了自学习网络,通过稀疏自编码和一个logistic回归或者softmax回归连接,显然是3层的.而这 ...

  6. java_设计模式_模板方法模式_Template Method Pattern(2016-08-11)

    定义: 定义一个操作中算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤.这里的算法的结构,可以理解为你根据需求设计出来的业务流程.特定的步骤就是指那些 ...

  7. phpcms v9 get调用标签整理

    常见的phpcms标签调用  1.调用本系统单条数据(调用ID为1的信息,标题长度不超过25个汉字,显示更新日期): "select * from phpcms_content where  ...

  8. python cx_Oracle install

    Ubuntu install  python-cx_Oracle 1: install alien tools  . sudo apt-get install alien 2: dowload fol ...

  9. Connect mysql on Linux from Windows

    ON LINUX: 1 sudo apt-get install mysql-server 2 sudo apt-get install python-dev 3 sudo apt-get insta ...

  10. 02:计算(a+b)*c的值

    总时间限制:  1000ms 内存限制:  65536kB 描述 给定3个整数a.b.c,计算表达式(a+b)*c的值. 输入 输入仅一行,包括三个整数a.b.c, 数与数之间以一个空格分开.(-10 ...