RSA加密、解密 JAVA版 lua版 js版

安全加密总结
一、近代密码学
恩尼格玛密码机:(被人工智能之父图灵破解)
核心使用了位移和替换算法,(这种方式的密码可以采用频度分析法进行破解)
二、现代密码学
1、加密方式
(1)流加密
对信息流中的每个元素(一个字母或一个bit)作为基本的处理单元进行加密最后拼接成密文
(2)块加密
先对信息流进行分块,再对每个块进行加密
(3)举例
例如原文为abcd、流加密先对a加密、再对b加密、再对c加密、再对d加密,最后吧加密后的数据拼接组成密文。块加密先对原文分块比如abc 作为第一块、然后d+xx+xx为第二块(xx为补位数据),然后对每个块进行加密,最后拼接组成一个密文
2、加密模式
(1)、ECB模式
需要对加密的消息按照块分为数个块,并对每个块进行独立加密
优点:可以并行处理数据
缺点:同样的原文生成同样的密文,不能很好的保护数据。同时加密,原文是一样的,加密出来的密文也一样的
(2)、CBC模式
密码块链接。每个明文块先与前一个密文块进行异或后,在进行加密。在这种方法中,每个密文块都依赖前一个明文块。
优点:同样的原文生成的密码不一样
缺点:串行处理,速度慢
3、加密算法
1、散列函数(即哈希函数)
常用的有MD5、SHA-1、SHA-256、SHA-512(这种函数加密属于单项加密,不可逆)
MD5可以将任意长度的原文加密生成一个长度为128bit(16字节)的哈希值
SHA-1可以将任意长度的原文加密生成一个长度为160bit(20字节)的哈希值
SHA-256可以将任意长度的原文加密生成一个长度为256bit(32字节)的哈希值
SHA-512可以将任意长度的原文加密生成一个长度为512bit(64字节)的哈希值

2、对称加密(特点密钥相同)
对称加密,加密和解密使用同一把密钥
1)常用算法
常用的有DES、3DES 、AES、DESX、Blowfish、RC4、RC5、RC6。
2)、 DES(已被破解、不推荐使用)
即数据加密标准,是一种加密算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准,并在非密级政府通信中使用。
特点:加密速度快,可以加密大文件。文件可逆
3)、 3DES(速度慢、不推荐使用)
DES升级版
1)、 AES(推荐使用)
高级加密标准,是下一代的加密算法标准,速度快,安全级别高
3、非对称加密(密钥对、最安全加密算法)
非称加密,加密和解密使用不同的密钥密钥,
即使用公钥加密的数据只能使用私钥解密
即使用私钥加密的数据只能使用公钥解密

1)、常用的算法
RSA、ECC(移动设备用)、DSA(数字签名较优)

2)RSA算法
1、参数说明
(1)m 加密数据
(2)N密钥长度 (注意RSA密钥一般是1024位,重要场合则为2048位)
(3)c加密数据
(4)e公钥指数
(5)d私钥指数
(6)符号^表示数学上的指数运算;mod表示模运算,即相除取余数。
2、RSA算法推导
(1)计算得到N
使用欧拉函数
φ(n) = (p-1)(q-1) (注:p和q为两个质数,所为质数即只能被1和它本身整除的数)
例如:7 和11就是两个质数
N=37=21
φ(77)等于2
6 即12
(2)得到公钥指数e
随机选择一个整数e作为公钥,条件是1< e < φ(n),且e与φ(n) 互质
在1到12之间,随机选择了5作为公钥e。(实际应用中,常常选择65537。)
(3)计算私钥指数d
使得d满足(de) mod φ(21) = 1 即(d5)mod 12=1
在这里插入图片描述

通过试算我们找到,当d=5时,e×d mod φ(21) = 1等式成立。因此,可令d=7。从而我们可以设计出一对公私密钥,加密密钥(公钥)为:KU =(e,n)=(5,21),解密密钥(私钥)为:KR =(d,n)=(5,21)。
(4)明文加密
测试两组数据
给字符’c’加密 码值为3
给字符’f’加密 码值为6
m^e mod N=c 即 3^5 mod 21=12
m^e mod N=c 即 6^5 mod 21=6
(5)密文解密
c^d mod N=m 即 12^5 mod 21=3 对应字符‘c’
c^d mod N=m 即 6^5 mod 21=6 对应字符‘f’

