java程式碼生成相容openssl可用的rsa公私鑰,pkcs8轉換pkcs1,
阿新 • • 發佈:2018-11-11
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公私金鑰校驗