Java CertificateFactory.generateCertPath(inputStream) not working as expected

Viewed 300

I recently discovered Java's CertificateFactory as a method of converting PEM content into certs and cert chains. My PEM content is just an X.509 certificate in PEM format (i.e., ----BEGIN CERTIFICATE----\n ...) in a String.

I tried to write my conversion method like this:

public List<? extends Certificate> certChainFromPem(String certPem) {
    try (ByteArrayInputStream bais = new ByteArrayInputStream(certPem.trim().getBytes(StandardCharsets.UTF_8))) {
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        CertPath certPath = factory.generateCertPath(bais);
        return certPath.getCertificates();
    } catch (GeneralSecurityException | IOException e) {
        throw new InvalidCertChainPemException("invalid cert chain pem content: " + certPem, e);
    }
}

This threw an exception indicating "Empty input" in the exception message. After much experimentation, I finally rewrote my method like this:

public List<? extends Certificate> certChainFromPem(String certPem) {
    try (ByteArrayInputStream bais = new ByteArrayInputStream(certPem.trim().getBytes(StandardCharsets.UTF_8))) {
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        Collection<? extends Certificate> certs = factory.generateCertificates(bais);
        CertPath certPath = factory.generateCertPath(new ArrayList<>(certs));
        return certPath.getCertificates();
    } catch (GeneralSecurityException | IOException e) {
        throw new InvalidCertChainPemException("invalid cert chain pem content: " + certPem, e);
    }
}

And now it works. Can someone please explain to me why the certificate factory is able to generate certificates, but not a cert path, from the input stream? With the exact same input, I'm able to generate a cert path from the certificates generated from the input stream. What key concept am I missing here? Both methods have an InputStream constructor, and stepping into the Java source shows me that the generateCertPath method seems to have no trouble parsing the PEM content from the input stream. It just can't seem to figure out what to do with the parsed content after that.

0 Answers
Related