Retrieve Subject alternative names of X.509 certificate in java

前端 未结 2 1464
既然无缘
既然无缘 2021-01-18 02:35

I have tried using the solution provided in this link.

I am getting following error when i tried reading subject alternative names of X.509 Certificate

相关标签:
2条回答
  • 2021-01-18 03:15

    Many examples use hard-coded integers. For readability, I much prefer to use:

    • GeneralName.dNSName = 2
    • GeneralName.iPAddress = 7
    • ... etc

    The code:

    public static String[] parseHostNames(X509Certificate cert) {
        List<String> hostNameList = new ArrayList<>();
        try {
            Collection<List<?>> altNames = cert.getSubjectAlternativeNames();
            if (altNames != null) {
                for(List<?> altName : altNames) {
                    if(altName.size()< 2) continue;
                    switch((Integer)altName.get(0)) {
                        case GeneralName.dNSName:
                        case GeneralName.iPAddress:
                            Object data = altName.get(1);
                            if (data instanceof String) {
                                hostNameList.add(((String)data));
                            }
                            break;
                        default:
                    }
                }
            }
            System.out.println("Parsed hostNames: " + String.join(", ", hostNameList));
        } catch(CertificateParsingException | IOException e) {
            System.err.println("Can't parse hostNames from this cert.");
            e.printStackTrace();
        }
        return hostNameList.toArray(new String[hostNameList.size()]);
    }
    

    Note: The accepted answer checks for byte[], but won't compile on my system. I found some other examples using byte[] by calling new ASN1InputStream((byte[])data).readObject();, but I have no certificate to test it with, so I've removed it from my example.

    0 讨论(0)
  • 2021-01-18 03:17

    I tried with your code for me it is working, I tested with a certificate exported from internet explorer

    Internet Explorer -> Tools -> Internet Options -> Content -> Certificates -> Untrusted Publishers -> www.google.com
    

    I exported this as ".cer", I made few changes to your code

    public static List<String> getSubjectAlternativeNames(X509Certificate certificate) {
            List<String> identities = new ArrayList<String>();
            try {
                Collection<List<?>> altNames = certificate.getSubjectAlternativeNames();
                if (altNames == null)
                    return Collections.emptyList();
                for (List item : altNames) {
                    Integer type = (Integer) item.get(0);
                    if (type == 0 || type == 2){
                        try {
                            ASN1InputStream decoder=null;
                            if(item.toArray()[1] instanceof byte[])
                                decoder = new ASN1InputStream((byte[]) item.toArray()[1]);
                            else if(item.toArray()[1] instanceof String)
                                identities.add( (String) item.toArray()[1] );
                            if(decoder==null) continue;
                            DEREncodable encoded = decoder.readObject();
                            encoded = ((DERSequence) encoded).getObjectAt(1);
                            encoded = ((DERTaggedObject) encoded).getObject();
                            encoded = ((DERTaggedObject) encoded).getObject();
                            String identity = ((DERUTF8String) encoded).getString();
                            identities.add(identity);
                        }
                        catch (UnsupportedEncodingException e) {
                            log.error("Error decoding subjectAltName" + e.getLocalizedMessage(),e);
                        }
                        catch (Exception e) {
                            log.error("Error decoding subjectAltName" + e.getLocalizedMessage(),e);
                        }
                    }else{
                        log.warn("SubjectAltName of invalid type found: " + certificate);
                    }
                }
            }
            catch (CertificateParsingException e) {
                log.error("Error parsing SubjectAltName in certificate: " + certificate + "\r\nerror:" + e.getLocalizedMessage(),e);
            }
            return identities;
        }
    

    I saved the file to c:\aa1.cer

    X509Certificate cert=null;
            FileInputStream fis = new FileInputStream("c:\\aa1.cer");
            BufferedInputStream bis = new BufferedInputStream(fis);
    
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            if (bis.available() > 0)
                try{
                   cert = (X509Certificate)cf.generateCertificate(bis);
                }
                catch (CertificateException e) {
                    e.printStackTrace();
                }
            System.out.println(CertificateInfo.getSubjectAlternativeNames(cert));
    

    I got the output as [www.google.com, google.com]

    Please check your certificate, I think the problem is your certificate

    0 讨论(0)
提交回复
热议问题