JCEKS
This is a replacement for the Java keytool
program that manipulates .jceks
(Java keystore) files. Its purpose is to reduce the pain of DevOps burdened by
Java deployments.
Usage
To install:
go get github.com/ProninIgorr/minijceks
Simply running the minijceks
command with no arguments produces a usage screen.
To inspect the content of a .jceks
file:
$ minijceks inspect my.jceks
# … shows certificates
$ minijceks inspect --password foo my.jceks
# … shows certificates, verifies the digest, shows keys encrypted with
the common password
To unpack a .jceks
file:
$ minijceks unpack --password foo --key-password server:bar my.jceks
$ tree my.jceks.d
my.jceks.d/
├── certs
│ └── ca.pem
├── keys
│ └── server
│ ├── cert-0001.pem
│ ├── cert-0002.pem
│ └── privkey.pem
└── password
3 directories, 5 files
Inspect
The inspect
command will show details about the certificates and possibly the
private keys embedded in the .jceks
file.
Without a password, the tool is able to display all the certificates and can
show which private keys are in the file (alias, timestamp, and associated
certificate chain), but it cannot decrypt the private keys to inspect them or
verify the integrity digest over the file.
If the keystore password is given, then the integrity digest can be verified.
Furthermore, this password will be used to attempt to decrypt each private key
embedded in the file. It is possible that one or more keys were encrypted using
different passwords; in that case, the --key-password <key_alias:password>
option may be used.
Unpack
The unpack
command will unpack each certificate (and private key if the
password is given) into a directory tree. It could be considered similar to
a tar x
operation.
The output directory name is derived by taking the source filename and adding a
.d
onto the end. If the directory already exists the command will refuse to
run.
The directory tree format is suitable for use with the pack
command.
Pack
The pack
command will pack a directory tree into a .jceks
file. It takes two
arguments: the name of the input directory, and the name of the output file. It
could be considered similar to a tar c
operation.
TODO: explain directory format.
TODO list
Pull requests accepted!
- OpenJDK appears to have a second key encryption algorithm available for private
keys using 3DES. This needs to be implemented for decryption purposes.
- Validation hints:
- Check that certificate entries are valid CA certificates (intermediate or
otherwise).
- Check private key certificate chains have correct corresponding public key,
correct order, and do not include the final root CA.
- Write clear file format specifications in a document.
- Testcases! I have some internal ones but they're not data I can share, so it
would be good to gather some real-world examples and check that we can
process them correctly.
- Unit tests for the functions would be good.
- PKCS#8 library: either find an existing one and extend it with the algorithms
we need for Java, or write a new one.
- Programmable mode? Auto-generate a new .jceks file based on a set of
instructions.
References
The .jceks
file format doesn't appear to be explicitly documented, but the
OpenJDK source is clear enough. It has a comment giving the file structure as
well as code for parsing and creating .jceks
files:
PKCS#8
Private keys are wrapped in PKCS#8, which is actually incredibly simple. It's
an ASN.1 object that has an algorithm OID followed by a blob of encrypted data.
Details in RFC5208 §6:
Key encryption type 1
There appear to be two types of encryption that can be used to encrypt the
private keys. One of them seems to be custom crypto (you should never do
this):
Key encryption type 2
Another type of encryption used to encrypt private keys. This might be specific
to OpenJDK. It appears to be a custom combination of existing algorithms: