java验证openssl生成的ssl证书和私钥是否匹配

本文介绍如何在Java中验证由OpenSSL生成的SSL证书与私钥是否匹配。通过读取证书的公钥和私钥,使用公钥加密测试字符串,然后用私钥解密,若能还原原始字符串,表明证书与私钥匹配。文章涉及PEM格式转换、Bouncyycastle库的使用,并提供完整代码和相关资源。
摘要由CSDN通过智能技术生成

      最近有一个需求上传ssl证书和私钥,但是上传之前需要验证ssl证书和私钥是否正确,其中的业务逻辑涉及到以下几点:

一、读取ssl证书,读取ssl证书公钥

      要实现该功能比较简单,java里面有现成的api支持。     

证书格式:

 

-----BEGIN CERTIFICATE-----
MIICYTCCAcoCCQCs45mePIbzRTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV
UzENMAsGA1UECAwETWFyczETMBEGA1UEBwwKaVRyYW5zd2FycDETMBEGA1UECgwK
aVRyYW5zd2FycDETMBEGA1UECwwKaVRyYW5zd2FycDEYMBYGA1UEAwwPd3d3LjU5
MXdpZmkuY29tMB4XDTE4MTAxNzAyMTA0OFoXDTI4MTAxNDAyMTA0OFowdTELMAkG
A1UEBhMCVVMxDTALBgNVBAgMBE1hcnMxEzARBgNVBAcMCmlUcmFuc3dhcnAxEzAR
BgNVBAoMCmlUcmFuc3dhcnAxEzARBgNVBAsMCmlUcmFuc3dhcnAxGDAWBgNVBAMM
D3d3dy41OTF3aWZpLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtxtP
cxgppTHrbzWloh26fXfIyLZI+YpNMCnJ+4wcv3jnZZ6OZsvnoo0z/yl/A9kDY9r5
Rft9fwE4WKMSPNKlGd4psPLw1XNHAXhi8RAy1cHgkBMuwor6ZJhFgnsqKk4Xp68D
jaCI2oxu2SYIBU67Fxy+h7G5BsWKwARtj5kP8NECAwEAATANBgkqhkiG9w0BAQUF
AAOBgQC2Pko8q1NicJ0oPuhFTPm7n03LtPhCaV/aDf3mqtGxraYifg8iFTxVyZ1c
ol0eEJFsibrQrPEwdSuSVqzwif5Tab9dV92PPFm+Sq0D1Uc0xI4ziXQ+a55K9wrV
TKXxS48TOpnTA8fVFNkUkFNB54Lhh9AwKsx123kJmyaWccbt9Q==
-----END CERTIFICATE-----

 

相关代码:

 

/**
     * 从证书文件获取公钥
     *
     * @param file
     * @return
     * @throws CertificateException
     * @throws FileNotFoundException
     */
    public static PublicKey getPublicKeyFromCert(File file) {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            FileInputStream in = new FileInputStream(file);
            Certificate crt = cf.generateCertificate(in);
            PublicKey publicKey = crt.getPublicKey();
            return publicKey;
        } catch (CertificateException e) {
            logger.error("read public key fail,the reason is :"+e.getMessage());
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            logger.error("read public key fail,the reason is the file not exist");
            e.printStackTrace();

        }
        return null;
    }

二、读取ssl证书私钥

      该功能实现有点困难,网上方法五花八门,需要对openssl生成私钥的格式和原理比较了解,openssl生成的RSA密钥默认是PEM格式,java包默认只支持DER格式,不能直接读取PEM格式文件,说了那么多,实际上PEM格式只是多了页面页脚,由于涉及到的知识点很多,网上资料很多,这里不在详细解释,我们只需要将页面页脚去掉然后进行base64位解码就可以正常读取了,推荐用第三方包Bouncycastle里面的pemReader工具类读取。

私钥格式:

-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQC3G09zGCmlMetvNaWiHbp9d8jItkj5ik0wKcn7jBy/eOdlno5m
y+eijTP/KX8D2QNj2vlF+31/AThYoxI80qUZ3imw8vDVc0cBeGLxEDLVweCQEy7C
ivpkmEWCeyoqThenrwONoIjajG7ZJggFTrsXHL6HsbkGxYrABG2PmQ/w0QIDAQAB
AoGBAIxvTcggSBCC8OciZh6oXlfMfxoxdFavU/QUmO1s0L+pow+1Q9JjoQxy7+ZL
lTcGQitbzsN11xKJhQW2TE6J4EVimJZQSAE4DDmYpMOrkjnBQhkUlaZkkukvDSRS
JqwBI/04G7se+RouHyXjRS9U76HnPM8+/IS2h+T6CbXLOpYBAkEA2j0JmyGVs+WV
I9sG5glamJqTBa4CfTORrdFW4EULoGkUc24ZFFqn9W4e5yfl/pCkPptCenvIrAWp
/ymnHeLn6QJBANbKGO9uBizAt4+o+kHYdANcbU/Cs3PLj8yOOtjkuMbH4tPNQmB6
/u3npiVk7/Txfkg0BjRzDDZib109eKbvGKkCQBgMneBghRS7+gFng40Z/sfOUOFR
WajeY/FZnk88jJlyuvQ1b8IUc2nSZslmViwFWHQlu9+vgF+kiCU8O9RJSvECQQCl
Vkx7giYerPqgC2MY7JXhQHSkwSuCJ2A6BgImk2npGlTw1UATJJq4Z2jtwBU2Z+7d
ha6BEU6FTqCLFZaaadKBAkEAxko4hrgBsX9BKpFJE3aUIUcMTJfJQdiAhq0k4DV8
5GVrcp8zl6mUTPZDaOmDhuAjGdAQJqj0Xo0PZ0fOZPtR+w==
-----END RSA PRIVATE KEY-----

相关代码:

 
  
/**
* 利用开源的工具类解析openssl私钥,openssl私钥文件格式为pem,需要去除页眉页脚后才能被java读取
*
* @param file
* @return
*/
public static PrivateKey getPrivateKey(File file) {
if (file == null) {
return null;
}
PrivateKey privKey = null;
PemReader pemReader = null;
try {
pemReader = new PemReader(new FileReader(file));
PemObject pemObject = pemReader.readPemObject();
byte[] pemContent = pemObject.getContent();
//支持从PKCS#1或PKCS#8 格式的私钥文件中提取私钥
if (pemObject.getType().endsWith("RSA PRIVATE KEY")) {
// 取得私钥 for PKCS#1
RSAPrivateKey asn1PrivKey = RSAPrivateKey.getInstance(pemContent);
RSAPrivateKeySpec rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent());
KeyFactory keyFactory= KeyFactory.getInstance("RSA");
privKey= keyFactory.generatePrivate(rsaPrivKeySpec);
} else if (pemObject.getType().endsWith("PRIVATE KEY")) {
//取得私钥 for PKCS#8
PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(pemContent);
KeyFactory kf = KeyFactory.getInstance("RSA");
privKey = kf.generatePrivate(privKeySpec);
}
} catch (FileNotFoundException e) {
logger.error("read private key fail,the reason is the file not exist");
e.printStackTrace();
} catch (IOException e) {
logger.error("read private key fail,the reason is :"+e.getMessage());
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
logger.error("read private key fail,the reason is :"+e.getMessage());
e.printStackTrace();
} catch (InvalidKeySpecException e) {
logger.error("read private key fail,the reason is :"+e.getMessage());
e.printStackTrace();
} finally {
try {
if (pemReader != null) {
pemReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return privKey;
}

三、ssl证书公钥和私钥是否匹配

      读取证书公钥和私钥后,将测试的字符串经过证书公钥加密后,再根据证书私钥解密后能后还原,说明上传的证书和私钥是正确的。

 /**
     * 加密
     *
     * @param key
     * @param plainBytes
     * @return
     */
    public static byte[] encrypt(PublicKey key, byte[] plainBytes) {

        ByteArrayOutputStream out = null;
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值