import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import ms.core.tool.DateTimeTool;
import ms.core.tool.JsonTool;
import ms.core.tool.SysTool;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.crypto.Cipher;
import javax.security.cert.X509Certificate;
import java.io.*;
import java.nio.charset.Charset;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
* openssl 证书公钥私钥读取加密解密工具类,主要用于验证上传的 openssl生成的证书和私钥文件是否正确的问题
* 主要逻辑:
* 1、根据私钥文件读取私钥
* 2、根据公钥文件读取公钥
* 3、根据证书文件读取公钥
* 4、根据证书公钥加密字符串
* 5、根据证书私钥解密字符串
* 6、如果字符串经过证书公钥加密后,再根据证书私钥解密后能后还原,说明上传的证书和私钥是正确的
public class OpenSslUtils {
private static final String DEFAULT_ENCODING = "UTF-8";
private static final Charset DEFAULT_CHARSET = Charset.forName(DEFAULT_ENCODING);
/** 默认是RSA/NONE/PKCS1Padding */
private static final String CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding";
/** RSA密钥长度必须是64的倍数,在512~65536之间。默认是1024 */
private static final int KEY_SIZE = 1024;
/** RSA最大加密明文大小:明文长度(bytes) <= 密钥长度(bytes)-11 */
private static final int MAX_ENCRYPT_BLOCK = KEY_SIZE / 8 - 11;
/** RSA最大解密密文大小 */
private static final int MAX_DECRYPT_BLOCK = KEY_SIZE / 8;
private static Logger logger = LogManager.getLogger(OpenSslUtils.class);
* 利用开源的工具类解析openssl私钥,openssl私钥文件格式为pem,
* 需要去除页眉页脚后才能被程序识别
* @param txtKey
* @return
public static PrivateKey getPrivateKey(String txtKey) {
PrivateKey privKey = null;
PemReader pemReader = null;
try {
pemReader = new PemReader(new StringReader(txtKey));
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 (Exception e) {
logger.error(e, e);
try {
if (pemReader != null) pemReader.close();
} catch (IOException e) {
return privKey;
* 从key文件读取私钥内容,并获取key对象
* @param file
* @return
public static PrivateKey getPrivateKey(File file) {
if (file == null || !file.exists()) return null;
return getPrivateKey(SysTool.readTxtFile2Str(file, "UTF8"));
* 从证书文本获取公钥
* @param content
* @return
public static PublicKey getPublicKey(String txtKey) {
InputStream in = null;
PublicKey publicKey = null;
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
in = new ByteArrayInputStream(txtKey.getBytes());
Certificate crt = cf.generateCertificate(in);
publicKey = crt.getPublicKey();
} catch (Exception e) {
logger.error(e, e);
try {
if (in!=null) in.close();
} catch(Exception e) {
return publicKey;
* 从证书公钥内容串,提取证书信息
* @param txtKey
* @return
public static Map
getPublicKeyInfo(String txtKey){
Map ret = new HashMap();
InputStream in = null;
try {
in = new ByteArrayInputStream(txtKey.getBytes());
X509Certificate crt = X509Certificate.getInstance(in);
ret.put("expiry", crt.getNotAfter());
ret.put("start", crt.getNotBefore());
ret.put("issue", crt.getIssuerDN().getName());
ret.put("ver", crt.getVersion());
} catch (Exception e) {
logger.error(e, e);
try {
if (in!=null) in.close();
} catch(Exception e) {
return ret;
* 从证书文件获取公钥
* @param file
* @return
public static PublicKey getPublicKey(File file) {
if (file==null || !file.exists()) return null;
return getPublicKey(SysTool.readTxtFile2Str(file, "UTF8"));
* 从openssl公钥文件中读取公钥
* @param file
* @return
public static PublicKey getPublicKeyFromFile(File file) {
if (file == null) return null;
PublicKey pubKey = null;
PemReader pemReader = null;
try {
pemReader = new PemReader(new FileReader(file));
PemObject pemObject = pemReader.readPemObject();
byte[] pemContent = pemObject.getContent();
//公钥需要使用x509格式编码
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(pemContent);
KeyFactory kf = KeyFactory.getInstance("RSA");
pubKey = kf.generatePublic(pubKeySpec);
} catch (Exception e) {
logger.error(e, e);
try {
if (pemReader != null) pemReader.close();
} catch (Exception ex) {
return pubKey;
* 公钥加密
* @param key
* @param plainBytes
* @return
private static byte[] encrypt(PublicKey key, byte[] plainBytes) {
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
if (plainBytes.length <= MAX_ENCRYPT_BLOCK) {
return cipher.doFinal(plainBytes);
return cipher.doFinal(plainBytes);
} catch (Exception e) {
logger.error(e,e);
return null;
* 根据公钥加密字符串
* @param key
* @param plainText 需要加密的字符串
* @return
public static String encrypt(PublicKey key, String plainText) {
byte[] encodeBytes = encrypt(key, plainText.getBytes(DEFAULT_CHARSET));
return Base64.encodeBase64String(encodeBytes);
* 私钥解密
* @param key
* @param encodedText
* @return
private static String decrypt(PrivateKey key, byte[] encodedText) {
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
int inputLen = encodedText.length;
if (inputLen <= MAX_DECRYPT_BLOCK) {
return new String(cipher.doFinal(encodedText), DEFAULT_CHARSET);
byte[] cache = cipher.doFinal(encodedText);
return new String(cache);
} catch (Exception e) {
logger.error(e,e);
return null;
* 根据私钥解密加密过的字符串
* @param key
* @param encodedText 加密过的字符串
* @return 解密后的字符串
public static String decrypt(PrivateKey key, String encodedText) {
byte[] bytes = Base64.decodeBase64(encodedText);
return decrypt(key, bytes);
* 验证证书
* @param cert
* @return
public static String validateCert(File cert){
if (cert == null) return "证书CRT文件不能为空";
PublicKey publicKey = getPublicKey(cert);
if (publicKey == null) return "无法读取证书公钥,证书CRT文件格式错误";
return null;
* 验证私钥
* @param privateKey
* @return
public static String validatePrivateKey(File privateKey){
if (privateKey == null) return "证书私钥不能为空";
PrivateKey privKey = getPrivateKey(privateKey);
if (privKey == null) return "无法读取证书私钥,证书私钥文件格式错误";
return null;
* 验证证书私钥是否匹配,如果不匹配返回错误消息
* @param cert
* @param privateKey
* @return 错误消息
public static String validate(File cert, File privateKey) {
String res = validateCert(cert); //验证证书
if((res!=null)&&(res.length()>0)){
return res; //返回错误消息
res = validatePrivateKey(privateKey); //验证私钥
if((res!=null)&&(res.length()>0)){
return res; //返回错误消息
PublicKey publicKey = getPublicKey(cert);
PrivateKey privKey = getPrivateKey(privateKey);
String str = "test"; //测试字符串
String encryptStr = OpenSslUtils.encrypt(publicKey, str); //根据证书公钥对字符串进行加密
String decryptStr = OpenSslUtils.decrypt(privKey, encryptStr); //根据证书私钥对加密字符串进行解密
if(!str.equals(decryptStr)){ //字符串根据证书公钥加密,私钥解密后不能还原说明证书与私钥不匹配
return "证书与私钥不匹配";
return "success";
* 验证公私钥是否匹配
* @param txtPrivateKey 私钥串
* @param txtPublicKey 公钥串
* @return 0-匹配;1-私钥错误;2-公钥错误;3-不匹配
public static int keyMatched(String txtPrivateKey, String txtPublicKey) {
PrivateKey prvKey = OpenSslUtils.getPrivateKey(txtPrivateKey);
if (prvKey==null) return 1;
PublicKey pubKey = OpenSslUtils.getPublicKey(txtPublicKey);
if (pubKey==null) return 2;
String str = "public key & private key";
String encryptStr = encrypt(pubKey, str);
String decryptStr = decrypt(prvKey, encryptStr);
return str.equals(decryptStr) ? 0:3;
public static void main(String[] args) {
File privateKeyFile = new File("d:/4key.txt");
PrivateKey privKey = OpenSslUtils.getPrivateKey(privateKeyFile);
System.out.println("私钥:" + privKey);
File certFile = new File("d:/4.txt");
PublicKey publicKey = OpenSslUtils.getPublicKey(certFile);
System.out.println("公钥:" + publicKey);
//公私钥匹配验证
String validateResult = validate(certFile,privateKeyFile);
System.out.println("匹配结果:" + validateResult);
String str = "this is a test";
String encryptStr = OpenSslUtils.encrypt(publicKey, str);
System.out.println("密文:" + encryptStr);
String decryptStr = OpenSslUtils.decrypt(privKey, encryptStr);
System.out.println("明文:" + decryptStr);
//获取证书信息,如有效期等
Map map = getPublicKeyInfo(SysTool.readTxtFile2Str(certFile, "UTF8"));
if (map.get("expiry")!=null) {
Date dt = (Date) map.get("expiry");
System.out.println("证书有效期:"+DateTimeTool.dateToDateString(dt));
System.out.println(JsonTool.beanToJson(map));
开发CDN平台过程,涉及到需要对证书做有效性验证,开发了以下工具类接口 package hs.cdn.tool;import org.apache.commons.codec.binary.Base64;import org.bouncycastle.asn1.pkcs.RSAPrivateKey;import org.bouncycastle.util.io.pem.Pem...
介绍一下编码格式
本节主要介绍密钥和
证书
中常见的编码规则 DER和由 DER 衍生出的密钥文件格式 PEM。
DER (Distinguished Encoding Rules)DER (Distinguished Encoding Rules)
DER 是用二进制DER编码的
证书
,DER格式常见于
java
语言
PEM格式是在DER格式的基础上采用base64编码得到,PEM is Base64-encoded DER。PEM格式是采用openssl生成密钥和
证书
的格式。
下面是经典
down voteYou will need BouncyCastle:import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.as...
1. 下载所要压缩 jar 包的源代码
2. 找到所有需要导入的类, 比如:
import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemReader;
3. 下载extjar-1.0.0.jar
链接:
https
://pan.baidu.com...
2901
证书
吊销 已激活
证书
吊销,放入吊销列表(CRL)
7101
证书
查询 如果指定了条件对应的值,该查询条件有效
7102 唯一
证书
查询 根据DN或序列号查询
证书
信息
7103
证书
公钥查询 根据序列号查询
证书
公钥信息
参考链接:http://bouncy-castle.1462172.n4.nabble.com/Problem-using-PEMReader-to-read-openssl-generated-private-key-td4382977.html
最近用到PEMReader,在官网下载最新的jar包之后,他的用法和以前不一样了,记录如下:
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.http.HttpUtil;
import com.faraway.pdemo.exception.DefinedException;
import lombok.extern.slf4j.Slf4j;
import org.bounc.
在公钥密码学(也称为非对称密码术)中,
加密
机制依赖于两个相关的密钥,一个公钥和一个私钥。公钥用于
加密
消息,而只有私钥的所有者才能解密消息。
在本教程中,我们将了解如何从 PEM 文件中读取公钥和私钥。
首先,我们将研究有关公钥密码学的一些重要概念。然后,我们将学习如何使用纯
Java
读取 PEM 文件。
最后,我们将探索BouncyCastle库作为替代方法。
2. 概念
在开始之前,让我们先了解一些关键概念。
X.509 是定义公钥
证书
格式的标准。因此,这种...
### 回答1:
小黄鸟HttpCanary是一款针对Android应用的抓包
工具
,它可以在无需root权限的情况下监测用户设备上的HTTP通信,捕获网络请求和响应数据,帮助用户分析网络协议和引发问题。
小黄鸟HttpCanary功能齐全,支持多种HTTP协议、WebSocket和TCP/UDP协议,支持多种过滤方式,可根据URL、IP、端口、请求头等来筛选请求,方便用户快速定位问题。此外,它还支持将抓取的数据保存为二进制文件或文本文件,方便用户离线分析。
对于开发者而言,小黄鸟HttpCanary也提供了一些有价值的功能。例如,可以通过设置代理方式,将HttpCanary作为代理服务器来拦截所有HTTP请求和响应,以便在调试过程中进行数据分析和修改。这样的功能可以显著减少开发调试的时间和难度。
小黄鸟HttpCanary还提供了完善的教学视频和
证书
,针对初学者和高级用户都有所帮助。总体来说,小黄鸟HttpCanary是一款十分优秀的Android抓包
工具
,无论是普通用户还是开发者,都可以从中受益。
### 回答2:
小黄鸟是一款安卓平台上的抓包
工具
,它的主要功能是通过分析网络请求数据,帮助开发人员找出应用程序的网络请求问题,在网络配置、数据加载、接口调用等方面提供帮助。
小黄鸟的优点在于其使用简单、功能强大、可靠性高,而且完全免费。它能够支持http和
https
两种协议下的数据抓取和分析,可以通过图表展示数据发送、接收等各项指标,并可实时查看接口返回值。同时,小黄鸟还拥有多种观察模式,可以将请求数据按时间顺序、域名、地址和协议等不同维度进行分类,帮助用户更好地了解网络请求。
小黄鸟的使用方法也很简单,只需安装后开启调试模式,然后在需要监测的应用中设置代理即可。此外,小黄鸟提供了完整的视频教程和使用
证书
,可以帮助开发人员更好地利用小黄鸟
工具
进行网络调试和优化工作。
总之,小黄鸟是一款非常实用的抓包
工具
,可以帮助开发人员在应用开发过程中更准确地了解网络请求数据,在网络调试、性能优化、故障排查等方面提供有力支持,是开发人员不可缺少的必备
工具
之一。
### 回答3:
小黄鸟httpcanary是一款开源的网络抓包
工具
,常用于安卓移动应用程序的抓包分析。通过小黄鸟httpcanary可以捕获和分析HTTP和
HTTPS
请求,并且可以保存请求数据以供后续分析。它适用于调试和分析安卓应用程序的网络问题,例如实时调试API接口、分析数据流量、监控请求响应数据和利用网络数据来优化应用程序的性能等。
小黄鸟httpcanary非常易于使用,用户只需要下载安卓apk文件并安装,即可开始使用。同时,它还提供了
证书
安装教学视频,帮助用户在
HTTPS
协议下正常抓取数据。通过合理的使用,可以帮助开发者更好地理解网络请求和响应的交互过程。
此外,小黄鸟httpcanary的源代码完全开源,用户可以自由地获取代码、修改和重新分发。同时,它还具备自定义规则功能,可以通过自定义规则设置筛选条件,只捕获需要的数据。这使得小黄鸟httpcanary非常适合于定制
处理
特殊应用程序的需求。
总之,小黄鸟httpcanary是一款功能强大、易于使用的抓包
工具
。它可以帮助开发者轻松进行网络调试和优化,为移动应用程序的开发和维护提供了不可或缺的支持。
解决Eclipse2021-12版本pom.xml报错“cvc-elt.1.a: Cannot find the declaration of element ‘project‘.”
解决Eclipse2021-12版本pom.xml报错“cvc-elt.1.a: Cannot find the declaration of element ‘project‘.”
qq_52066207:
为servlet项目编写定时任务
天行归来:
为servlet项目编写定时任务
selectwherefrom:
获取亚马逊产品广告报告(Sponsored Product Report)
skyhi1234:
解决Eclipse2021-12版本pom.xml报错“cvc-elt.1.a: Cannot find the declaration of element ‘project‘.”
唯一回忆: