从文件加载 RSA 公钥

我已经生成了一个私钥:

openssl genrsa [-out file] –des3

在这之后,我用下面的代码生成了一个公钥:

openssl rsa –pubout -in private.key [-out file]

我想用我的私钥签署一些消息,并用我的公钥验证一些其他消息,使用如下代码:

public String sign(String message) throws SignatureException{
try {
Signature sign = Signature.getInstance("SHA1withRSA");
sign.initSign(privateKey);
sign.update(message.getBytes("UTF-8"));
return new String(Base64.encodeBase64(sign.sign()),"UTF-8");
} catch (Exception ex) {
throw new SignatureException(ex);
}
}


public boolean verify(String message, String signature) throws SignatureException{
try {
Signature sign = Signature.getInstance("SHA1withRSA");
sign.initVerify(publicKey);
sign.update(message.getBytes("UTF-8"));
return sign.verify(Base64.decodeBase64(signature.getBytes("UTF-8")));
} catch (Exception ex) {
throw new SignatureException(ex);
}
}

我找到了一个解决方案,将我的私钥转换为 PKCS8格式并加载它。它的代码是这样的:

public PrivateKey getPrivateKey(String filename) 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();
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf =
KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}

最后我的问题是: 如何从文件加载 RSA 公钥?

我认为可能需要将公钥文件转换为 x509格式,并使用 X509EncodedKeySpec。但我该怎么做呢?

262991 次浏览

下面是 扎奇提供的来自 链接的相关信息。

生成一个2048位 RSA 私钥

$ openssl genrsa -out private_key.pem 2048

将私有密钥转换为 PKCS # 8格式(这样 Java 就可以读取它)

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

以 DER 格式输出公钥部分(这样 Java 就可以读取它)

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

私人钥匙

import java.nio.file.*;
import java.security.*;
import java.security.spec.*;


