使用java自带的sercurity包解析x.509证书字符串

背景:本来是使用某个公司的jar包解析x.509证书,但他的包被扫描的时候却发现了很多安全漏洞,所以要使用其他方式对x.509证书进行解析,我解析的是前端传过来的一个字符串,类似于这样的“MIICMjCCAZsCCQD3/xw1j77JATANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJD”,据网上说,x.509的文本其实是这样的-----BEGIN CERTIFICATE----- MIICMjCCAZsCCQD3/xw1j77JATANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJD.....省略----END CERTIFICATE-----。也就是说,前端是传给我中间的字符串。但网上的资源比较少,因此在这里总结一下,供后面的人知晓。

有关x.509和Base64的相关知识可以去网上查,因为代码用了这方面的知识。采用解析x509格式的包为java.sercurity,使用了反射的技术,反射会导致元空间内存变大,而且是在运行时编译,会影响性能,一般要少用。这里是因为我想获取的数据存在类似于递归的对象中,java.sercurity并没有提供获得该对象的接口(可能有,只是我懒得再细找了~),我只能使用反射。

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import sun.misc.BASE64Decoder;

import sun.security.x509.X500Name;
import sun.security.x509.X509AttributeName;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;

/**
 * 解析X509证书字符串
 */
public class X509StringRecord {

    public static void main(String[] args) throws IOException, CertificateException, ClassNotFoundException, IllegalAccessException {

        //模仿前端获得的X509证书格式的字符串,自己替换自己的,后面还省略了很多字符串串
        String signed_data="MIICMjCCAZsCCQD3/xw1j77JATANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJD";

        //身份证号
        String IDcord="";

        //姓名
        String name;

        //我解码的字符串存储X509这个类中,等下会使用反射,哇,这里是X500Name
        X500Name  x500Name=null;

        //存储前端传的参数通过base64进行解码的结果
        byte[] signedContent=null;

        BASE64Decoder decoder=new BASE64Decoder();
        signedContent=decoder.decodeBuffer(signed_data);

        //CertificateFactory解析是一个InputStream类型的对象,使用ByteArrayInputStream进行转换
        ByteArrayInputStream bain=new ByteArrayInputStream(signedContent);

        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        //这里不能用generateCertificate(bain);,它限制了inputStream的长度。应该用generateCertificates(bain);
        //另外,我这个例子这里报错应该是证书格式不符合,因为涉及到隐私,截取了部分,替换成自己的吧,
        List<? extends Certificate> certificates=(List<? extends Certificate>) cf.generateCertificates(bain);
        Iterator iterator=certificates.iterator();

        while(iterator.hasNext()){
            X509CertImpl x509Cert=(X509CertImpl) iterator.next();

            //通过反射获得X509CertInfo的对象
            Class x509CertImpl=Class.forName("sun.security.x509.X509CertImpl");
            Field[] fsX509CertImplFields=x509CertImpl.getDeclaredFields();

            for(Field fs509CertImplField:fsX509CertImplFields){
                //设置属性可达,不然会报访问私有属性异常
                fs509CertImplField.setAccessible(true);
                if("info".equals(fs509CertImplField.getName())){
                    //得到对应X509CertImpl对象中的X509CertInfo属性值
                    X509CertInfo certInfo=(X509CertInfo) fs509CertImplField.get(x509Cert);
                    //通过反射获得X500Name对象
                    Class classX509CertInfo=Class.forName("sun.security.x509.X509CertInfo");
                    Field[] fsX509CertInfoFields=classX509CertInfo.getDeclaredFields();
                    for(Field fsX509CertInfoField:fsX509CertInfoFields){
                        //得到对应X509CertImpl对象中的X509CertInfo属性值
                        fsX509CertInfoField.setAccessible(true);

                        if("subject".equals(fsX509CertInfoField.getName())){
                            x500Name=(X500Name) fsX509CertInfoField.get(certInfo);
                            break;
                        }
                    }
                    break;
                }
            }
        }

        if(x500Name!=null){
            //输出结果类似于CN=字符串,OU=TrustMore安全网关,O=T1,c=CN
            System.out.println(x500Name);
        }
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值