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

一对公钥私钥可以使用 OpenSSL创建, 通常 1024位长度够了.

注意:

1. 公钥私钥是BASE64编码的,私钥需要转换成PKCS8格式;

2. 密文是字节数组,可以转化为BASE64编码字符串或16进制字符串。

3.JAVA,Android RSA 加密默认是"RSA/None/NoPadding", IOS需要调用方法进行设置。

(1)IOS RSA 加密算法,

https://github.com/ideawu/Objective-C-RSA

加密模式是"RSA/None/NoPadding", IOS需要调用方法进行设置。

(2)Android, Java , RSA加密:

下面是Java代码 (公钥私钥需要替换成你自己的,否则不工作!)

加密默认是"RSA/None/NoPadding"

package com.jcfax.app.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.security.Security; import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException; import org.bouncycastle.jce.provider.BouncyCastleProvider; import sun.misc.BASE64Decoder;//将base64转换为byte[]
import sun.misc.BASE64Encoder;//转byet[]换为base64 import java.net.URLEncoder;
import java.net.URLDecoder;
import java.io.UnsupportedEncodingException; //================================================================================
public class RSAEncrypt { /** 指定加密算法为RSA */
private static String ALGORITHM = "RSA";
/** 指定key的大小 */
private static int KEYSIZE = 1024; //String source_text= "Hello,World!";
//RSA Public key
private static final String DEFAULT_PUBLIC_KEY=
"MIGfMA0GCSqGSIb3DwQEBAQUAA4GNADCBiQKBgQDSS5owhX3tsB5tCuVuJMZrmMrq" + "\r" +
"KmctKjAUOdBAFO2i5VvJzVTwwCxY3XJ2L9pAZZDKorpxCrkQ7b6sA+93lxJ6TABtq" + "\r" +
"kRaGaEJEE2GclgkkdCesozecGkDXitPQ/Y1i+HKVxnNxv9E/a/ChvfGn50DKIW1S" + "\r" +
"Pzna8iFwgEq1QcUrrfwIDAQAB" + "\r"; //RSA Private Key (PKCS8 格式)
private static final String DEFAULT_PRIVATE_KEY=
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANJLmjCFfe2wHm0K" + "\r" +
"5W4kxmuYyuoqZy0qMBQ50EAU7aLlW8nNVPALFjdcnYv2kBlkMqiunEKuRDtvqwD7" + "\r" +
"3eXEnpMAG2qRFoZoQkQTYZyWCSR0J6yjN5waQNeK09D9jWL4cpXGc3G/0T9r8KG9" + "\r" +
"8afnQMohbVI/OdryIWASrVBxSut/AgMBAAECgYEAj7qMT81tHB7bLLvdw0HvO2ra" + "\r" +
"hOEmU4AaDDjXVHT5VfRcn7hu7QEm1f++zgJeynvpA9ETi59/kv/naGy8ZGXV2nRG" + "\r" +
"cWK0U5+6DgT7oOeG6KlZie3Hw/KHPlKnwW3FoXRIh4bSGcxx6pxyrxCwQYKzM4Yc" + "\r" +
"VetYXBS6gnZbuj8D8YECQQD8+dl0rG2Xm/Khn0M69g3rStL4QAaLXGOcB0uiDl+J" + "\r" +
"trpw3D1fDN/yFrrE0VzxzvXxalGzVn4NOP/PZckvjUZ3AkEA1M8kg3xlPWQURfKZ" + "\r" +
"KpBphPa13v1V2ot43Ce2wHTwpxXU9Uj5cwlz/+Jv5VZSwiYNCXwPkv79Kh8d14nMZ" + "\r" +
"L+tdOQJBANrZav48jTKzftvDY+4GH1SGjqyk9wRpEONSjGPN+2iv4+rvHUi1YqeU" + "\r" +
"ck8CsF2gpbQMPlHfaX0W6ncJn1q75VECQCB84xEjq3z8y0+GYrWpyEIhO9CoEjRD" + "\r" +
"+JZ7hZ3J+2pGpK7qkFSnx/gXL7BN+8lyfW5t9L0FIgaqf6erdJvpLZkCQEmc2Ml2" + "\r" +
"bgTq5sWFr+KsI+yWxUgP76M4JP7u8/XeH7a16nJSj/D6xSpkYz9bYkOI2Ulh3wbE" + "\r" +
"sLxepdwmlvm3kSIY=" + "\r"; /**
* 私钥
*/
private RSAPrivateKey privateKey; /**
* 公钥
*/
private RSAPublicKey publicKey; /**
* 字节数据转字符串专用集合
*/
private static final char[] HEX_CHAR= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; /**
* 获取私钥
* @return 当前的私钥对象
*/
public RSAPrivateKey getPrivateKey() {
return privateKey;
} /**
* 获取公钥
* @return 当前的公钥对象
*/
public RSAPublicKey getPublicKey() {
return publicKey;
} /**
* 随机生成密钥对:1024位密钥
*/
public void genKeyPair(){
KeyPairGenerator keyPairGen= null;
try {
keyPairGen= KeyPairGenerator.getInstance(ALGORITHM);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
keyPairGen.initialize(KEYSIZE, new SecureRandom());
KeyPair keyPair= keyPairGen.generateKeyPair();
this.privateKey= (RSAPrivateKey) keyPair.getPrivate();
this.publicKey= (RSAPublicKey) keyPair.getPublic();
} /**
* 从文件中输入流中加载公钥
* @param in 公钥输入流
* @throws Exception 加载公钥时产生的异常
*/
public void loadPublicKey(InputStream in) throws Exception{
try {
BufferedReader br= new BufferedReader(new InputStreamReader(in));
String readLine= null;
StringBuilder sb= new StringBuilder();
while((readLine= br.readLine())!=null){
if(readLine.charAt(0)=='-'){
continue;
}else{
sb.append(readLine);
sb.append('\r');
}
}
loadPublicKey(sb.toString());
} catch (IOException e) {
throw new Exception("公钥数据流读取错误");
} catch (NullPointerException e) {
throw new Exception("公钥输入流为空");
}
} /**
* 从字符串中加载公钥
* @param publicKeyStr 公钥数据字符串
* @throws Exception 加载公钥时产生的异常
*/
public void loadPublicKey(String publicKeyStr) throws Exception{
//System.out.println("==print publicKeyStr==");
//System.out.println(publicKeyStr); try {
BASE64Decoder base64Decoder= new BASE64Decoder();
byte[] buffer= base64Decoder.decodeBuffer(publicKeyStr);
//System.out.println(new String(buffer));
KeyFactory keyFactory= KeyFactory.getInstance(ALGORITHM);
X509EncodedKeySpec keySpec= new X509EncodedKeySpec(buffer);
this.publicKey= (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此算法");
} catch (InvalidKeySpecException e) {
throw new Exception("公钥非法");
} catch (IOException e) {
throw new Exception("公钥数据内容读取错误");
} catch (NullPointerException e) {
throw new Exception("公钥数据为空");
}
} /**
* 从文件中加载私钥
* @param keyFileName 私钥文件名
* @return 是否成功
* @throws Exception
*/
public void loadPrivateKey(InputStream in) throws Exception{
try {
BufferedReader br= new BufferedReader(new InputStreamReader(in));
String readLine= null;
StringBuilder sb= new StringBuilder();
while((readLine= br.readLine())!=null){
if(readLine.charAt(0)=='-'){
continue;
}else{
sb.append(readLine);
sb.append('\r');
}
}
loadPrivateKey(sb.toString());
} catch (IOException e) {
throw new Exception("私钥数据读取错误");
} catch (NullPointerException e) {
throw new Exception("私钥输入流为空");
}
} public void loadPrivateKey(String privateKeyStr) throws Exception{
//System.out.println("==print privateKeyStr==");
//System.out.println(privateKeyStr); try {
BASE64Decoder base64Decoder= new BASE64Decoder();
byte[] buffer= base64Decoder.decodeBuffer(privateKeyStr);
//System.out.println(new String(buffer));
PKCS8EncodedKeySpec keySpec= new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory= KeyFactory.getInstance(ALGORITHM);
this.privateKey= (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此算法");
} catch (InvalidKeySpecException e) {
throw new Exception("私钥非法");
} catch (IOException e) {
throw new Exception("私钥数据内容读取错误");
} catch (NullPointerException e) {
throw new Exception("私钥数据为空");
}
} /**
* 加密过程
* @param publicKey 公钥
* @param plainTextData 明文数据
* @return
* @throws Exception 加密过程中的异常信息
*/
public byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception{
if(publicKey== null){
throw new Exception("加密公钥为空, 请设置");
}
Cipher cipher= null;
try {
cipher= Cipher.getInstance(ALGORITHM, new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] output= cipher.doFinal(plainTextData);
return output;
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此加密算法");
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
}catch (InvalidKeyException e) {
throw new Exception("加密公钥非法,请检查");
} catch (IllegalBlockSizeException e) {
throw new Exception("明文长度非法");
} catch (BadPaddingException e) {
throw new Exception("明文数据已损坏");
}
} /**
* 解密过程
* @param privateKey 私钥
* @param cipherData 密文数据
* @return 明文
* @throws Exception 解密过程中的异常信息
*/
public byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception{
if (privateKey== null){
throw new Exception("解密私钥为空, 请设置");
}
Cipher cipher= null;
try {
cipher= Cipher.getInstance(ALGORITHM, new BouncyCastleProvider());
cipher.init(Cipher.DECRYPT_MODE, privateKey); //Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
//final Cipher cipher = Cipher.getInstance(PADDING, PROVIDER); byte[] output= cipher.doFinal(cipherData);
return output;
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此解密算法");
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
}catch (InvalidKeyException e) {
throw new Exception("解密私钥非法,请检查");
} catch (IllegalBlockSizeException e) {
throw new Exception("密文长度非法");
} catch (BadPaddingException e) {
throw new Exception("密文数据已损坏");
}
} /**
* 字节数据转十六进制字符串
* @param data 输入数据
* @return 十六进制内容
*/
public static String byteArrayToString(byte[] data){ //char[] HEX_CHAR= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
StringBuilder stringBuilder= new StringBuilder();
for (int i=0; i<data.length; i++){
//取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
stringBuilder.append(HEX_CHAR[(data[i] & 0xf0)>>> 4]);
//取出字节的低四位 作为索引得到相应的十六进制标识符
stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
// if (i<data.length-1){
// stringBuilder.append(' ');
// }
}
return stringBuilder.toString();
} private static byte toByte(char c) {
byte b = (byte) "0123456789abcdef".indexOf(c);
return b;
}
/**
* 把16进制字符串转换成字节数组
* @param hex
* @return
*/ public static byte[] hexStringToByte(String hex) {
int len = (hex.length() / 2);
byte[] result = new byte[len];
char[] achar = hex.toCharArray();
for (int i = 0; i < len; i++) {
int pos = i * 2;
result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
}
return result;
} //===================================================================
//测试用例
public static void main(String[] args) { RSAEncrypt rsaEncrypt= new RSAEncrypt();
//rsaEncrypt.genKeyPair(); //加载公钥
try {
rsaEncrypt.loadPublicKey(RSAEncrypt.DEFAULT_PUBLIC_KEY);
System.out.println("Loading RSA Public Key,成功!");
} catch (Exception e) {
System.err.println(e.getMessage());
System.err.println("Loading RSA Public Key,失败!");
} //加载私钥
try {
rsaEncrypt.loadPrivateKey(RSAEncrypt.DEFAULT_PRIVATE_KEY);
System.out.println("Loading RSA Private Key,成功!");
} catch (Exception e) {
System.err.println(e.getMessage());
System.err.println("Loading RSA Private Key,失败!");
} long currentTime =System.currentTimeMillis();
System.err.println(currentTime/1000); //测试字符串
//System.out.println("--print source_text --");
String source_text= "Hello,World!";
// System.out.println(source_text);
// System.out.println("明文长度:"+ source_text.length()); try {
//使用公钥加密
System.out.println("==使用公钥加密==");
byte[] cipher_byte = rsaEncrypt.encrypt(rsaEncrypt.getPublicKey(), source_text.getBytes()); System.out.println(new String(cipher_byte));
System.out.println("密文长度:"+ cipher_byte.length); //for(int i=0;i<cipher_text.length;i++)
// System.out.println(cipher_text[i]); //System.out.println(RSAEncrypt.byteArrayToString(cipher_byte));
//String cipher_hex="7e4f2c4794d19a1800060f0d716411d8c1eebefb080415154eb39ef3f703377dec058b0c319f729b4fe40fba5656ee71f75efe1b7b80683207243e7ec1ee81b854ea39768a0bb190923a2437a1f51bff11fc4c0847cf6c4c46c4010f54af4334cd7a88ca9d846c3ea2e12e7d5744c949d174483bf78c08d68a89b4d5cdb9fc65";
//cipher_byte=RSAEncrypt.hexStringToByte(cipher_hex);
//System.out.println(new String(cipher_byte)); //使用私钥解密,从这里开始!
System.out.println("==使用私钥解密,得到明文!==");
//byte[] cipher_byte 密文二进制数组,最大长度小于128 Bytes.
byte[] plain_text = rsaEncrypt.decrypt(rsaEncrypt.getPrivateKey(), cipher_byte); System.out.println(new String(plain_text));
//System.out.println("明文长度:"+ plain_text.length);
//System.out.println(RSAEncrypt.byteArrayToString(plain_text)); } catch (Exception e) {
System.err.println(e.getMessage());
} }
}

