java默认的KeyPairGenerator生成的rsa 公私钥不能直接被openssl来使用
java生成的私钥是pkcs8 格式 公钥是x.509格式
openssl生成和使用的是pkcs1格式,pem公私钥文件,所以需要转换
本项目可以动态生成openssl兼容的,openssl可使用的公私钥
maven项目
//pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dddd</groupId>
<artifactId>jrsa</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
</dependencies>
</project>
//Test3.java
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
import java.io.StringWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
/**
* java生成openssl兼容的rsa 公私钥
*
* KeyPairGenerator生成的 私钥是pkcs8格式,需要先转为pkcs1格式,再由pkcs1转为pem格式(openssl生成的pem)
* KeyPairGenerator生成的 公钥是x509格式,需要替换_为/,替换-为+,格式化后,加-----BEGIN PUBLIC KEY-----头,-----END PUBLIC KEY-----尾,就与openssl生成的公钥一致了
*
* 根据私钥生成公钥,公私钥是一对一 openssl rsa -pubout -in rsa_private_key.pem -out rsa_public_key.pem
*/
public class Test3 {
public static void main(String[] args) throws Exception{
KeyPairGenerator kpg =KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair keyPair = kpg.generateKeyPair();
String publicKey = Base64.encodeBase64URLSafeString(keyPair.getPublic().getEncoded());
String privateKey = Base64.encodeBase64URLSafeString(keyPair.getPrivate().getEncoded());
System.out.println(privateKey);
String pem = privatePem(privateKey);
System.out.println("openssl 生成的私钥.pem:");
System.out.println(pem);
System.out.println(publicKey);
System.out.println("openssl 生成的公钥.pem");
System.out.println("-----BEGIN PUBLIC KEY-----");
formatKey(publicKey.replace("_","/").replace("-","+"));
System.out.println("-----END PUBLIC KEY-----");
}
public static String publicPem(String publicKey) throws Exception{
byte[] pubBytes = Base64.decodeBase64(publicKey);
SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfo.getInstance(pubBytes);
ASN1Primitive primitive = spkInfo.parsePublicKey();
byte[] publicKeyPKCS1 = primitive.getEncoded();
PemObject pemObject = new PemObject("RSA PUBLIC KEY", publicKeyPKCS1);
StringWriter stringWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(stringWriter);
pemWriter.writeObject(pemObject);
pemWriter.close();
String pemString = stringWriter.toString();
return pemString;
}
public static String privatePem(String privateKey) throws Exception{
byte[] privBytes = Base64.decodeBase64(privateKey);
PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privBytes);
ASN1Encodable encodable = pkInfo.parsePrivateKey();
ASN1Primitive primitive = encodable.toASN1Primitive();
byte[] privateKeyPKCS1 = primitive.getEncoded();
return pkcs1ToPem(privateKeyPKCS1,false);
}
public static String pkcs1ToPem(byte[] pcks1KeyBytes,boolean isPublic) throws Exception{
String type;
if(isPublic){
type = "RSA PUBLIC KEY";
}else{
type = "RSA PRIVATE KEY";
}
PemObject pemObject = new PemObject(type, pcks1KeyBytes);
StringWriter stringWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(stringWriter);
pemWriter.writeObject(pemObject);
pemWriter.close();
String pemString = stringWriter.toString();
return pemString;
}
/**
* 格式化java生成的key,一行长的,不适合pem中的-----BEGIN PUBLIC KEY-----,pem已经有换行了
* @param key
*/
public static void formatKey(String key){
if(key==null) return;
key = key.replace("\n","");
int count = (key.length()-1)/64+1;
for(int i=0;i<count;i++){
if(i+1==count){
//循环的最后一次
System.out.println(key.substring(i*64));
}else{
System.out.println(key.substring(i*64,i*64+64));
}
}
}
/**
* 从pem格式(-----BEGIN PUBLIC KEY-----)的key获取一行key
* @param pem
* @return
*/
public static String pemToKey(String pem){
if(pem==null) return "";
if(pem.indexOf("KEY-----")>0){
pem = pem.substring(pem.indexOf("KEY-----")+"KEY-----".length());
}
if(pem.indexOf("-----END")>0){
pem = pem.substring(0,pem.indexOf("-----END"));
}
return pem.replace("\n","");
}
}
运行后生成的公私钥
在线RSA公私密钥校验