3、RSA加密解密公式
1、加密公式:m^e mod N=c
2、解密公式:c^d mod N=m
4、RSA使用注意事项
RSA的分组长度太大,为保证安全性,n至少也要512位以上,使运算代价很高,尤其是速度很慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。
JAVA和lua集成注意问题:
1、密钥对生成N值最好使用512、1024、2048这个数据的大小会决定生成密钥的长度,并且还会影响加密原文的长度,还会意向加密的效率
2、生成密钥对使用的标准是pkcs8,所以用其他语言生成密钥时要注意
Lua其中pkcs1生成如下
在这里插入图片描述

Lua其中pkcs8生成如下
在这里插入图片描述

填充模式注意事项:
1、两边填充模式不同可能造成加密解密出现乱码。和报错
例如lua中使用PADDING.RSA_PKCS1_PADDING这种填充对应java为PKCS1Padding
还有其他的填充模式可以对照响应语言的API去查看
2、加密解密数据base64加密方式不同造成问题
例如:Lua中使用ngx.encode_base64和ngx.decode_base64加解密时java中使用import sun.misc.BASE64Decoder这个包中的Base进行加解密
3、数据网络传输出现的问题
使用Lua私钥签名加密,调用java公钥验签的时候出现Base加密的数据在传输过程中把+改成了空格,这样在验签的时候数据不一致验签失败,采用下图处理

在这里插入图片描述

Lua框架支撑加密解密方式
目前市面上提供的Lua的 rsa框架很少只有一个成熟的lua-resty-rsa
这个框架底层使用C语言进行开发,研究发现C语言使用了Openssl框架实现Openssl是使用C开发,提供了大量的加密算法库
1、方法有生成密钥对方法支持支持的key_type 即标准有PKCS#1和PKCS#8两种
Lua加密
公钥加密(lua)+私钥解密(其他应用)
私钥加密签名(lua)+公钥验签(其他应用)

Lua解密
公钥解密(其他应用)+私钥解密(Lua)
私钥加密(其他应用)+公钥解密(Lua)

3)RSA实现示例
1、Lua 实现使用
1、参考网站 https://github.com/spacewander/lua-resty-rsa
2、说明:lua-resty-rsa是Openresty集成rsa的一个框架
一、lua-resty-rsa集成到Openresty
1、下载
https://github.com/spacewander/lua-resty-rsa到本地
2、复制rsa.lua脚本
在这里插入图片描述

3、打开项目的如下目录粘贴rsa.lua
在这里插入图片描述

二、lua-resty-rsa集成到Openresty
1、打开gateway项目
复制rsa.lua到lib目录
在这里插入图片描述

3、编写脚本例子
1、rsa_test.lua

– Created by IntelliJ IDEA.
– User: admin
– Date: 2021/4/7
– Time: 18:08
– To change this template use File | Settings | File Templates.

ngx.req.read_body()
local body=ngx.req.get_body_data()

local cjson = require(“cjson”);
–local d=cjson.encode(body)
–ngx.log(ngx.INFO,"-------d---------"…body.data)

–http声明
local zhttp = require(“resty.http”)
local httpc = zhttp.new()
httpc:set_timeout(30000)
local rsa_util = require(“rsa_util”)
local url=“http://10.221.100.145:8076/”;
–生成证书
function rsa_init_keyTest()
local ReadAndWriteFile = require(“ReadAndWriteFile”)
local VmPath = require(“VmPath”)
local rsa_public_key1, rsa_priv_key1, err =rsa_util:rsa_init_key(1024);
ReadAndWriteFile:write_file(VmPath.rsa_public_key_path,rsa_public_key1)
ReadAndWriteFile:write_file(VmPath.rsa_priv_key_path,rsa_priv_key1)
ngx.say(rsa_public_key1…"=============="…rsa_priv_key1)
end

–公钥加密
function publicEncryptionTest(data)
local result=rsa_util:publicEncryption(data);
local res, err_ = httpc:request_uri(url…“privateDecryptBnc”, {
method = “POST”,
body= “password=”…result,
headers = {
[“Content-Type”] = “application/x-www-form-urlencoded; charset=utf-8”,
}
})

if res ~= nil then
    if res.status == ngx.HTTP_OK then
        ngx.log(ngx.DEBUG, "响应:", res.body)
        ngx.say(res.body)
        return res.body
    else
        ngx.log(ngx.ERR, "出错")
        ngx.exit(res.status)
    end
else
    ngx.log(ngx.ERR, "出错")
    ngx.exit(500)
end

end

–私钥签名
function privSignDataTest(sources)
local result=rsa_util:privSigData(sources);
local res, err_ = httpc:request_uri(url…“publicSignBnc”, {
method = “POST”,
body= “password=”…result…"&sources="…sources,
headers = {
[“Content-Type”] = “application/x-www-form-urlencoded”
}
})
if res ~= nil then
if res.status == ngx.HTTP_OK then
ngx.log(ngx.DEBUG, “响应:”, res.body)
ngx.say(res.body)
return res.body
else
ngx.log(ngx.ERR, “出错”)
ngx.exit(res.status)
end
else
ngx.log(ngx.ERR, “出错”)
ngx.exit(500)
end
end

–私钥解密
function privDecryptDataTest(sources)
local result=rsa_util:privDecryptData(sources);
ngx.say(result)
end

local postargs = ngx.req.get_uri_args()
local type = postargs[“type”]
local data = postargs[“data”]
if typenil or datanil then
local postargs1 = ngx.req.get_post_args()
type = postargs1[“type”]
data = postargs1[“data”]
end

–data=urlDecode(data);
if(type==‘1’)then
rsa_init_keyTest();
elseif (type==‘2’) then
publicEncryptionTest(data)
elseif (type==‘3’) then
privSignDataTest(data);
elseif (type==‘4’) then
privDecryptDataTest(data);
end

2、rsa_util.lua

– Created by IntelliJ IDEA.
– User: lpp
– Date: 2021/4/25
– Time: 13:44
– To change this template use File | Settings | File Templates.

–rsa
local rsa_util={}
local resty_rsa = require “resty.rsa”
local ReadAndWriteFile = require(“ReadAndWriteFile”)
local VmPath = require(“VmPath”)
function rsa_util:rsa_init_key(size)
local rsa_public_key1, rsa_priv_key1, err = resty_rsa:generate_rsa_keys(size,true)
if not rsa_public_key1 then
ngx.say('generate rsa keys err: ', err)
end
return rsa_public_key1, rsa_priv_key1, err
end

–获取公钥key
function rsa_util:rsa_public_key()
–在共享缓存中获取
local rsa_public_key =ngx.shared.dict_sp_rsa_key:get(“rsa_public_key”)
if rsa_public_keynil then
–在文件中获取
rsa_public_key= ReadAndWriteFile:read_file(VmPath.rsa_public_key_path)
ngx.shared.dict_sp_rsa_key:set(“rsa_public_key”,rsa_public_key)
end
return rsa_public_key
end
–获取私钥key
function rsa_util:rsa_priv_key()
–在共享缓存中获取
local rsa_priv_key =ngx.shared.dict_sp_rsa_key:get(“rsa_priv_key”)
if rsa_priv_key
nil then
–在文件中获取
rsa_priv_key= ReadAndWriteFile:read_file(VmPath.rsa_priv_key_path)
ngx.shared.dict_sp_rsa_key:set(“rsa_priv_key”,rsa_priv_key)
end
return rsa_priv_key
end
–公钥加密
function rsa_util:publicEncryption(data)
local pub, err =resty_rsa:new({public_key = rsa_util:rsa_public_key(),padding = resty_rsa.PADDING.RSA_PKCS1_PADDING});
if not pub then
ngx.say("new rsa err: ", err)
return
end
local encrypted, err = pub:encrypt(data)
if not encrypted then
ngx.say("failed to encrypt: ", err)
return
end
return ngx.encode_base64(encrypted)
end

–私钥签名
function rsa_util:privSigData(data)
local priv, err = resty_rsa:new({ private_key = rsa_util:rsa_priv_key(),padding = resty_rsa.PADDING.RSA_PKCS1_PADDING,algorithm = “sha256WithRSAEncryption”})
if not priv then
ngx.log(ngx.INFO,"new rsa err: "…err)
return
end
local sig, err = priv:sign(data)
if not sig then
ngx.log(ngx.INFO,“failed to sign:”…err)
return
end
return ngx.encode_base64(sig)
end

