package RSA;
import org.apache.commons.codec.binary.Base64;//这两条指令的执行需引入外部包,外部包分别为commons-codec和commons-io
import org.apache.commons.io.IOUtils;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
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.HashMap;
import java.util.Map;
public class RSA {
public static final String CHARSET="UTF-8"; //设置以UTF-8编码
public static final String RSA_ALGORITHM="RSA"; //采用RSA加解密算法
public static Map<String,String> createKeys(int keySize)
{
KeyPairGenerator kpg;
try{
kpg=KeyPairGenerator.getInstance(RSA_ALGORITHM);
}catch(NoSuchAlgorithmException e)
{
throw new IllegalArgumentException("No such algorithm: "+RSA_ALGORITHM+"!");
}
//初始化KeyPairGenerator对象,密钥长度
kpg.initialize(keySize);
//生成密钥对
KeyPair keyPair=kpg.generateKeyPair();
//得到密钥对的公钥
Key publicKey=keyPair.getPublic();
String publicKeyStr=Base64.encodeBase64URLSafeString(publicKey.getEncoded());
//得到密钥对的私钥
Key privateKey=keyPair.getPrivate();
String privateKeyStr=Base64.encodeBase64String(privateKey.getEncoded());
//将公钥私钥加入到Map中,方便后面的取出
Map<String,String>keyMap=new HashMap<String,String>();
keyMap.put("publicKey", publicKeyStr);
keyMap.put("privateKey",privateKeyStr);
return keyMap;
}
/*
得到公钥
KeySpec的抽象实现类(EncodedKeySpec)构建了用于构建公钥规范和私钥规范的两个实现(X509EncodedKeySpec用于构建公钥规范,PKCS8EncodedKeySpec用于构建私钥规范)
*/
public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException,InvalidKeySpecException{
//通过X509编码的Key指令获得公钥对象
try{KeyFactory keyFactory=KeyFactory.getInstance(RSA_ALGORITHM);
X509EncodedKeySpec x509Key=new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
RSAPublicKey key=(RSAPublicKey)keyFactory.generatePublic(x509Key);
return key;
}catch(Exception e){
throw new RuntimeException("得到公钥时异常", e);
}
}
/*
得到私钥
*/
public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//通过PKCS8编码的Key指令获得私钥对象
KeyFactory keyFactory=KeyFactory.getInstance(RSA_ALGORITHM);
PKCS8EncodedKeySpec pkcs8Key=new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
RSAPrivateKey key=(RSAPrivateKey)keyFactory.generatePrivate(pkcs8Key);
return key;
}
/*
公钥加密
*/
public static String publicEncrypt(String data,RSAPublicKey publicKey){
try{
Cipher cipher=Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher,Cipher.ENCRYPT_MODE,data.getBytes(CHARSET),publicKey.getModulus().bitLength()));
}
catch(Exception e){
throw new RuntimeException("加密字符串"+data+"时异常",e);
}
}
/*
私钥解密
*/
public static String privateDecrypt(String data,RSAPrivateKey privateKey){
try{
Cipher cipher=Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(rsaSplitCodec(cipher,Cipher.DECRYPT_MODE,Base64.decodeBase64(data),privateKey.getModulus().bitLength()),CHARSET);
}catch(Exception e)
{
throw new RuntimeException("解密字符串"+data+"时异常",e);
}
}
/*
* 私钥加密
*/
public static String privateEncrypt(String data,RSAPrivateKey privateKey){
try{
Cipher cipher=Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher,Cipher.ENCRYPT_MODE,data.getBytes(CHARSET),privateKey.getModulus().bitLength()));
}catch(Exception e)
{
throw new RuntimeException("解密字符串"+data+"时异常",e);
}
}
/*
* 公钥解密
*/
public static String publicDecrypt(String data,RSAPublicKey publicKey){
try{
Cipher cipher=Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
}catch(Exception e)
{
throw new RuntimeException("解密字符串"+data+"时异常",e);
}
}
/*RSA加密算法对于加密的长度是有要求的。一般来说,加密时,明文长度大于加密钥长度-11时,明文就要进行分段;解密时,密文大于解密钥长度时,密文就要进行分段(以字节为单位)*/
private static byte[] rsaSplitCodec(Cipher cipher,int opmode,byte[] datas,int keySize){
int maxBlock=0;
if(opmode==Cipher.DECRYPT_MODE){
maxBlock=keySize/8;
}else{
maxBlock=keySize/8-11;
}
ByteArrayOutputStream out=new ByteArrayOutputStream();
int offSet=0;
byte[] buff;
int i=0;
try{
while(datas.length>offSet){
if(datas.length-offSet>maxBlock){
buff=cipher.doFinal(datas,offSet,maxBlock);
}else {
buff=cipher.doFinal(datas, offSet, datas.length-offSet);
}
out.write(buff,0,buff.length);
i++;
offSet=i*maxBlock;
}
}catch(Exception e)
{
throw new RuntimeException("加解密时异常");
}
byte[] resultDatas=out.toByteArray();
IOUtils.closeQuietly(out);
return resultDatas;
}
public static void main(String[] args) throws Exception{
Map<String,String>keyMap=RSA.createKeys(1024);
String publicKey=keyMap.get("publicKey");
String privateKey=keyMap.get("privateKey");
System.out.println("公钥: \n" + publicKey);
System.out.println("私钥:\n" + privateKey);
System.out.println("\n公钥加密——私钥解密");
String str = "对称密码,非对称密码,数字签名,Hash函数";
System.out.println("明文:\n" + str);
String encodedData = RSA.publicEncrypt(str, RSA.getPublicKey(publicKey));
System.out.println("密文:\n" + encodedData);
String decodedData = RSA.privateDecrypt(encodedData, RSA.getPrivateKey(privateKey));
System.out.println("解密后文字: \n" + decodedData);
System.out.println("\n\n~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("私钥加密——公钥解密");
String str2 = "对称密码,非对称密码,数字签名,Hash函数~~~~~~";
System.out.println("明文:\n" + str2);
String encodedData2 = RSA.privateEncrypt(str2, RSA.getPrivateKey(privateKey));
System.out.println("密文:\n" + encodedData2);
String decodedData2 = RSA.publicDecrypt(encodedData2, RSA.getPublicKey(publicKey));
System.out.println("解密后文字: \n" + decodedData2);
}
}
Java实现RSA公钥密码
最新推荐文章于 2024-07-08 02:48:54 发布