Skip to content

Instantly share code, notes, and snippets.

@borgle
Last active August 29, 2015 14:26
Show Gist options
  • Save borgle/c2477d76dfb13e31176d to your computer and use it in GitHub Desktop.
Save borgle/c2477d76dfb13e31176d to your computer and use it in GitHub Desktop.
RSA工具:可以生成密钥对,可以把c#格式、openssl格式的密钥对进行互转,可以进行字符串的加解密。

使用指南

  • 依赖说明 commons-cli 用于格式化命令行参数

  • 编译说明 采用JDK7编译,导出为runnable jar file

  • 使用手册

    • java -jar RSATools.jar 查看帮助
    • java -jar RSATools.jar -g -length 2048 生成一个长度为2048位的密钥对。length参数可以忽略,默认为1024
    • java -jar RSATools.jar -g -lang c# 生成一个长度为1024位的密钥对,格式为c#语言下的格式
    • java -jar RSATools.jar -g -public rsa_public_key.pem -private rsa_private_key_pkcs8.pem 生成一个长度为1024位的密钥对,公钥文件名为rsa_public_key.pem;私钥文件名为rsa_private_key_pkcs8.pem
    • java -jar RSATools.jar -c -lang c# -public public.xml -private private.xml 将一个c#格式的密钥对文件转换为openssl方式下的格式密钥对,c#格式的公钥文件为public.xml,私钥文件为private.xml
    • java -jar RSATools.jar -c -public rsa_public_key.pem -private rsa_private_key_pkcs8.pem 将openssl格式的密钥对转换为c#使用的密钥对
    • java -jar RSATools.jar -encode srctxt -public rsa_public_key.pem 使用rsa_public_key.pem加密字符串srctxt,得到一个加密后的Base64字符串
    • java -jar RSATools.jar -decode encodetxt -public rsa_private_key_pkcs8.pem 使用rsa_private_key_pkcs8.pem解密字符串encodetxt,得到原文