–私钥解密
function rsa_util:privDecryptData(data)
local priv, err = resty_rsa:new({ private_key = rsa_util:rsa_priv_key(),padding = resty_rsa.PADDING.RSA_PKCS1_PADDING})
if not priv then
ngx.log(ngx.INFO,“new rsa err: “…err)
return
end
–base64解码
local enc = ngx.decode_base64(data)
local decrypt, err = priv:decrypt(enc)
if not decrypt then
ngx.log(ngx.INFO,“failed to decryp:”…err)
return
end
return decrypt;
end
return rsa_util
3、ReadAndWriteFile.lua
local ReadAndWriteFile={}
–对文件
function ReadAndWriteFile:read_file(file_path)
local file =io.open(file_path,“r”)
local data=file:read(”*a”) --读取整个文件
file:close()
return data
end
function ReadAndWriteFile:write_file(file_path,data)
local file =io.open(file_path,“w+”)
file:write(data) --读取整个文件
file:close()
end
return ReadAndWriteFile
4、VmPath.lua

local bak=“D:/work/DAma/hjpt/bcp.gateway/Nginx/bak/”;
local VmPath={
rsa_public_key_path=bak…“rsa_public_key.crt”,
rsa_priv_key_path=bak…“rsa_priv_key.crt”
}

return VmPath

2、java实现使用
采用springboot开发
1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>


4.0.0

<groupId>org.example</groupId>
<artifactId>rsaclient</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!-- 移除嵌入式tomcat插件 -->
        <!-- <exclusions>
              <exclusion>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-tomcat</artifactId>
              </exclusion>
          </exclusions>-->
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcpkix-jdk15on</artifactId>
        <version>1.64</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.7</version>
    </dependency>
</dependencies>
2、RsaController.java package com.sihua.rsa.controller;

import com.sihua.rsa.service.SynchronizationService;
import com.sihua.rsa.utils.RSAUtils;
import com.sihua.rsa.utils.RsaJs;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.File;
import java.nio.charset.Charset;

@Controller
public class RsaController {
@Autowired
private SynchronizationService syncservice;
//公钥
@Value(" r s a . p u b l i c K e y P a t h " ) p r i v a t e S t r i n g p u b l i c K e y P a t h ; / / 私 钥 @ V a l u e ( " {rsa.publicKeyPath}") private String publicKeyPath; //私钥 @Value(" rsa.publicKeyPath")privateStringpublicKeyPath;//@Value("{rsa.privateKeyPath}")
private String privateKeyPath;
/**
* 生成密钥对
* @return
*/
@ResponseBody
@RequestMapping("/initKey")
public String initKey() throws Exception{
RSAUtils.initKey(1024,publicKeyPath,privateKeyPath);
return “key生成成功”;
}

/**
 * 公钥加密
 * @param password
 * @return
 */
@ResponseBody
@RequestMapping("/publicDataBnc")
public String publicDataBnc(String password) throws Exception{
    System.out.println("原数据:"+password);
    String data = RSAUtils.publicEncrypt(password,publicKeyPath);
    System.out.println("公钥加密后数据:"+data);
    //调用服务端
    String s = syncservice.postSend(data);
    return s;
}

/**
 * 公钥验签
 * @param password
 * @return
 */
@ResponseBody
@RequestMapping("/publicSignBnc")
public boolean publicSignBnc(String password,String sources) throws Exception{
    password=password.replaceAll(" ", "+");
    System.out.println("lua加密数据:"+password);
    boolean s = RSAUtils.verify(password,sources,publicKeyPath);
    System.out.println("验签结果:"+s);
    return s;
}

/**
 * 私钥解密
 * @param password
 * @return
 */
@ResponseBody
@RequestMapping("/privateDecryptBnc")
public String privateDecryptBnc (String password,String a) throws Exception{
    password=password.replaceAll(" ", "+");
    System.out.println("lua加密数据:"+password);
    String s = RSAUtils.privateDecrypt(password,privateKeyPath);
    System.out.println("原始数据=========="+s);
    return s;
}







/**
 * 私钥解密
 * @return
 */
@RequestMapping("/getPrivateDecryptJs")
@ResponseBody
public String getPrivateDecryptJs (String password) throws Exception{
    String privateKeyStr = FileUtils.readFileToString(new File(privateKeyPath), Charset.forName("utf-8"));
    System.out.println("JS加密数据:=="+password);
    String publicStr = RsaJs.privateDecryptData(password,privateKeyStr );
    System.out.println("解密字符:=="+publicStr);
    return publicStr;
}
/**
 * 公钥钥解密
 * @return
 */
@RequestMapping("/getPublicDecryptJs")
@ResponseBody
public String getPublicDecryptJs (String password) throws Exception{
    String publicKeyStr = FileUtils.readFileToString(new File(publicKeyPath), Charset.forName("utf-8"));

    System.out.println("JS加密数据:=="+password);
    String publicStr = RsaJs.publicDecryptData(password,publicKeyStr);
    System.out.println("解密字符:=="+publicStr);
    return publicStr;
}

/**
 * 测试页面
 * @return
 */
@RequestMapping("/test")
public String test (Model model, String data) throws Exception{
    model.addAttribute("data",data);
    return "/test";
}

}
3、SynchronizationService.java
package com.sihua.rsa.service;

import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;

@Service
public interface SynchronizationService {
String postSend(String data) throws UnsupportedEncodingException;
}
4、SynchronizationServiceImpl.java
package com.sihua.rsa.service.impl;

import com.sihua.rsa.service.SynchronizationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;

@Service
public class SynchronizationServiceImpl implements SynchronizationService {
@Autowired
private RestTemplate restTemplate;
//发送lua
private String retryUrl=“http://10.221.100.145:8088/rsatest”;
@Override
public String postSend(String data) throws UnsupportedEncodingException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
requestEntity.add(“data”, data);
requestEntity.add(“type”, “4”);
String s = restTemplate.postForObject(retryUrl, requestEntity, String.class);

  return s;
}

}
5、RSAUtils.java lua工具类
package com.sihua.rsa.utils;

import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import sun.plugin.com.Utils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**

  • RSA 加密工具
  • 加密过长的会报错:
    Data must not be longer than 245 bytes
    原因是应为不同长度的密钥对应可以加密不同最大长度的原文,2048就对应245
    解决办法是:
    1.分段
    2.RSA加密是有长度限制的.单纯用RSA加密较长数据时得使用分段加密,效率低下.用RSA+AES是比较主流的做法:AES加密数据产生密文,RSA加密AES密钥产生加密后的AES密钥,然后将密文和加密后的AES密钥一起传输
  • @author hank
  • @since 2020/4/28 0028 下午 15:42
    */

