java下使用openssl生成公私钥
原创公私钥准备
-
使用openssl生成私钥
openssl genrsa -out rsa_private.key 1024
这里使用1024使用通用场景,需要加强的话使用2048 -
使用openssl生成公钥
openssl rsa -in rsa_private.key -out rsa_public.key -pubout
java的私钥格式要求
查看刚刚生成的私钥的页眉页脚都是带有“rsa”加密方式
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDMnP55TJgP2g6mHby+dXLmRL1MNSh+GKi4G1+gp9tQVFXGX3PV
LCgUw8xUu4Fozo7KGuinmKAlQz1NvzcqDYCKAlwOPeNa
-----END RSA PRIVATE KEY-----
这个文件格式是如下
-----页眉-----
DER格式
-----页脚-----
DER说明
-inform DER|NET|PEM This specifies the input format. The DER option uses an ASN1 DER encoded form
compatible with the PKCS#1 RSAPrivateKey or SubjectPublicKeyInfo format.
The PEM form is the default format: it consists of the DER format base64
encoded with additional header and footer lines. On input PKCS#8 format
private keys are also accepted. The NET form is a format is described
in the NOTES section.
Java具有私钥的编码密钥规范:PKCS8EncodedKeySpec - 但是,它实现了“PKCS#8”而不是我们使用的“PKCS#1”。幸运的是,OpenSSL还包含一个这种格式的转换器:
openssl pkcs8 -topk8 -in rsa_private.key -out pkcs8_rsa_private.key -nocrypt
转换后格式如下
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMyc/nlMmA/aDqYd
-----END PRIVATE KEY-----
这里就大概得出结论是: java要读取openssl文件需要去掉页眉页脚来der且全换成经过base64反编译得真实编码值
代码片段
详细代码查看后面源码文件
读取公钥,采用的是509格式
public static PublicKey readPublicKeyFromFile (String path, String
algorithm)
throws IOException, NoSuchAlgorithmException,
InvalidKeySpecException
String publicKeyPEM = FileUtils.readFileToString(
new File(path), "UTF8");
publicKeyPEM = publicKeyPEM
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "");
byte[] publicKeyDER = new BASE64Decoder().decodeBuffer(publicKeyPEM);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyDER));
return publicKey;
}
- 这里FileUtils是来自依赖apache的commons-io的,读取文件到一个String。
- 去掉页眉页脚
- 转码得到真实编码Base64Decoder
- 通过api获取对应的密钥
读取私钥,采用的是PCK#8
public static PrivateKey readPrivateKeyFromFile (String path, String
algorithm)
throws IOException, NoSuchAlgorithmException,
InvalidKeySpecException
String privateKeyPEM = FileUtils.readFileToString(
new File(path), "UTF8");
privateKeyPEM = privateKeyPEM
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "");
byte[] privateKeyDER = new BASE64Decoder().decodeBuffer(privateKeyPEM);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyDER));
return privateKey;
}
源码文件
CyperUtil.java
package com.roger;
import org.apache.commons.io.FileUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class CyperUtil {
* 用私钥对信息生成数字签名
* @param data 数据
* @param privateKey 私钥
* @return
* @throws Exception
public static String sign(byte[] data, PrivateKey privateKey) throws
Exception {
// byte[] data = plainText.getBytes("UTF8");
Signature sig = Signature.getInstance("SHA1WithRSA");
sig.initSign(privateKey);
sig.update(data);
byte[] signatureBytes = sig.sign();
return new BASE64Encoder().encode(signatureBytes);
* 校验数字签名
* @param data 数据
* @param publicKey 公钥
* @param sign 数字签名
* @return
* @throws Exception
public static boolean verify(byte[] data, PublicKey publicKey, String sign)
throws Exception {
byte[] s = new BASE64Decoder().decodeBuffer(sign);
Signature sig = Signature.getInstance("SHA1WithRSA");
sig.initVerify(publicKey);
sig.update(data);
return sig.verify(s);
* 从文件加载公钥
* @param path 文件路劲
* @param algorithm 算法名称
* @return PublicKey 公钥
* @throws IOException, NoSuchAlgorithmException,
* InvalidKeySpecException
public static PublicKey readPublicKeyFromFile (String path, String
algorithm)
throws IOException, NoSuchAlgorithmException,
InvalidKeySpecException
String publicKeyPEM = FileUtils.readFileToString(
new File(path), "UTF8");
publicKeyPEM = publicKeyPEM
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "");
byte[] publicKeyDER = new BASE64Decoder().decodeBuffer(publicKeyPEM);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyDER));
return publicKey;
* 从文件加载私钥
* @param path 文件路劲
* @param algorithm 算法名称
* @return PrivateKey 私钥
* @throws IOException, NoSuchAlgorithmException,
* InvalidKeySpecException
public static PrivateKey readPrivateKeyFromFile (String path, String
algorithm)
throws IOException, NoSuchAlgorithmException,
InvalidKeySpecException
String privateKeyPEM = FileUtils.readFileToString(
new File(path), "UTF8");
privateKeyPEM = privateKeyPEM
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "");
byte[] privateKeyDER = new BASE64Decoder().decodeBuffer(privateKeyPEM);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyDER));
return privateKey;
}
TestRSA.java
package com.roger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
public class TestRSA {
public static void main(String[] args) throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair keyPair = kpg.genKeyPair();
String plainText = "test";
String sign = CyperUtil.sign(plainText.getBytes("UTF8"), keyPair
.getPrivate());
System.out.println("sign:" + sign);
System.out.println("sign length:" + sign.length());
Boolean pass = CyperUtil.verify(plainText.getBytes("UTF8"), keyPair
.getPublic(), sign);
System.out.println("verify:" + pass);
System.out.println("========");
PublicKey publickey = CyperUtil.readPublicKeyFromFile
("/D:/temp/rsa_public.key", "RSA");
PrivateKey privateKey = CyperUtil.readPrivateKeyFromFile
("/D:/temp/pkcs8_rsa_private.key", "RSA");
sign = CyperUtil.sign(plainText.getBytes("UTF8"), privateKey);
System.out.println("sign:" + sign);
System.out.println("sign length:" + sign.length());
pass = CyperUtil.verify(plainText.getBytes
("UTF8"), publickey, sign);
System.out.println("verify:" + pass);
}
POM文件依赖片段
<dependencies>