package com.gkeeps.tools;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
public class Application {
protected static CommandLine buildCommandline(String[] args) {
final Options options = new Options();
// ////////////////////////////////////////////////////
Option opt = new Option("h", "help", false, "Print help");
opt.setRequired(false);
options.addOption(opt);
opt = new Option("lang", "language", true, "the keyfile generated language. esage: c#, other");
opt.setRequired(false);
options.addOption(opt);
opt = new Option("private", "privatekey", true, "private keyfile.");
opt.setRequired(false);
options.addOption(opt);
opt = new Option("public", "publickey", true, "public keyfile.");
opt.setRequired(false);
options.addOption(opt);
opt = new Option("g", "generate", false, "rsa keyfile generater.");
opt.setRequired(false);
options.addOption(opt);
opt = new Option("c", "convert", false, "covert keyfile to other language.");
opt.setRequired(false);
options.addOption(opt);
opt = new Option("length", "keylength", true, "set seckey length.");
opt.setRequired(false);
options.addOption(opt);
opt = new Option("encode", "encode", true, "encode something use public keyfile.");
opt.setRequired(false);
options.addOption(opt);
opt = new Option("decode", "decode", true, "decode something use private keyfile.");
opt.setRequired(false);
options.addOption(opt);
// ////////////////////////////////////////////////////
PosixParser parser = new PosixParser();
HelpFormatter hf = new HelpFormatter();
hf.setWidth(110);
CommandLine commandLine = null;
try {
commandLine = parser.parse(options, args);
if (commandLine.hasOption('h') || commandLine.getOptions().length == 0) {
hf.printHelp("RSAUtils", options, true);
return null;
}
} catch (ParseException e) {
hf.printHelp("RSAUtils", options, true);
return null;
}
return commandLine;
}
/**
* 获取密钥文件的内容
* @param keyfile 密钥文件路径
* @return String
*/
protected static String getKeyString(String keyfile){
String base64KeyString = "";
try {
InputStream fis = new FileInputStream(keyfile);
InputStreamReader isr = new InputStreamReader(fis, Charset.forName("UTF-8"));
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
if (line.startsWith("--"))
continue;
base64KeyString += line;
}
base64KeyString = base64KeyString.replace("\r", "").replace("\n", "");
} catch (Exception e) {
e.printStackTrace();
}
return base64KeyString;
}
public static void main(String[] args){
CommandLine cmdline = buildCommandline(args);
if (cmdline == null) {
return;
}
String language = cmdline.getOptionValue("lang", "other").toLowerCase();
String privateKeyfile = cmdline.getOptionValue("private", "rsa_private_key_pkcs8.pem");
String publicKeyfile = cmdline.getOptionValue("public", "rsa_public_key.pem");
String encodeString = cmdline.getOptionValue("encode");
String decodeString = cmdline.getOptionValue("decode");
Integer length = Integer.parseInt(cmdline.getOptionValue("length", "1024"));
Boolean isgenerater = cmdline.hasOption("g");
Boolean isconvert = cmdline.hasOption("c");
if (!language.equals("c#") && !language.equals("other")) {
System.out.println("the lanuage is wrong. esage: c#, other");
return;
}
if(isgenerater){
RSAUtils.GeneralKeyPair(length, language, privateKeyfile, publicKeyfile);
return;
}
if(isconvert){
String privateKeyString = getKeyString(privateKeyfile);
String publicKeyString = getKeyString(publicKeyfile);
if(language.equals("c#")){
//转换为openssl格式的密钥
RSAPrivateKey privateKey = (RSAPrivateKey)RSAUtils.decodePrivateKeyFromXml(privateKeyString);
RSAPublicKey publicKey = (RSAPublicKey)RSAUtils.decodePublicKeyFromXml(publicKeyString);
RSAUtils.generatePrivateKeyFile(privateKey, "new_" + privateKeyfile);
RSAUtils.generatePublicKeyFile(publicKey, "new_" + publicKeyfile);
}else{
//转换为c#格式的密钥
RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey)RSAUtils.decodePrivateKeyPKCS8(privateKeyString);
RSAPublicKey publicKey = (RSAPublicKey)RSAUtils.decodePublicKey(publicKeyString);
RSAUtils.generatePrivateKeyXmlFile(privateKey, "new_" + privateKeyfile);
RSAUtils.generatePublicKeyXmlFile(publicKey, "new_" + publicKeyfile);
}
return;
}
//加密
if(encodeString !=null && encodeString.length()>0){
String publicKeyString = getKeyString(publicKeyfile);
if(language.equals("c#")){
RSAPublicKey publicKey = (RSAPublicKey)RSAUtils.decodePublicKeyFromXml(publicKeyString);
System.out.println("加密结果:\n" + RSAUtils.encrypt(publicKey, encodeString));
}else{
RSAPublicKey publicKey = (RSAPublicKey)RSAUtils.decodePublicKey(publicKeyString);
System.out.println("加密结果:\n" + RSAUtils.encrypt(publicKey, encodeString));
}
return;
}
//解密
if(decodeString !=null && decodeString.length()>0){
String privateKeyString = getKeyString(privateKeyfile);
if(language.equals("c#")){
RSAPrivateKey privateKey = (RSAPrivateKey)RSAUtils.decodePrivateKeyFromXml(privateKeyString);
System.out.println("解密结果:\n" + RSAUtils.decrypt(privateKey, decodeString));
}else{
RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey)RSAUtils.decodePrivateKeyPKCS8(privateKeyString);
System.out.println("解密结果:\n" + RSAUtils.decrypt(privateKey, decodeString));
}
return;
}
}
}
package com.gkeeps.tools;
import java.io.FileWriter;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
public class RSAUtils {
private static BASE64Encoder encoder = new BASE64Encoder();
private static BASE64Decoder decoder = new BASE64Decoder();
public static void GeneralKeyPair(Integer length, String language, String privateKeyfile, String publicKeyfile) {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化密钥对生成器,密钥大小为length位,单次加密字符串长度为length/8-11
keyPairGen.initialize(length);
KeyPair keyPair = keyPairGen.generateKeyPair();
if (language.equals("c#")) {
RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
generatePrivateKeyXmlFile(privateKey, privateKeyfile);
generatePublicKeyXmlFile(publicKey, publicKeyfile);
} else {
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
generatePrivateKeyFile(privateKey, privateKeyfile);
generatePublicKeyFile(publicKey, publicKeyfile);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void generatePrivateKeyFile(RSAPrivateKey privateKey, String privateKeyfile) {
try {
FileWriter writer = new FileWriter(privateKeyfile);
writer.write("-----BEGIN RSA PRIVATE KEY-----\r\n");
writer.write(encoder.encode(privateKey.getEncoded()));
writer.write("\r\n-----END RSA PRIVATE KEY-----");
writer.flush();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void generatePublicKeyFile(RSAPublicKey publicKey, String publicKeyfile) {
try {
FileWriter writer = new FileWriter(publicKeyfile);
writer.write("-----BEGIN PUBLIC KEY-----\r\n");
writer.write(encoder.encode(publicKey.getEncoded()));
writer.write("\r\n-----END PUBLIC KEY-----");
writer.flush();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void generatePrivateKeyXmlFile(RSAPrivateCrtKey privateKey, String privateKeyfile) {
try {
FileWriter writer = new FileWriter(privateKeyfile);
writer.write("<?xml version=\"1.0\" encoding=\"gbk\" ?>\n");
writer.write(encodePrivateKeyToXml(privateKey));
writer.flush();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void generatePublicKeyXmlFile(RSAPublicKey publicKey, String publicKeyfile) {
try {
FileWriter writer = new FileWriter(publicKeyfile);
writer.write("<?xml version=\"1.0\" encoding=\"gbk\" ?>\n");
writer.write(encodePublicKeyToXml(publicKey));
writer.flush();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 采用公钥加密
* @param publicKey 公钥对象
* @param srcString 待加密字符串
* @return 加密后的Base64字符串
*/
public static String encrypt(RSAPublicKey publicKey, String srcString) {
if (publicKey != null) {
try {
byte[] srcBytes = srcString.getBytes();
// Cipher负责完成加密或解密工作,RSA/ECB/PKCS1Padding or PKCS8Padding
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] resultBytes = cipher.doFinal(srcBytes);
return encoder.encode(resultBytes).replaceAll("\r|\n", "");
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 采用私钥解密
* @param privateKey 私钥对象
* @param encString 待解密的Base64字符串
* @return 原始字符串
*/
public static String decrypt(RSAPrivateKey privateKey, String encString) {
if (privateKey != null) {
try {
byte[] encBytes = decoder.decodeBuffer(encString);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decBytes = cipher.doFinal(encBytes);
return new String(decBytes);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 从字符串中加载公钥
*/
public static PublicKey decodePublicKey(String publicKeyStr) {
try {
byte[] buffer = decoder.decodeBuffer(publicKeyStr);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 从字符串中加载私钥PKCS8
*/
public static PrivateKey decodePrivateKeyPKCS8(String privateKeyStr) {
try {
byte[] buffer = decoder.decodeBuffer(privateKeyStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 从字符串中加载私钥PKCS1
*/
public static PrivateKey decodePrivateKeyPKCS1(String privateKeyStr) {
// 依赖 org.bouncycastle
/*
* RSAPrivateKeyStructure asn1PrivKey = new
* RSAPrivateKeyStructure((ASN1Sequence)
* ASN1Sequence.fromByteArray(privateKeyStr)); RSAPrivateKeySpec
* rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(),
* asn1PrivKey.getPrivateExponent()); KeyFactory keyFactory=
* KeyFactory.getInstance("RSA"); return
* keyFactory.generatePrivate(rsaPrivKeySpec);
*/
throw new NotImplementedException();
}
/**
* java公钥转换成C#公钥
*/
public static String encodePublicKeyToXml(RSAPublicKey publicKey) {
StringBuilder sb = new StringBuilder();
sb.append("<RSAKeyValue>\n");
sb.append("<Modulus>").append(encoder.encode(publicKey.getModulus().toByteArray()).replace("\r", "").replace("\n", ""))
.append("</Modulus>\n");
sb.append("<Exponent>").append(encoder.encode(publicKey.getPublicExponent().toByteArray()).replace("\r", "").replace("\n", ""))
.append("</Exponent>\n");
sb.append("</RSAKeyValue>");
return sb.toString();
}
/**
* C#公钥转换成java公钥
*/
public static PublicKey decodePublicKeyFromXml(String publicKeyXml) {
publicKeyXml = publicKeyXml.replaceAll("\r", "").replaceAll("\n", "");
KeyFactory keyf;
try {
BigInteger modulus = new BigInteger(1, decoder.decodeBuffer(
publicKeyXml.substring(publicKeyXml.indexOf("<Modulus>") + 9, publicKeyXml.indexOf("</Modulus>"))));
BigInteger publicExponent = new BigInteger(1, decoder.decodeBuffer(publicKeyXml
.substring(publicKeyXml.indexOf("<Exponent>") + 10, publicKeyXml.indexOf("</Exponent>"))));
RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, publicExponent);
keyf = KeyFactory.getInstance("RSA");
return keyf.generatePublic(rsaPubKey);
} catch (Exception e) {
return null;
}
}
/**
* java私钥转换成C#私钥
*/
public static String encodePrivateKeyToXml(RSAPrivateCrtKey privateKey) {
StringBuilder sb = new StringBuilder();
sb.append("<RSAKeyValue>\n");
sb.append("<Modulus>").append(encoder.encode(privateKey.getModulus().toByteArray()).replace("\r", "").replace("\n", ""))
.append("</Modulus>\n");
sb.append("<Exponent>").append(encoder.encode(privateKey.getPublicExponent().toByteArray()).replace("\r", "").replace("\n", ""))
.append("</Exponent>\n");
sb.append("<P>").append(encoder.encode(privateKey.getPrimeP().toByteArray()).replace("\r", "").replace("\n", ""))
.append("</P>\n");
sb.append("<Q>").append(encoder.encode(privateKey.getPrimeQ().toByteArray()).replace("\r", "").replace("\n", ""))
.append("</Q>\n");
sb.append("<DP>").append(encoder.encode(privateKey.getPrimeExponentP().toByteArray()).replace("\r", "").replace("\n", ""))
.append("</DP>\n");
sb.append("<DQ>").append(encoder.encode(privateKey.getPrimeExponentQ().toByteArray()).replace("\r", "").replace("\n", ""))
.append("</DQ>\n");
sb.append("<InverseQ>").append(encoder.encode(privateKey.getCrtCoefficient().toByteArray()).replace("\r", "").replace("\n", ""))
.append("</InverseQ>\n");
sb.append("<D>").append(encoder.encode(privateKey.getPrivateExponent().toByteArray()).replace("\r", "").replace("\n", ""))
.append("</D>\n");
sb.append("</RSAKeyValue>");
return sb.toString();
}
/**
* C#私钥转换成java私钥
*/
public static PrivateKey decodePrivateKeyFromXml(String privateKeyXml) {
privateKeyXml = privateKeyXml.replaceAll("\r", "").replaceAll("\n", "");
KeyFactory keyf;
try {
BigInteger modulus = new BigInteger(1, decoder.decodeBuffer(privateKeyXml
.substring(privateKeyXml.indexOf("<Modulus>") + 9, privateKeyXml.indexOf("</Modulus>"))));
BigInteger publicExponent = new BigInteger(1, decoder.decodeBuffer(privateKeyXml
.substring(privateKeyXml.indexOf("<Exponent>") + 10, privateKeyXml.indexOf("</Exponent>"))));
BigInteger privateExponent = new BigInteger(1, decoder.decodeBuffer(
privateKeyXml.substring(privateKeyXml.indexOf("<D>") + 3, privateKeyXml.indexOf("</D>"))));
BigInteger primeP = new BigInteger(1, decoder.decodeBuffer(
privateKeyXml.substring(privateKeyXml.indexOf("<P>") + 3, privateKeyXml.indexOf("</P>"))));
BigInteger primeQ = new BigInteger(1, decoder.decodeBuffer(
privateKeyXml.substring(privateKeyXml.indexOf("<Q>") + 3, privateKeyXml.indexOf("</Q>"))));
BigInteger primeExponentP = new BigInteger(1, decoder.decodeBuffer(
privateKeyXml.substring(privateKeyXml.indexOf("<DP>") + 4, privateKeyXml.indexOf("</DP>"))));
BigInteger primeExponentQ = new BigInteger(1, decoder.decodeBuffer(
privateKeyXml.substring(privateKeyXml.indexOf("<DQ>") + 4, privateKeyXml.indexOf("</DQ>"))));
BigInteger crtCoefficient = new BigInteger(1, decoder.decodeBuffer(privateKeyXml
.substring(privateKeyXml.indexOf("<InverseQ>") + 10, privateKeyXml.indexOf("</InverseQ>"))));
RSAPrivateCrtKeySpec rsaPriKey = new RSAPrivateCrtKeySpec(modulus, publicExponent, privateExponent, primeP,
primeQ, primeExponentP, primeExponentQ, crtCoefficient);
keyf = KeyFactory.getInstance("RSA");
return keyf.generatePrivate(rsaPriKey);
} catch (Exception e) {
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment