How to load public certificate from pem file?

66,044

Solution 1

An X.509 certificate and an X509EncodedKeySpec are quite different structures, and trying to parse a cert as a key won't work. Java's X509EncodedKeySpec is actually SubjectPublicKeyInfo from X.509 or equivalent and more convenient PKIX also linked from Key, which is only a small part of a certificate.

What you need to do is read and parse the cert and then extract the pubkey from the cert. Standard SunJCE CertificateFactory can do it (and can read either PEM or DER to boot) like this:

CertificateFactory fact = CertificateFactory.getInstance("X.509");
FileInputStream is = new FileInputStream (args[0]);
X509Certificate cer = (X509Certificate) fact.generateCertificate(is);
PublicKey key = cer.getPublicKey();
is.close();
// add error handling as appropriate, try-with-resources is often good

If you have BouncyCastle you can use its provider the same way (just add a second argument to .getInstance or set the default provider list order), or you can use PEMParser with JcaX509CertificateConverter -- which effectively does the same thing, internally running the data through a CertificateFactory.

Solution 2

With Sun JVM it is also possible with

import java.security.cert.X509Certificate;
import sun.security.x509.X509CertImpl;

InputStream is = ...
X509Certificate crt = new X509CertImpl(is);

, although I'd prefer the accepted answer as JVM implementation-independent one.

Under the hood, in Sun JVM, CertificateFactory(more precisely, X509Factory) does instantiate X509CertImpl , but there is very subtle difference between the two approaches: CertificateFactory caches X509 Certificate instances by binary content of the input stream, the one that can be retrieved by cer.getEncoded().

The cache can be cleared by

fact.generateCertificate(null);
Share:
66,044
surendhar_s
Author by

surendhar_s

Updated on December 05, 2021

Comments

  • surendhar_s
    surendhar_s over 2 years

    I was trying to extract RES public key from the file below

    -----BEGIN CERTIFICATE-----
    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
    -----END CERTIFICATE-----
    

    Here is the code i did..

    public static PublicKey loadPublicKeyFromFile(File publicKeyFile) throws Exception {
    
        FileReader file = new FileReader(publicKeyFile);
        PemReader reader = new PemReader(file);
        X509EncodedKeySpec caKeySpec = new X509EncodedKeySpec(reader.readPemObject().getContent());
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PublicKey caKey = kf.generatePublic(caKeySpec);
        return caKey;
    }
    

    But It throws out

    java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data isn't an object ID

    What's the appropriate way to extract RES Public key from a file..

  • ch271828n
    ch271828n about 3 years
    the input stream should be closed
  • dave_thompson_085
    dave_thompson_085 about 3 years
    @ch271828n: I originally meant that to be included in 'to taste', but I might as well be explicit, and found other useful updates as well -- thanks.
  • ch271828n
    ch271828n about 3 years
    by the way, close it in finally{} or use the try(...){}
  • Maarten Bodewes
    Maarten Bodewes almost 2 years
    It's 2022 by now, and 2021 in the given answer; we know we should not be using Sun internal classes by now.
  • igor.zh
    igor.zh almost 2 years
    @MaartenBodewes, I never said we should use this way. Like I said, I'd prefer the accepted answer's way. Just wanted to look a little bit "under the hood" and point out that in most popular Sun JVM there is a caching in place.