Java使用X509Certificate获取证书详情

Java使用X509Certificate获取证书详情

场景

​ 我们在进行加密相关项目的开发时会使用到各种证书,证书文件以.cer后缀结尾。双击打开后可以看到证书的详细信息,包括版本、序列号、签名算法、颁发者、使用者、有效期、公钥等信息。那么我们如何使用java程序获取相应的信息返回给前端展示呢?
在这里插入图片描述

证书的内容和意义如表所示:

证书内容意义
Version告诉这个X.509证书是哪个版本的,目前有v1、V2、v3
Serial Number由证书分发机构设置证书的序列号
Signature Algorithm Identifier证书采用什么样的签名算法
Issuer Name证书发行者名,也就是给这个证书签名的机构名
Validity Period证书有效时间范围
Subject Name被证书发行机构签名后的公钥拥有者或实体的名字,采用X.500协议,在Internet上的标志是惟一的。例如:CN=Java,OU=Infosec,O=Infosec Lab,C=CN表示一个subject name。

最终效果

{
  "code": 200,
  "data": {
    "effDate": "2023-07-03 17:44:47",
    "serialNumber": "00a4cbbc64a19f000003",
    "issuerDN": "CN=1111, C=CN",
    "type": "EC",
    "expDate": "2024-07-02 17:44:47",
    "subjectDN": "CN=52000000121320000000_5200000012, O=123, O=00, L=123, L=123, C=CN",
    "sigAlgName": "SM3的SM2签名"
  },
  "msg": "成功"
}

代码实现

/**
     * 
     * @param fileName
     * @return 证书详情
     */
public Object getCert(String fileName){
        fileName =filePath+File.separator+fileName;
        JSONObject jsonObject = new JSONObject();
        CertificateFactory cf = null;
        X509Certificate cert = null;
        try {
            cf = CertificateFactory.getInstance("X.509");
            FileInputStream in = new FileInputStream(fileName);
            cert = (X509Certificate) cf.generateCertificate(in);
        } catch (CertificateException e) {
            throw new RuntimeException(e);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        //签发者
        String subjectDN = cert.getSubjectDN().toString();
        //使用者
        String issuerDN = cert.getIssuerDN().toString();
        //序列号(十进制转十六进制,左补零)
        String serialNumber =  String.format("%" + 20 + "s", cert.getSerialNumber().toString(16)).replace(' ', '0');
        //生效时间
        Date effDate = cert.getNotBefore();
        //过期时间
        Date expDate = cert.getNotAfter();
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String effStr = null;
        String expStr = null;
        try {
            effStr = sdf.format(effDate);
            expStr = sdf.format(expDate);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //秘钥类型
        String type = cert.getPublicKey().getAlgorithm();
        //签名哈希算法
        String sigAlgName = cert.getSigAlgName();

        jsonObject.put("subjectDN",subjectDN);
        jsonObject.put("issuerDN",issuerDN);
        jsonObject.put("serialNumber",serialNumber);
        jsonObject.put("effDate",effStr);
        jsonObject.put("expDate",expStr);
        jsonObject.put("type",type);
        jsonObject.put("sigAlgName", CertType.getNameByCode(sigAlgName));
        return jsonObject;
    }
/**
     * 
     * 枚举类,实现数字证书对象标识Oid与名称的转换
     */
public enum CertType {

    rsaEncryption("1.2.840.113549.1.1.1", "RSA"),
    sha1withRSAEncryption("1.2.840.113549.1.1.5", "SHA1"),
    ECC("1.2.840.10045.2.1", "ECC"),
    SM2("1.2.156.10197.1.301", "SM2"),
    SM3WithSM2("1.2.156.10197.1.501", "SM3的SM2签名"),
    sha1withSM2("1.2.156.10197.1.502", "SHA1的SM2签名"),
    sha256withSM2("1.2.156.10197.1.503", "SHA256的SM2签名"),
    sm3withRSAEncryption("1.2.156.10197.1.504", "SM3的RSA签名"),
    commonName("2.5.4.3", "主体名"),
    emailAddress("1.2.840.113549.1.9.1", "邮箱"),
    cRLDistributionPoints("2.5.29.31", "CRL分发点"),
    extKeyUsage("2.5.29.37", "扩展密钥用法"),
    subjectAltName("2.5.29.17", "使用者备用名称"),
    CP("2.5.29.32", "证书策略"),
    clientAuth("1.3.6.1.5.5.7.3.2", "客户端认证");


    CertType(String code, String name) {
        this.code = code;
        this.name = name;
    }

    private String code;

    private String name;


    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static String getNameByCode(String code){
        CertType[] values = CertType.values();
        for(CertType plateColorEnum:values){
            if(code.equals(plateColorEnum.getCode())){
                return plateColorEnum.getName();
            }
        }
        return null;
    }

    public static String getCodeByName(String name){
        CertType[] values = CertType.values();
        for(CertType plateColorEnum:values){
            if(name.equals(plateColorEnum.getName())){
                return String.valueOf(plateColorEnum.getCode());
            }
        }
        return null;
    }

}

数字证书的对象标识符

数字证书的每项都有对象标识Oid,SM2数字证书的主要区别就是公钥算法、公钥参数、签名算法标识不一样,其余的都是X509里标准项。数字证书常见得对象标识有如下:

对象标识符名称OID
rsaEncryptionRSA算法标识1.2.840.113549.1.1.1
sha1withRSAEncryptionSHA1的RSA签名1.2.840.113549.1.1.5
ECCECC算法标识1.2.840.10045.2.1
SM2SM2算法标识1.2.156.10197.1.301
SM3WithSM2SM3的SM2签名1.2.156.10197.1.501
sha1withSM2SHA1的SM2签名1.2.156.10197.1.502
sha256withSM2SHA256的SM2签名1.2.156.10197.1.503
sm3withRSAEncryptionSM3的RSA签名1.2.156.10197.1.504
commonName主体名2.5.4.3
emailAddress邮箱1.2.840.113549.1.9.1
cRLDistributionPointsCRL分发点2.5.29.31
extKeyUsage扩展密钥用法2.5.29.37
subjectAltName使用者备用名称2.5.29.17
CP证书策略2.5.29.32
clientAuth客户端认证1.3.6.1.5.5.7.3.2
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
可以使用 X509Certificate 证书来实现加解密功能。具体实现方法可以参考以下步骤: 1. 从证书文件中读取证书信息,可以使用 Java 中的 KeyStore 类来实现。 2. 使用证书中的公钥进行加密,可以使用 Java 中的 Cipher 类来实现。 3. 使用证书中的私钥进行解密,同样可以使用 Cipher 类来实现。 以下是一个简单的示例代码: ``` import java.io.FileInputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.X509Certificate; import javax.crypto.Cipher; public class X509CertificateDemo { public static void main(String[] args) throws Exception { // 读取证书文件 FileInputStream fis = new FileInputStream("certificate.pfx"); KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(fis, "password".toCharArray()); // 获取证书和私钥 X509Certificate cert = (X509Certificate) ks.getCertificate("alias"); PrivateKey privateKey = (PrivateKey) ks.getKey("alias", "password".toCharArray()); // 获取证书中的公钥 PublicKey publicKey = cert.getPublicKey(); // 加密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedData = cipher.doFinal("Hello, world!".getBytes()); // 解密 cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedData = cipher.doFinal(encryptedData); System.out.println(new String(decryptedData)); } } ``` 注意:这只是一个简单的示例代码,实际应用中需要考虑更多的安全性和异常处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值