public class PrivateKeyReader {


public static PrivateKey get(String filename)
throws Exception {


byte[] keyBytes = Files.readAllBytes(Paths.get(filename));


PKCS8EncodedKeySpec spec =
new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
}

公开密钥

import java.nio.file.*;
import java.security.*;
import java.security.spec.*;


public class PublicKeyReader {


public static PublicKey get(String filename)
throws Exception {
    

byte[] keyBytes = Files.readAllBytes(Paths.get(filename));


X509EncodedKeySpec spec =
new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
}

这个程序使用公钥和私钥做几乎所有的事情。 可以获得 der 格式,但要保存原始数据(不需要编码 base64)。 我希望这对程序员有帮助。

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import sun.security.pkcs.PKCS8Key;
import sun.security.pkcs10.PKCS10;
import sun.security.x509.X500Name;


import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;






/**
* @author Desphilboy
* DorOd bar shomA barobach
*
*/
public class csrgenerator {


private static PublicKey publickey= null;
private static PrivateKey privateKey=null;
//private static PKCS8Key privateKey=null;
private static KeyPairGenerator kpg= null;
private static ByteArrayOutputStream bs =null;
private static csrgenerator thisinstance;
private KeyPair keypair;
private static PKCS10 pkcs10;
private String signaturealgorithm= "MD5WithRSA";


public String getSignaturealgorithm() {
return signaturealgorithm;
}






public void setSignaturealgorithm(String signaturealgorithm) {
this.signaturealgorithm = signaturealgorithm;
}






private csrgenerator() {
try {
kpg = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.out.print("No such algorithm RSA in constructor csrgenerator\n");
}
kpg.initialize(2048);
keypair = kpg.generateKeyPair();
publickey = keypair.getPublic();
privateKey = keypair.getPrivate();
}






/** Generates a new key pair
*
* @param int bits
*   this is the number of bits in modulus must be 512, 1024, 2048  or so on
*/
public KeyPair generateRSAkys(int bits)
{
kpg.initialize(bits);
keypair = kpg.generateKeyPair();
publickey = keypair.getPublic();
privateKey = keypair.getPrivate();
KeyPair dup= keypair;
return dup;
}


public static csrgenerator getInstance() {
if (thisinstance == null)
thisinstance = new csrgenerator();
return thisinstance;
}




/**
*  Returns a CSR as string
* @param cn  Common Name
* @param OU  Organizational Unit
* @param Org  Organization
* @param LocName Location name
* @param Statename  State/Territory/Province/Region
* @param Country    Country
* @return     returns  csr as string.
* @throws Exception
*/
public String getCSR(String commonname, String organizationunit, String organization,String localname, String statename, String country ) throws Exception {
byte[] csr = generatePKCS10(commonname, organizationunit, organization, localname, statename, country,signaturealgorithm);
return new String(csr);
}


/** This function generates a new Certificate
* Signing Request.
*
* @param CN
*            Common Name, is X.509 speak for the name that distinguishes
*            the Certificate best, and ties it to your Organization
* @param OU
*            Organizational unit
* @param O
*            Organization NAME
* @param L
*            Location
* @param S
*            State
* @param C
*            Country
* @return    byte stream of generated request
* @throws Exception
*/
private static byte[] generatePKCS10(String CN, String OU, String O,String L, String S, String C,String sigAlg) throws Exception {
// generate PKCS10 certificate request


pkcs10 = new PKCS10(publickey);
Signature   signature = Signature.getInstance(sigAlg);
signature.initSign(privateKey);
// common, orgUnit, org, locality, state, country
//X500Name(String commonName, String organizationUnit,String organizationName,Local,State, String country)
X500Name x500Name = new X500Name(CN, OU, O, L, S, C);
pkcs10.encodeAndSign(x500Name,signature);
bs = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(bs);
pkcs10.print(ps);
byte[] c = bs.toByteArray();
try {
if (ps != null)
ps.close();
if (bs != null)
bs.close();
} catch (Throwable th) {
}
return c;
}


public  PublicKey getPublicKey() {
return publickey;
}








/**
* @return
*/
public PrivateKey getPrivateKey() {
return privateKey;
}


/**
* saves private key to a file
* @param filename
*/
public  void SavePrivateKey(String filename)
{
PKCS8EncodedKeySpec pemcontents=null;
pemcontents= new PKCS8EncodedKeySpec( privateKey.getEncoded());
PKCS8Key pemprivatekey= new  PKCS8Key( );
try {
pemprivatekey.decode(pemcontents.getEncoded());
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
File file=new File(filename);
try {


file.createNewFile();
FileOutputStream fos=new FileOutputStream(file);
fos.write(pemprivatekey.getEncoded());
fos.flush();
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}






}






/**
* Saves Certificate Signing Request to a file;
* @param filename  is a String containing full path to the file which will be created containing the CSR.
*/
public void SaveCSR(String filename)
{
FileOutputStream fos=null;
PrintStream ps=null;
File file;
try {


file = new File(filename);
file.createNewFile();
fos = new FileOutputStream(file);
ps= new PrintStream(fos);
}catch (IOException e)
{
System.out.print("\n could not open the file "+ filename);
}


try {
try {
pkcs10.print(ps);
} catch (SignatureException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ps.flush();
ps.close();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.print("\n cannot write to the file "+ filename);
e.printStackTrace();


}


}




/**
* Saves both public key and private  key to file names specified
* @param fnpub  file name of public key
* @param fnpri  file name of private key
* @throws IOException
*/
public static void SaveKeyPair(String fnpub,String fnpri) throws IOException {


// Store Public Key.
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
publickey.getEncoded());
FileOutputStream fos = new FileOutputStream(fnpub);
fos.write(x509EncodedKeySpec.getEncoded());
fos.close();


// Store Private Key.
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
fos = new FileOutputStream(fnpri);
fos.write(pkcs8EncodedKeySpec.getEncoded());
fos.close();
}




/**
* Reads a Private Key from a pem base64 encoded file.
* @param filename name of the file to read.
* @param algorithm Algorithm is usually "RSA"
* @return returns the privatekey which is read from the file;
* @throws Exception
*/
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-----", "");
privKeyPEM = privKeyPEM.replace("-----END PRIVATE KEY-----", "");
//System.out.println("Private key\n"+privKeyPEM);


BASE64Decoder b64=new BASE64Decoder();
byte[] decoded = b64.decodeBuffer(privKeyPEM);


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






/**
* Saves the private key to a pem file.
* @param filename  name of the file to write the key into
* @param key the Private key to save.
* @return  String representation of the pkcs8 object.
* @throws Exception
*/
public  String  SavePemPrivateKey(String filename) throws Exception {
PrivateKey key=this.privateKey;
File f = new File(filename);
FileOutputStream fos = new FileOutputStream(f);
DataOutputStream dos = new DataOutputStream(fos);




byte[] keyBytes = key.getEncoded();
PKCS8Key pkcs8= new PKCS8Key();
pkcs8.decode(keyBytes);
byte[] b=pkcs8.encode();


BASE64Encoder b64=new BASE64Encoder();
String  encoded = b64.encodeBuffer(b);


encoded= "-----BEGIN PRIVATE KEY-----\r\n" + encoded + "-----END PRIVATE KEY-----";


dos.writeBytes(encoded);
dos.flush();
dos.close();


//System.out.println("Private key\n"+privKeyPEM);
return pkcs8.toString();


}




/**
* Saves a public key to a base64 encoded pem file
* @param filename  name of the file
* @param key public key to be saved
* @return string representation of the pkcs8 object.
* @throws Exception
*/
public  String  SavePemPublicKey(String filename) throws Exception {
PublicKey key=this.publickey;
File f = new File(filename);
FileOutputStream fos = new FileOutputStream(f);
DataOutputStream dos = new DataOutputStream(fos);




byte[] keyBytes = key.getEncoded();
BASE64Encoder b64=new BASE64Encoder();
String  encoded = b64.encodeBuffer(keyBytes);


encoded= "-----BEGIN PUBLIC KEY-----\r\n" + encoded + "-----END PUBLIC KEY-----";


dos.writeBytes(encoded);
dos.flush();
dos.close();


//System.out.println("Private key\n"+privKeyPEM);
return  encoded.toString();


}










/**
* reads a public key from a file
* @param filename name of the file to read
* @param algorithm is usually RSA
* @return the read public key
* @throws Exception
*/
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 = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");




BASE64Decoder b64=new BASE64Decoder();
byte[] decoded = b64.decodeBuffer(publicKeyPEM);


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








public static void main(String[] args) throws Exception {
csrgenerator gcsr = csrgenerator.getInstance();
gcsr.setSignaturealgorithm("SHA512WithRSA");
System.out.println("Public Key:\n"+gcsr.getPublicKey().toString());


System.out.println("Private Key:\nAlgorithm: "+gcsr.getPrivateKey().getAlgorithm().toString());
System.out.println("Format:"+gcsr.getPrivateKey().getFormat().toString());
System.out.println("To String :"+gcsr.getPrivateKey().toString());
System.out.println("GetEncoded :"+gcsr.getPrivateKey().getEncoded().toString());
BASE64Encoder encoder= new BASE64Encoder();
String s=encoder.encodeBuffer(gcsr.getPrivateKey().getEncoded());
System.out.println("Base64:"+s+"\n");


String csr = gcsr.getCSR( "desphilboy@yahoo.com","baxshi az xodam", "Xodam","PointCook","VIC" ,"AU");
System.out.println("CSR Request Generated!!");
System.out.println(csr);
gcsr.SaveCSR("c:\\testdir\\javacsr.csr");
String p=gcsr.SavePemPrivateKey("c:\\testdir\\java_private.pem");
System.out.print(p);
p=gcsr.SavePemPublicKey("c:\\testdir\\java_public.pem");
privateKey= gcsr.getPemPrivateKey("c:\\testdir\\java_private.pem", "RSA");
BASE64Encoder encoder1= new BASE64Encoder();
String s1=encoder1.encodeBuffer(gcsr.getPrivateKey().getEncoded());
System.out.println("Private Key in Base64:"+s1+"\n");
System.out.print(p);




}


}

一旦将密钥存储在 PEM 文件中,就可以使用 BouncyCastle 提供的 PemObject 和 PemReader 类轻松地将其读回,如下面的 本教程所示。

创建一个封装文件处理的 PemFile 类:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;


import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;


public class PemFile {


private PemObject pemObject;


public PemFile(String filename) throws FileNotFoundException, IOException {
PemReader pemReader = new PemReader(new InputStreamReader(
new FileInputStream(filename)));
try {
this.pemObject = pemReader.readPemObject();
} finally {
pemReader.close();
}
}


public PemObject getPemObject() {
return pemObject;
}
}

然后像往常一样实例化私钥和公钥:

import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;


import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;


public class Main {


protected final static Logger LOGGER = Logger.getLogger(Main.class);


public final static String RESOURCES_DIR = "src/main/resources/rsa-sample/";


public static void main(String[] args) throws FileNotFoundException,
IOException, NoSuchAlgorithmException, NoSuchProviderException {
Security.addProvider(new BouncyCastleProvider());
LOGGER.info("BouncyCastle provider added.");


KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
try {
PrivateKey priv = generatePrivateKey(factory, RESOURCES_DIR
+ "id_rsa");
LOGGER.info(String.format("Instantiated private key: %s", priv));


PublicKey pub = generatePublicKey(factory, RESOURCES_DIR
+ "id_rsa.pub");
LOGGER.info(String.format("Instantiated public key: %s", pub));
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
}


private static PrivateKey generatePrivateKey(KeyFactory factory,
String filename) throws InvalidKeySpecException,
FileNotFoundException, IOException {
PemFile pemFile = new PemFile(filename);
byte[] content = pemFile.getPemObject().getContent();
PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
return factory.generatePrivate(privKeySpec);
}


private static PublicKey generatePublicKey(KeyFactory factory,
String filename) throws InvalidKeySpecException,
FileNotFoundException, IOException {
PemFile pemFile = new PemFile(filename);
byte[] content = pemFile.getPemObject().getContent();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
return factory.generatePublic(pubKeySpec);
}
}

希望这个能帮上忙。

下面的代码对我来说工作得非常好。这段代码将通过 Java 代码读取 RSA 私钥和公钥。你可以参考 http://snipplr.com/view/18368/

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
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;
    

public class Demo {
public static final String PRIVATE_KEY="/home/user/private.der";
public static final String PUBLIC_KEY="/home/user/public.der";


public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
//get the private key
File file = new File(PRIVATE_KEY);
FileInputStream fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fis);


byte[] keyBytes = new byte[(int) file.length()];
dis.readFully(keyBytes);
dis.close();


PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPrivateKey privKey = (RSAPrivateKey) kf.generatePrivate(spec);
System.out.println("Exponent :" + privKey.getPrivateExponent());
System.out.println("Modulus" + privKey.getModulus());


//get the public key
File file1 = new File(PUBLIC_KEY);
FileInputStream fis1 = new FileInputStream(file1);
DataInputStream dis1 = new DataInputStream(fis1);
byte[] keyBytes1 = new byte[(int) file1.length()];
dis1.readFully(keyBytes1);
dis1.close();


X509EncodedKeySpec spec1 = new X509EncodedKeySpec(keyBytes1);
KeyFactory kf1 = KeyFactory.getInstance("RSA");
RSAPublicKey pubKey = (RSAPublicKey) kf1.generatePublic(spec1);


System.out.println("Exponent :" + pubKey.getPublicExponent());
System.out.println("Modulus" + pubKey.getModulus());
}
}
@Value("${spring.security.oauth2.resourceserver.jwt.key-value}")
RSAPublicKey key;

Key-value 可以是 uri (即“ classspath: keys/pub.pcks8.pem”)或 pem 内容。

你必须包括以下各项:

compile project(':spring-security-config')
compile project(':spring-security-oauth2-jose')
compile project(':spring-security-oauth2-resource-server')