在上一篇文章中,我们已经将密钥的生成方法和流程,归纳总结。而本篇主要是讲如何利用密钥进行加解密。

首先,在上一篇文章中的我们生成了很多密钥,证书等等。

在上述生成的文件中,接收服务端加密报文:pkcs8_private_key.pem给安卓使用解密,private_key.p12 给IOS使用解密(IOS加密是public_key.der文件),rsa_public_key.pem是JAVA服务器端使用的加密密钥(双向通信需要用两套不一样的密钥)。发送加密报文:rsa_public_key.pem给安卓使用加密,public_key.der给IOS使用加密,pkcs8_private_key.pem在服务器端进行解密密钥。

其次,打开密钥文件后,一般长这个样子。

于是为了将其利用起来,写了如下代码:

 public static String readWantedText(String url) {
try {
FileReader fr = new FileReader(url);
BufferedReader br = new BufferedReader(fr);
StringBuffer sb = new StringBuffer(); String temp = "";// 用于临时保存每次读取的内容
temp = br.readLine();
while ((temp = br.readLine()) != null) {
if (temp.charAt(0) == '-') {
continue;
}
sb.append(temp);
} return sb.toString(); } catch (Exception e) {
e.printStackTrace();
return null;
}
}

获得以上密钥字符串之后,再将其转化为可用的密钥,转化私钥代码如下

 public static PrivateKey getPrivateKey(String key) throws Exception {

         byte[] keyBytes = key.getBytes();
keyBytes = Base64.decodeBase64(keyBytes);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}

转化公钥代码如下:

 public static PublicKey getPublicKey(String key) throws Exception {

         byte[] keyBytes = key.getBytes();
keyBytes = Base64.decodeBase64(keyBytes);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}

然后,得到了密钥之后我们进行加解密操作,其中一个重要的点就是117 可以参考此篇博文:http://www.metsky.com/archives/657.html,详细了解。这里关注点是,加密117字节加密 一下,解密用128解密。

加密函数如下:

 public static final String KEY_ALGORITHM = "RSA";
private static final int MAX_ENCRYPT_BLOCK = 117;
private static final int MAX_DECRYPT_BLOCK = 128; public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
byte[] keyBytes = Base64Utils.decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}

解密函数如下:

public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
throws Exception {
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}

上两段代码中,涉及到的转码代码为:

 public static byte[] decode(String base64) throws Exception {
return Base64.decode(base64.getBytes());
} public static String encode(byte[] bytes) throws Exception {
return new String(Base64.encode(bytes));
}

由此 我们就完成了对密钥的使用,现在我们通过一个简单的测试代码来检验我们这几篇文档的成果。

 public static void main(String[] args) {

         String publicFilePath = "E:\\test_public_key.pem";
String publickey = RSAForCommunication.readWantedText1(publicFilePath);
String word = "这是用来测试,加密效果的一句话,可以试试 有多长。但是目前的情况来看,是可以长场产出噶哈哈哈哈哈哈哈哈啊哈哈哈哈哈啊哈哈哈哈啊啊啊哈哈哈";
String encode ="";
try {
byte[] a = RSAForCommunication.encryptByPublicKey(word.getBytes(), publickey);
encode = Base64Utils.encode(a);
} catch (Exception e) { } System.out.println("-------加密之后的密文:");
System.out.println(encode); String filePath = "E:\\test_private_key.pem";
String key = RSAForCommunication.readWantedText1(filePath);
byte[] a;
try {
a = Base64Utils.decode(encode);
byte[] b = decryptByPrivateKey(a, key);
String deCodeStr = new String(b, "utf-8");
System.out.println("--------密文解密为:");
System.out.println(deCodeStr);
} catch (Exception ex) {
System.out.println("1");
} }

结果展示

最后,这里的密文在传输过程中会出现空格或者被转义的情况,请注意!这是因为安卓或者IOS使用了通信框架或者其他原因导致。会使得通信失败

如果你有更好的加解密办法请联系我。

——————————————————————————————————————————

补充

关于Base64的包 不建议使用 sun.misc.BASE64Encoder这个包,具体的原因是由于SUN公司卖给oracle之前,自己定义的一些类。并不在公布的API中,以后随时可能被删除掉,所以不建议使用。

建议使用 ,如:org.apache.commons.codec.binary.Base64类

最新文章

  1. Location对象、History对象
  2. 416. Partition Equal Subset Sum
  3. Modify a Stored Procedure using SQL Server Management Studio
  4. SQL Server 树查询
  5. openCV_java 图像二值化
  6. 使用ASP.NET Web API自带的类库实现对CORS的支持(在开发中使用这种方式)(转载)
  7. DFS ZOJ 1002/HDOJ 1045 Fire Net
  8. jquery,extjs中的extend用法小结
  9. 英特尔® 实感™ SDK R4 (v.6.0) 的全新特性
  10. PHP写入文件用file_put_contents代替fwrite优点多多(转)
  11. linux 查看外网IP
  12. 【三支火把】---队列和栈的C程序实现
  13. ruby文档
  14. Django 列的自定义显示
  15. 安装mavlink遇到的问题(future找不到)
  16. 关于IWMS后台登录问题总结
  17. 2017-2018-2 20165221实验二《Java面向对象程序设计》实验报告
  18. springbank 开发日志 springbank是如何注册handler的
  19. Unity Shader序列帧动画学习笔记
  20. redis+php实现微博功能(三)

热门文章

  1. Linux 上搭建 git 的服务器
  2. 在Angular项目下使用Umeditor
  3. jquery获取文件名称
  4. AngularJS的相关应用
  5. 记录——excel导出lua工具(python实现)
  6. React Native技术做的一个项目“微笑阅读”
  7. 使用openXML 不用插件导出excel
  8. js快速去除数组重复项
  9. kobo阅读器安装koreader
  10. OAuth及第三方登录