b l o g _ m a x i m u m

keytool enhancements

Monday Feb 23, 2009

There're two enhancements made to keytool today (the doc has not been updated, it's still for JDK 6):

new commands and options

We have 2 new commands: -gencert, -printcertreq and 1 new option -ext. Read the RFE descriptions.

-printcertreq is simply for printing the content of a certificate request. It behaves like the -printcert command, reading a PKCS #10 format cert req from a file or stdin, and does not need a keystore to run with.

-gencert is a big enhancement, which means you can setup a tiny CA now with keytool. The command reads a certificate request from a file (specified by -infile) or stdin, creates a certificate, signs it with the private key in the PrivateKeyEntry specified by -alias, and print the output to another file (specified by -outfile) or stdout. That's it. Just like -genkeypair for self-signed certificate, you can specify -sigalg, -startdate, and -validity options to the command.

-ext is used to add X.509v3 certificate extensions to a certificate (for both -genkeypair and -gencert) or a certificate request (for -certreq). The option can be specified multiple times to add multiple extensions. The value of this option takes the form of name[:critical][=value]. Here name is the extension name, and value the value (omit if empty). The :critical modifier, if provided, means the extension's isCritical attribute is true; otherwise, false.

Currently we support these named extensions (case-insensitive):
namevalue
BC or BasicConstraintsThe full form: "ca:{true|false}[,pathlen:len]"; or, "len", a shorthand for "ca:true,pathlen:len"; or omitted, means "ca:true"
KU or KeyUsageusage(,usage)*, usage can be one of digitalSignature, nonRepudiation (contentCommitment), keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign, encipherOnly, decipherOnly. Usage can be abbreviated with the first few letters (say, dig for digitalSignature) or in camel-case style (say, dS for digitalSignature, cRLS for cRLSign), as long as no ambiguity is found. Usage is case-insensitive.
EKU or ExtendedkeyUsageusage(,usage)*, usage can be one of anyExtendedKeyUsage, serverAuth, clientAuth, codeSigning, emailProtection, timeStamping, OCSPSigning, or any OID string. Named usage can be abbreviated with the first few letters or in camel-case style, as long as no ambiguity is found. Usage is case-insensitive.
SAN or SubjectAlternativeNametype:value(,type:value)*, type can be EMAIL, URI, DNS, IP, or OID, value is the string format value for the type.
IAN or IssuerAlternativeNamesame as SubjectAlternativeName
SIA or SubjectInfoAccessmethod:location-type:location-value (,method:location-type:location-value)*, method can be "timeStamping", "caRepository" or any OID. location-type and location-value can be any type:value supported by the SubjectAlternativeName extension.
AIA or AuthorityInfoAccesssame as SubjectInfoAccess. method can be "ocsp", "caIssuers" or any OID.

When name is an arbitrary OID, value is the HEX dumped DER encoding of the extnValue for the extension excluding the OCTET STRING type and length bytes. Any extra character other than standard HEX numbers (0-9, a-f, A-F) are ignored in the HEX string. Therefore, both "01:02:03:04" and "01020304" are accepted as identical values. If there's no value, the extension has an empty value field then.

A special name "honored", used in -gencert only, denotes how the extensions included in the certificate request should be honored. The value for this name is a comma-seperated list of "all" (all requested extensions are honored), "name[:{critical|non-critical}]" (the named extension is honored, but using a different isCritical attribute) and "-name" (used with all, denotes an exception). Requested extensions are not honored by default.

If, besides the -ext honored option, another named or OID -ext option is provided, this extension will be added to those already honored. However, if this name (or OID) also appears in the honored value, its value and criticality overrides the one in the request.

The subjectKeyIdentifier extension is always created. For non self-signed certificates, the authorityKeyIdentifier is always created.

Try this command on your system if you already have 2 self-signed certs me and ca created in your default keystore:
    keytool -storepass changeit -certreq -alias me -ext bc -ext eku=sa,ca | \
    keytool -storepass changeit -gencert -alias ca -ext honored=all,-bc \
        -ext aia=ocsp:uri:http://ocsp.ca.com,cai:uri:http://ca.com/ca.crt  |
    keytool -printcert
Here, the user me requests for an SSL server certificate from the CA. It asks for an EKU extension named ServerAuth and ClientAuth, which is useful for an SSL server. However, it also secretly asks for a BC extension, so that it can start its own CA. The CA, with sharp eyes, notices this problem. It grants all extensions requested except BC. It also adds another extension AIA which includes issuer info into the cert generated.

openssl-style certificate support

When you run openssl x509 -text with an X.509 certificate, the output includes a bunch of human-readable texts before the BASE64-encoded certificate itself. Java did not accept these texts and threw an exception something like "unknown tag or bad length", since it tried to interpret the file as DER encoded. Now we enhance the X.509 CertificateFactory class to accept this kind of certificate.



By the way, have I mentioned -startdate before? This option allows you to change the issuing time of a certificate from current system time to something else. Some people may like this option to create certs for special test cases, and some other people would like the certificate to have an earlier time because they want to use it right now but their clients and servers are not precisely time-synchronized. The grammar for this option takes one of the 2 following formats:
  1. ([+-]nnn[ymdHMS])+
  2. [yyyy/mm/dd] [HH:MM:SS]
So -startdate -5M means 5 minutes ago, -startdate "2001/01/01 11:11:11" means that exact time, -startdate 11:11:11 means that time today. Read more in the RFE decriptions.

[5] Comments
Like this post? del.icio.us | furl | slashdot | technorati | digg
Comments:

These are really great news!

Just one question, the description of the RFE states that -ext has been implemented for Java 7, and not for Java 6 as you say. Does this mean that it has been back-ported to Java6 and will be available at some update?

Cheers

Posted by Rodrigo Ruiz on March 10, 2009 at 11:41 PM CST #

Not likely for JDK 6, normally new features do not go into update releases.

Posted by Weijun on March 11, 2009 at 08:45 AM CST #

Hello Weijun,
From your post, it means that adding DNS names extensions as Certificate Subject Alt Name for X509v3 is not possible in JDK 6 (and previous versions) but it'll be with JDK 7 which implements the -ext option. Correct?
Thanks,
Gildas.

Posted by SALAUN on October 23, 2009 at 10:14 PM CST #

It's now in JDK 7 (and OpenJDK), not in JDK 6 or any other previous releases.

Posted by Weijun on October 24, 2009 at 07:29 PM CST #

Many thanks for your answer Weijun!
Gildas

Posted by Gildas on October 26, 2009 at 04:25 PM CST #

Post a Comment:
  • HTML Syntax: NOT allowed