public class RSAUtils {
private static final String CHARSET = “UTF-8”;
private static final BASE64Decoder decoder64 = new BASE64Decoder();
private static final BASE64Encoder encoder64 = new BASE64Encoder();

/**
 * 生成公私钥
 * @param keySize
 * @return
 * @throws NoSuchAlgorithmException
 */
public static void initKey(int keySize,String publicKeyPath,String privateKeyPath) throws NoSuchAlgorithmException, IOException {
    BASE64Encoder encoder64 = new BASE64Encoder();
    //生成密钥对
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
    keyGen.initialize(keySize);
    KeyPair pair = keyGen.generateKeyPair();
    PrivateKey privateKey = pair.getPrivate();
    PublicKey publicKey = pair.getPublic();
    String rsaPublicKey=encoder64.encode(publicKey.getEncoded());
    String rsaPrivateKey=encoder64.encode(privateKey.getEncoded());
    //这里可以将密钥对保存到本地
    System.out.println("公钥:"+rsaPublicKey);
    System.out.println("私钥:"+rsaPrivateKey);
    FileUtils.writeStringToFile(new File(publicKeyPath),rsaPublicKey,Charset.forName(CHARSET));
    FileUtils.writeStringToFile(new File(privateKeyPath),rsaPrivateKey,Charset.forName(CHARSET));
}
//获取私钥key
public static PrivateKey getPrivateKey(String privateKeyPath) {
    try {
        String privateKeyStr = FileUtils.readFileToString(new File(privateKeyPath), Charset.forName(CHARSET));
        PKCS8EncodedKeySpec pKCS8EncodedKeySpec=new PKCS8EncodedKeySpec(decoder64.decodeBuffer(privateKeyStr));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pKCS8EncodedKeySpec);
        return privateKey;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
//获取公钥key
public static PublicKey getPublicKey(String publicKeyPath) {
    try {
        String privateKeyStr = FileUtils.readFileToString(new File(publicKeyPath), Charset.forName(CHARSET));
        X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(decoder64.decodeBuffer(privateKeyStr));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        return publicKey;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
/**
 * 私钥加密
 * @param data
 * @return
 * @throws IOException
 */
public static String privateEncrypt(String data,String privateKeyPath) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException {

    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(privateKeyPath));
    return encoder64.encode(cipher.doFinal(data.getBytes(CHARSET)));
}


/**
 * 公钥解密
 * @param data
 * @param publicKeyPath
 * @return
 */
public static String publicDecrypt(String data,String publicKeyPath) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException {

    byte[] encryptDataBytes= decoder64.decodeBuffer(data);
    Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
    Security.addProvider(provider);
    //解密
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding",provider);
    cipher.init(Cipher.DECRYPT_MODE, getPublicKey(publicKeyPath));
    byte[] bytes = cipher.doFinal(encryptDataBytes);
    String s = new String(bytes, Charset.forName("UTF-8"));
    return s;
}

/**
 * 公钥验签
 * @param data
 * @return
 */
public static boolean verify(String data, String sources,String publicKeyPath) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException, SignatureException {
    Signature publicSignature = Signature.getInstance("SHA256withRSA");
    publicSignature.initVerify(getPublicKey(publicKeyPath));
    publicSignature.update(sources.getBytes(Charset.forName("UTF-8")));

    byte[] signatureBytes = decoder64.decodeBuffer(data);

    return publicSignature.verify(signatureBytes);
}

/**
 * 公钥加密
 * @param data
 * @return
 */
public static String publicEncrypt(String data,String publicKeyPath) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException {
    byte[] encryptDataBytes=new String(data).getBytes(CHARSET);
    //解密
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKeyPath));
    String encode = encoder64.encode(cipher.doFinal(encryptDataBytes));
    encode=encode.replaceAll("\r\n","");
    return encode;
}

/**
 * 私钥解密
 * @param data
 * @return
 * @throws IOException
 */
public static String privateDecrypt(String data,String privateKeyPath) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException {
    Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
    Security.addProvider(provider);
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding",provider);cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKeyPath));
    byte[] bytes = decoder64.decodeBuffer(data);
    return new String(cipher.doFinal(bytes),CHARSET);
}




public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException {
   initKey(2048,"","");
    System.out.println("--------------------------");
    System.out.println("私钥加密---公钥解密");
    String str1="测试rsa算法1";
    System.out.println("原数据:"+str1);
    String privateEncrypt = privateEncrypt(str1,"");
    System.out.println("密文:"+privateEncrypt);
    String publicDecrypt = publicDecrypt(privateEncrypt,"");
    System.out.println("解密:"+publicDecrypt);
    System.out.println("--------------------------");

    System.out.println("--------------------------");
    System.out.println("私钥加密---公钥解密");
    String str2="测试rsa算法2";
    System.out.println("原数据:"+str2);
    String publicEncrypt = publicEncrypt(str2,"");
    System.out.println("密文:"+publicEncrypt);
    String privateDecrypt = privateDecrypt(publicEncrypt,"");
    System.out.println("解密:"+privateDecrypt);

}

}
6、RsaJs.java js实现工具类
package com.sihua.rsa.utils;

import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.engines.RSAEngine;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PublicKeyFactory;

import javax.crypto.Cipher;
import java.nio.charset.Charset;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;

