java - 如何读取. pem 文件获得私钥和公钥

我使用以下命令生成密钥。

以下命令生成密钥对。


 $openssl genrsa -out mykey.pem 2048

此命令用于生成私钥


$openssl pkcs8 -topk8 -inform PEM -outform PEM -in mykey.pem 
 -out private_key.pem -nocrypt

这个命令来获取public密钥。


$ openssl rsa -in mykey.pem -pubout -outform DER -out public_key.der

我写了两种方法分别读取私钥和public密钥。


 public PrivateKey getPemPrivateKey(String filename, String algorithm) throws Exception {
 File f = new File(filename);
 FileInputStream fis = new FileInputStream(f);
 DataInputStream dis = new DataInputStream(fis);
 byte[] keyBytes = new byte[(int) f.length()];
 dis.readFully(keyBytes);
 dis.close();

 String temp = new String(keyBytes);
 String privKeyPEM = temp.replace("-----BEGIN PRIVATE KEY-----n","");
 privKeyPEM = privKeyPEM.replace("-----END PRIVATE KEY-----","");
 //System.out.println("Private keyn"+privKeyPEM);

 Base64 b64 = new Base64();
 byte [] decoded = b64.decode(privKeyPEM);

 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);
 KeyFactory kf = KeyFactory.getInstance(algorithm);
 return kf.generatePrivate(spec);
 }

 public PublicKey getPemPublicKey(String filename, String algorithm) throws Exception {
 File f = new File(filename);
 FileInputStream fis = new FileInputStream(f);
 DataInputStream dis = new DataInputStream(fis);
 byte[] keyBytes = new byte[(int) f.length()];
 dis.readFully(keyBytes);
 dis.close();

 String temp = new String(keyBytes);
 String publicKeyPEM = temp.replace("-----BEGIN PUBLIC KEY-----n","");
 publicKeyPEM = privKeyPEM.replace("-----END PUBLIC KEY-----","");


 Base64 b64 = new Base64();
 byte [] decoded = b64.decode(publicKeyPEM);

 X509EncodedKeySpec spec =
 new X509EncodedKeySpec(decoded);
 KeyFactory kf = KeyFactory.getInstance(algorithm);
 return kf.generatePublic(spec);
 }


时间:

一个选项是使用bouncycastle的pemParser

解析包含X509证书,PKCS8编码密钥和PKCS7对象的OpenSSL PEM编码流的类。

对于PKCS7对象,reader 将返回一个CMS ContentInfo对象,public键将被返回为SubjectPublicKeyInfo对象,私钥将被返回,并形成PrivateKeyInfo对象,如果编码包含私钥和public密钥定义,则通常会返回一个私钥的PEMKeyPair ,CRL,证书,PKCS 10请求和属性证书将生成适当的BC持有人类别。

你可以看到使用它的例子,Parser测试代码 。

我的代码,就像你的代码一样,几乎没有区别。


public static X509Certificate loadPublicX509(String fileName) 
 throws GeneralSecurityException {
 InputStream is = null;
 X509Certificate crt = null;
 try {
 is = fileName.getClass().getResourceAsStream("/" + fileName);
 CertificateFactory cf = CertificateFactory.getInstance("X.509");
 crt = (X509Certificate)cf.generateCertificate(is);
 } finally {
 closeSilent(is);
 }
 return crt;
}

public static PrivateKey loadPrivateKey(String fileName) 
 throws IOException, GeneralSecurityException {
 PrivateKey key = null;
 InputStream is = null;
 try {
 is = fileName.getClass().getResourceAsStream("/" + fileName);
 BufferedReader br = new BufferedReader(new InputStreamReader(is));
 StringBuilder builder = new StringBuilder();
 boolean inKey = false;
 for (String line = br.readLine(); line != null; line = br.readLine()) {
 if (!inKey) {
 if (line.startsWith("-----BEGIN") && 
 line.endsWith(" PRIVATE KEY-----")) {
 inKey = true;
 }
 continue;
 }
 else {
 if (line.startsWith("-----END") && 
 line.endsWith(" PRIVATE KEY-----")) {
 inKey = false;
 break;
 }
 builder.append(line);
 }
 }
 //
 byte[] encoded = DatatypeConverter.parseBase64Binary(builder.toString());
 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
 KeyFactory kf = KeyFactory.getInstance("RSA");
 key = kf.generatePrivate(keySpec);
 } finally {
 closeSilent(is);
 }
 return key;
}

