bmargulies
bmargulies

Reputation: 100161

How do I read an sha1WithRSAEncryption public DER key in Java?

openssl x509 -inform DER -text 

on my DER file gives the dump on the bottom of this question.

I try to read it with:

static PublicKey getCertKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
    URL keyUrl = Resources.getResource(LManager.class, "iid.der");
    byte[] keyBytes = Resources.toByteArray(keyUrl);
    X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePublic(spec);
}

And I get:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:205)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
....
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Caused by: java.security.InvalidKeyException: IOException: ObjectIdentifier() -- data isn't an object ID (tag = -96)
at sun.security.x509.X509Key.decode(X509Key.java:397)
at sun.security.x509.X509Key.decode(X509Key.java:403)
at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:83)
at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:298)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:201)
... 25 more


Certificate:
Data:
    Version: 3 (0x2)
    Serial Number:
        a9:cb:e1:41:03:30:df:c5
    Signature Algorithm: sha1WithRSAEncryption
    Issuer: REDACTED
    Validity
        Not Before: Jun  5 14:28:02 2014 GMT
        Not After : Jun  5 14:28:02 2024 GMT
    Subject: REDACTED
    Subject Public Key Info:
        Public Key Algorithm: rsaEncryption
        RSA Public Key: (1024 bit)
            Modulus (1024 bit):
                00:87:bd:18:df:ff:49:12:b6:92:76:e3:c9:21:b4:
                86:8d:f2:a9:03:37:7b:64:c3:85:63:bc:0f:67:bc:
                f9:76:6a:72:4e:f9:e2:01:52:a3:df:40:6d:3d:91:
                99:70:a5:6a:66:c8:ef:1b:18:1d:91:5a:a5:b1:0b:
                0b:81:fd:d7:27:22:86:fa:c3:8d:b4:93:d5:98:e4:
                2d:08:20:6b:43:44:d6:ae:37:79:2e:bc:65:e4:c3:
                71:c4:9c:5d:04:8d:8a:f4:a5:cc:96:52:f0:72:59:
                8e:0a:b3:06:55:e3:65:fb:63:b5:d2:4b:5d:e1:38:
                87:0b:e8:d2:c0:f8:7f:78:fd
            Exponent: 65537 (0x10001)
    X509v3 extensions:
        X509v3 Subject Key Identifier:
            25:D6:CC:08:15:CA:B6:F0:9C:59:DC:14:52:2C:EF:B5:41:76:51:38
        X509v3 Authority Key Identifier:
            keyid:25:D6:CC:08:15:CA:B6:F0:9C:59:DC:14:52:2C:EF:B5:41:76:51:38
            DirName:/C=US/ST=Washington/L=Seattle/O=Amazon.com Inc./CN=ec2.amazonaws.com
            serial:A9:CB:E1:41:03:30:DF:C5

        X509v3 Basic Constraints:
            CA:TRUE

Upvotes: 0

Views: 1144

Answers (1)

dave_thompson_085
dave_thompson_085

Reputation: 39010

First, openssl -inform DER -text is an error. The openssl program is a wrapper that runs one of a bunch of functions, identified by the first argument, which in this case must be x509, so openssl x509 -inform DER -text.

That's a clue. Your file is an X.509 certificate not (just) a public key. Certificates in general, and X.509 certificates in particular, contain a public key but that is not the same thing as being a public key.

Since your file is an X.509 certificate, use a CertificateFactory of type X.509 to read it. The pattern is similar: use a static .getInstance() method to get a factory then use .generateCertificate() to take some input, here a stream that reads the data (directly from the file, or from memory if you have it buffered), and generate a Certificate object. (Note java.security.cert.Certificate not the obsolete and deprecated java.security.Certificate -- some IDEs may not default to the good one.)

If you want to use the public key in the certificate for something like encrypting or verifying call .getPublicKey() on the Certificate. If you want to look at other information such as the subject name or extensions which are specific to X.509, cast the Certificate to X509Certificate (also in java.lang.security.cert) and use its additional methods.

Also: the certificate is signed with sha1withRSA. The publickey itself is an RSA key, and could be used for any RSA operation -- but since the cert claims this key belongs to a CA, the corresponding privatekey should be used only for signing certs and/or CRLs (controlled by KeyUsage if present, but it's not unless you've redacted it) and thus doing something with this publickey other than verifying those certs and/or CRLs is useless. And since the key is only 1024 bits, using a signing hash stronger than SHA1 would be wasted, except for the facts that RSA-1024 is already considered insecure (since early 2014) and using SHA1-RSA for certificates is considered at risk and prohibited after sometime next year.

Upvotes: 1

Related Questions