public class RsaJs {
final static String publicKeyStr="";
final static String pairKeyStr="";
static String charset = “utf-8”;

public static void main(String[] args) {

}
// KeyPair is a simple holder for a key pair.
private static final KeyPair keyPair = initKey();
/**
 * 初始化方法,产生key pair,提供provider和random
 * @return KeyPair instance
 */
private static KeyPair initKey() {
    try {
        // 添加provider
        Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
        Security.addProvider(provider);
        // 产生用于安全加密的随机数
        SecureRandom random = new SecureRandom();
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider);
        generator.initialize(1024, random);
        return generator.generateKeyPair();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

/**
 * 获取公钥public key
 * @return public key字符串
 */
public static String generateBase64PublicKey() {

    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    // encodeBase64(): Encodes binary data using the base64
    // algorithm but does not chunk the output.
    // getEncoded():返回key的原始编码形式
    System.out.println("公钥:==="+new String(Base64.encodeBase64(publicKey.getEncoded())));
    System.out.println("私钥:==="+new String(Base64.encodeBase64(privateKey.getEncoded())));
    return new String(Base64.encodeBase64(publicKey.getEncoded()));
}

/**
 * 公钥解密数据
 * @param string 需要解密的字符串
 * @return 破解之后的字符串
 */
public static String publicDecryptData(String string,String publicKeyBase) {
    // decodeBase64():将Base64数据解码为"八位字节”数据
    return new String(publicDecrypt(Base64.decodeBase64(string.getBytes(Charset.forName(charset))),publicKeyBase), Charset.forName(charset));
}

/**
 * 私钥解密数据
 * @param string 需要解密的字符串
 * @return 破解之后的字符串
 */
public static String privateDecryptData(String string,String privateKeyBase) {
    // decodeBase64():将Base64数据解码为"八位字节”数据
    return new String(privateDecrypt(Base64.decodeBase64(string.getBytes(Charset.forName(charset))),privateKeyBase), Charset.forName(charset));
}

private static byte[] publicDecrypt(byte[] byteArray,String publicKeyBase) {
try {

        AsymmetricBlockCipher cipher = new RSAEngine();
        //这里也可以从流中读取,从本地导入
        byte[] privateInfoByte=Base64.decodeBase64(publicKeyBase);
        AsymmetricKeyParameter pubKey = PublicKeyFactory.createKey(privateInfoByte);
        //true表示加密
        cipher.init(false, pubKey);
        //byte[] publicInfoBytes= Base64.decodeBase64(data);
        byte[] encryptDataBytes = cipher.processBlock(byteArray
                , 0, byteArray.length);
        return encryptDataBytes;
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}

/*private static byte[] publicDecrypt(byte[] byteArray,String publicKeyBase) {
    try {
        Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
        Security.addProvider(provider);
        // Cipher: 提供加密和解密功能的实例
        // transformation: "algorithm/mode/padding" RSA/None/PKCS1Padding
        Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", provider);

        byte[] publicInfoByte=Base64.decodeBase64(publicKeyBase);
        //PrivateKey privateKey = keyPair.getPrivate();

        X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(publicInfoByte);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

        // RSAPrivateKeySpec rsaPrivateKeySpec=new RSAPrivateKeySpec();
        // 初始化
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        // doFinal(): 加密或者解密数据
        byte[] plainText = cipher.doFinal(byteArray);
        return plainText;
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}*/

/*private static byte[] privateDecrypt(byte[] byteArray,String privateKeyBase64) {
    try {
        AsymmetricBlockCipher cipher = new RSAEngine();

        //这里也可以从流中读取,从本地导入
        byte[] privateInfoByte=Base64.decodeBase64(privateKeyBase64);
        AsymmetricKeyParameter pubKey = PrivateKeyFactory.createKey(privateInfoByte);
        //true表示加密
        cipher.init(false, pubKey);
        //byte[] publicInfoBytes= Base64.decodeBase64(data);
        byte[] encryptDataBytes = cipher.processBlock(byteArray
                , 0, byteArray.length);
        return encryptDataBytes;
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}*/
private static byte[] privateDecrypt(byte[] byteArray,String privateKeyBase64) {
    try {
        Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
        Security.addProvider(provider);
        // Cipher: 提供加密和解密功能的实例
        // transformation: "algorithm/mode/padding" RSA/None/PKCS1Padding
        Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding",provider);

        byte[] privateInfoByte=Base64.decodeBase64(privateKeyBase64);
        //PrivateKey privateKey = keyPair.getPrivate();

        PKCS8EncodedKeySpec pKCS8EncodedKeySpec=new PKCS8EncodedKeySpec(privateInfoByte);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pKCS8EncodedKeySpec);

        // RSAPrivateKeySpec rsaPrivateKeySpec=new RSAPrivateKeySpec();
        // 初始化
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        // doFinal(): 加密或者解密数据
        byte[] plainText = cipher.doFinal(byteArray);
        return plainText;
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}

}
3、JS实现使用
1、test.html

Title

})

</script>

js公钥加密-java私钥解密 结果
js私钥加密-java公钥解密 结果 2、jsencrypt.min.js 下载

4)RSA 验证
http://localhost:8088/rsatest?type=1&data=2 //lua生成证书 (注:要和java联调需要把生成的证书拷贝到java中的resources目录下)
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

http://localhost:8088/rsatest?type=2&data=2 //lua公钥加密java私钥解密

在这里插入图片描述

http://localhost:8088/rsatest?type=3&data=2 //lua私钥签名java公钥验签
在这里插入图片描述
在这里插入图片描述

http://localhost:8076/publicDataBnc?password=12312 //java公钥加密 lua私钥解密
在这里插入图片描述

http://localhost:8076/test?data=1 js加密测试页面
在这里插入图片描述

5)RSA 示例源码下载
下载路径:https://pan.baidu.com/s/13kEzM2aSwYCVQKoo6BYjtQ 9ys1

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值