public static void closeSilent(final InputStream is) {
 if (is == null) return;
 try { is.close(); } catch (Exception ign) {}
}

尝试这个类。


package groovy;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;

public class RSA {

private static String getKey(String filename) throws IOException {
 // Read key from file
 String strKeyPEM ="";
 BufferedReader br = new BufferedReader(new FileReader(filename));
 String line;
 while ((line = br.readLine()) != null) {
 strKeyPEM += line +"n";
 }
 br.close();
 return strKeyPEM;
}
public static RSAPrivateKey getPrivateKey(String filename) throws IOException, GeneralSecurityException {
 String privateKeyPEM = getKey(filename);
 return getPrivateKeyFromString(privateKeyPEM);
}

public static RSAPrivateKey getPrivateKeyFromString(String key) throws IOException, GeneralSecurityException {
 String privateKeyPEM = key;
 privateKeyPEM = privateKeyPEM.replace("-----BEGIN PRIVATE KEY-----n","");
 privateKeyPEM = privateKeyPEM.replace("-----END PRIVATE KEY-----","");
 byte[] encoded = Base64.decodeBase64(privateKeyPEM);
 KeyFactory kf = KeyFactory.getInstance("RSA");
 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
 RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(keySpec);
 return privKey;
}


public static RSAPublicKey getPublicKey(String filename) throws IOException, GeneralSecurityException {
 String publicKeyPEM = getKey(filename);
 return getPublicKeyFromString(publicKeyPEM);
}

public static RSAPublicKey getPublicKeyFromString(String key) throws IOException, GeneralSecurityException {
 String publicKeyPEM = key;
 publicKeyPEM = publicKeyPEM.replace("-----BEGIN PUBLIC KEY-----n","");
 publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----","");
 byte[] encoded = Base64.decodeBase64(publicKeyPEM);
 KeyFactory kf = KeyFactory.getInstance("RSA");
 RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(new PKCS8EncodedKeySpec(encoded));
 return pubKey;
}

public static String sign(PrivateKey privateKey, String message) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, UnsupportedEncodingException {
 Signature sign = Signature.getInstance("SHA1withRSA");
 sign.initSign(privateKey);
 sign.update(message.getBytes("UTF-8"));
 return new String(Base64.encodeBase64(sign.sign()),"UTF-8");
}


public static boolean verify(PublicKey publicKey, String message, String signature) throws SignatureException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
 Signature sign = Signature.getInstance("SHA1withRSA");
 sign.initVerify(publicKey);
 sign.update(message.getBytes("UTF-8"));
 return sign.verify(Base64.decodeBase64(signature.getBytes("UTF-8")));
}

public static String encrypt(String rawText, PublicKey publicKey) throws IOException, GeneralSecurityException {
 Cipher cipher = Cipher.getInstance("RSA");
 cipher.init(Cipher.ENCRYPT_MODE, publicKey);
 return Base64.encodeBase64String(cipher.doFinal(rawText.getBytes("UTF-8")));
}

public static String decrypt(String cipherText, PrivateKey privateKey) throws IOException, GeneralSecurityException {
 Cipher cipher = Cipher.getInstance("RSA");
 cipher.init(Cipher.DECRYPT_MODE, privateKey);
 return new String(cipher.doFinal(Base64.decodeBase64(cipherText)),"UTF-8");
}

}

所需的jar库"common-codec-1.6 "

...