--

IOS, Android, Java Web Rest : RSA 加密和解密问题的更多相关文章

  1. 【转】 我的java web登录RSA加密

    [转] 我的java web登录RSA加密 之前一直没关注过web应用登录密码加密的问题,这两天用appscan扫描应用,最严重的问题就是这个了,提示我明文发送密码.这个的确很不安全,以前也大概想过, ...

  2. Java Web项目RSA加密

    最近做的一个项目,服务器为Java,采用SSH框架,客户端为Android和IOS.当用户登录时,从客户端向服务器提交用户名和密码.这就存在一个问题,如果数据包在网络上被其他人截取了,密码就有可能泄露 ...

  3. JAVA WEB实现前端加密后台解密

    最近在研究登陆密码的加密,下边上具体代码,只是给出核心代码,具体的代码视业务而定吧,给位有什么问题或者意见请留言. 加密方法用的是AES-128-CBC,BASE64用的是org.apache.com ...

  4. RSA加密和解密工具类

    import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import java.security.*; i ...

  5. C# Java间进行RSA加密解密交互

    原文:C# Java间进行RSA加密解密交互 这里,讲一下RSA算法加解密在C#和Java之间交互的问题,这两天纠结了很久,也看了很多其他人写的文章,颇受裨益,但没能解决我的实际问题,终于,还是被我捣 ...

  6. C# Java间进行RSA加密解密交互(二)

    原文:C# Java间进行RSA加密解密交互(二) 接着前面一篇文章C# Java间进行RSA加密解密交互,继续探讨这个问题. 在前面,虽然已经实现了C# Java间进行RSA加密解密交互,但是还是与 ...

  7. C# Java间进行RSA加密解密交互(三)

    原文:C# Java间进行RSA加密解密交互(三) 接着前面一篇C# Java间进行RSA加密解密交互(二)说吧,在上篇中为了实现 /** * RSA加密 * @param text--待加密的明文 ...

  8. [更新]一份包含: 采用RSA JWT(Json Web Token, RSA加密)的OAUTH2.0,HTTP BASIC,本地数据库验证,Windows域验证,单点登录的Spring Security配置文件

    没有任何注释,表怪我(¬_¬) 更新: 2016.05.29: 将AuthorizationServer和ResourceServer分开配置 2016.05.29: Token获取采用Http Ba ...

  9. C# 与 Java Rsa加密与解密互通

    Rsa 加密标准的制定已经过去了十多年了. 这两天在看rsa 加密的文章,基本上都是在说 .net 与 java 之间的 rsa加密是不能互通的.因为项目有用到,所以花了点时间对rsa加密做了一点点了 ...

随机推荐

  1. topcoder srm 693 div1 -3

    1.给出一个$n$个顶点的无向带权图.其中顶点$i,i+1$之间存在边,$i,i+2$之间存在边.而且仅有这些边.现在删掉其中的一些边,剩下的边满足图仍然是2联通的情况下使得权值和最小? 思路:其实就 ...

  2. linux内核中的DMI是什么?

    答: 桌面管理接口(Desktop Management Interface).是用来获取硬件信息的,在内核中有一个配置项CONFIG_DMI用来添加此功能到内核中!

  3. linux下如何删除行首的数字?

    举例如下: 1.某文件jello.txt中有以下行 1111-yes 2222-no 3333-yes-no-no 2.删除jello.txt中每行行首的数字 cat jello.txt | cut ...

  4. centos6配置网络常见问题

    1. 启用网卡 查看网卡模块: lsmod 移除网卡:modprobe -r e1000 装载网卡: modprobe e1000 2. 配置网络 vim /etc/sysconfig/network ...

  5. LuoguP3792 由乃与大母神原型和偶像崇拜

    题目地址 题目链接 题解 由乃题还是毒瘤啊orz 显然的一个结论是,如果保证不重复,维护区间min,max然后判断max-min+1==r-l+1是否成立即可 但是有重复 于是就要orz题解区的各位大 ...

  6. Hbase与Oracle比较(列式数据库与行式数据库)

    Hbase与Oracle比较(列式数据库与行式数据库) 1 主要区别 Hbase适合大量插入同时又有读的情况 Hbase的瓶颈是硬盘传输速度,Oracle的瓶颈是硬盘寻道时间.   Hbase本质上只 ...

  7. [UVA-11100] The Trip

    题目大意 大箱子能装小箱子,求在满足最少箱子的情况下,最小化每个箱子中最大的箱子个数. 解析 想到二分枚举箱子数,然后贪心的选择放进箱子的位置. 最优策略一定是将最大的 \(m\) 个先找出来,然后把 ...

  8. 2017-2018-2 20165306 实验三《敏捷开发与XP实践》实验报告

    实验三<敏捷开发与XP实践>实验报告 实验报告封面 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一) 敏捷开发与XP实践-1 实验要求: 参考 代码规范 安装alibaba 插 ...

  9. Python cmd中输入'pip' 不是内部或外部命令,也不是可运行的程序或批处理文件。

    配置一下环境变量,找到 添加一下Scripts文件夹的路径,如:这是我的路径C:\Users\ck\AppData\Local\Programs\Python\Python36 就是你python的安 ...

  10. hdu 6071 Lazy Running 最短路建模

    Lazy Running Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others) P ...