前几天说了手头项目用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. SQL Cursor 基本用法

     1 table1结构如下  2 id    int  3 name  varchar(50)  4   5 declare @id int  6 declare @name varchar(50) ...

  2. mxnet运行时遇到问题及解决方法

    1.训练好模型之后,进行预测时出现这种错误: mxnet.::] src/ndarray/ndarray.cc:: Check failed: ,) to.shape=(,) 这种问题的解决方法,在全 ...

  3. Python开发【第二十一篇】:Web框架之Django【基础】

    Python开发[第二十一篇]:Web框架之Django[基础]   猛击这里:http://www.cnblogs.com/wupeiqi/articles/5237704.html Python之 ...

  4. SQL SERVER 查看死锁的存储过程

    end

  5. mybatis for .net

    MyBatis For .NET学习笔记:开篇 http://chenkai.blog.51cto.com/2023960/763806 MyBatis For .NET学习笔记[2]:配置环境 ht ...

  6. Spring通过SchedulerFactoryBean实现调度任务的配置

    http://blog.csdn.net/hu_shengyang/article/details/19815201(里面是配置) 介绍SchedulerFactoryBean http://blog ...

  7. CentOS 7重装mysql编译过程报错解决方法

    错误记录: [ 82%] Building C object libmysql/CMakeFiles/clientlib.dir/__/sql-common/client.c.o/usr/local/ ...

  8. 删除我的电脑中360随身WiFi云U盘的图标

    可通过删除注册表的方法 运行-regedit 找到这个项 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\My ...

  9. JSONModel的基本使用

    JSONModel 是一个库,它能智能并且快速的创建出数据 model,你可以在你的 iOS 项目或者 OSX 项目上使用它. 使用前准备 添加 JSONModel 到你的工程中 1.需要的环境: A ...

  10. iOS 集成支付宝遇到的问题(续)

    调起支付宝进行支付时提示private key is null ,碰到这个问题有两种解决方案 第一种. 将私钥转成PKCS8替换一下原私钥即可 1.生成私钥pem,  执行命令openssl genr ...