生成RSA公钥私钥不仅可以通过代码去进行实现,还可以通过keytool去创建证书,进而用代码去读取证书中的公钥和私钥去进行加解密的操作。
1.keytool生成RSA证书
1.管理员身份进入dos环境 运行 keytool -genkey
注意红框部分,生成的证书将会在这个路径下面
运行后,会让你输入一系列名称,输入后尽量记住别输错,后面生成证书会用到,另外,会让你输入两个六位数的密码,两个密码可以一致。
2.运行 keytool -genkey -alias ceshi -keyalg RSA -keysize 2048 -keystore mykeystore -validity 400
此行命令解释为:将使用RSA算法生成2048位的公钥/私钥对及整数,密钥长度为2048位,证书有效期为400天。使用的密钥库为mykeystore文件,别名为ceshi(后面可以直接用这个别名来代表mykeystore文件)。
生成成功会让你输入密码,用之前的密码输入即可。
3.导出公钥证书 keytool -export -alias ceshi -keystore mykeystore -file ceshi.cer
解释为:keytool -export -alias 别名 -keystore 文件名 -file 证书名称 导出别名为ceshi的文件keystore,取一个证书名字.cer(此处证书的存放路径为上文截图的红框部分),不论是否报错,都去证书路径处查看是否有证书。
4.代码里面读取证书路径,从而拿到相应的rsa的公钥私钥去进行加解密的操作。
此处为我的证书路径,代码中无论读取哪个都行,读取第二个的时候会读取最新的数据(每次最新的数据会覆盖).
代码中识别本地生成的rsa证书,并进行加解密(公钥加密私钥解密),加密和验签的操作,基本符合我们的需求
package com.youfuli.apicenter.utils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.security.*;
import java.security.cert.Certificate;
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.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
public class RSAUtils {
public static final String CHARSET = "UTF-8";
public static final String RSA_ALGORITHM = "RSA";
/**
* 验签
*/
public static boolean verify(byte[] message, byte[] signMessage, PublicKey publicKey, String algorithm,
String provider) throws Exception {
Signature signature;
if (null == provider || provider.length() == 0) {
signature = Signature.getInstance(algorithm);
} else {
signature = Signature.getInstance(algorithm, provider);
}
signature.initVerify(publicKey);
signature.update(message);
return signature.verify(signMessage);
}
/**
* 签名
*/
public static byte[] sign(byte[] message, PrivateKey privateKey, String algorithm, String provider) throws Exception {
Signature signature;
if (null == provider || provider.length() == 0) {
signature = Signature.getInstance(algorithm);
} else {
signature = Signature.getInstance(algorithm, provider);
}
signature.initSign(privateKey);
signature.update(message);
return signature.sign();
}
//公钥加密
public static byte[] encrypt(byte[] content, PublicKey publicKey) throws Exception{
Cipher cipher=Cipher.getInstance("RSA");//java默认"RSA"="RSA/ECB/PKCS1Padding"
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(content);
}
//私钥解密
public static byte[] decrypt(byte[] content, PrivateKey privateKey) throws Exception{
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(content);
}
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("C:\\Windows\\System32\\mykeystore");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(in,"135246".toCharArray());
Enumeration aliasEnum = keyStore.aliases();
String keyAlias = "" ;
while (aliasEnum.hasMoreElements()) {
keyAlias = (String) aliasEnum.nextElement();
System.out.println("别名"+keyAlias);
}
Certificate ce = keyStore.getCertificate(keyAlias);
PublicKey publicKey = keyStore.getCertificate(keyAlias).getPublicKey();
//System.out.println("publicKey"+publicKey);
String publick = Base64.encodeBase64String(publicKey.getEncoded());
System.out.println("public"+publick);
//加载私钥,这里填私钥密码
PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) keyStore.getEntry(keyAlias,
new KeyStore.PasswordProtection("135246".toCharArray()))).getPrivateKey();
//加载私钥另一写法
//PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias, "123456".toCharArray());
//base64输出私钥
String strKey = Base64.encodeBase64String(privateKey.getEncoded());
//测试签名
String sign = Base64.encodeBase64String(sign("测试msg".getBytes(),privateKey,"SHA1withRSA",null));
byte[] jiami = encrypt("01510136|15000364728".getBytes(),publicKey);
System.out.println("加密后"+Base64.encodeBase64String(jiami));
//测试验签
boolean verfi = verify("01510136|15000364728".getBytes(),Base64.decodeBase64(sign), publicKey,"SHA1withRSA",null);
//String s = privateDecrypt("我是一个人",privateKey);
byte[] jiemi = decrypt(jiami,privateKey);
System.out.println("解密后"+new String(jiemi));
}
}
整体的运行效果如下图显示
很明显,通过将byte[]转化为base64编码后,然后将编码后的文件进行了解密,这里要注意的是,我这里解密的未进行编码的加密数据,所以实际大家使用的时候记得base64解码后再进行解密。最终也是成功的解出了最后的加密数据,当然,你要是想进行签名操作,也可以调用验签和签名的方法,我在main方法中也有进行调用。
其实也折腾了很久,比如会碰到RSAPublicKey和PublicKey的区别,其实只是不同包名下面的不同方法,分别调用即可。
麻烦大家使用注明出处有哟,大家一起进步成长!