2015-02-16

Keystore

3 years ago (or maybe 2 and half years), I've written incomplete PKCS#12 library which could at least load PKCS#12 keystores. Then it's been neglected for couple of years because there was no need to handle PKCS#12 keystores. Recently I needed to read it and remembered I've written it long time ago. So I thought it's a good timing to finish up the library at least making it work a bit properly like storing keys and certificates. It took couple of days to finish it but kinda looks good enough to expose so let me introduce a bit. (I still need to write documents, *sigh*)

The basic usage of PKCS#12 library is like the followings:
(import (rnrs) (rsa pkcs :12))

(define keystore (load-pkcs12-keystore-file "test.p12" "test"))

(pkcs12-keystore-get-key keystore "ca")
;; -> private key (currently only RSA is supported)

(pkcs12-keystore-get-certificate keystore "ca")
;; -> certificate (currently only X509 is supported)

;; storing a private key
;; private-key must be an RSA private key
;; certs must be a list of certificate for above private key.
(pkcs12-keystore-set-key! keystore "ca2" private-key certs)

;; storing a certificate
;; cert must be an X509 certificate
(pkcs12-keystore-set-certificate! keystore "ca2" cert)

;; dump to a file
(store-pkcs12-keystore-to-file keystore "test2.p12" "test2")
There are couple of more APIs but basic ones are above (I guess). There are couple of issues such as it can't handle empty password. These are because of my laziness and would be fixed when it became a problem (as usual).

There are bunch of types of keystores, one of the most famous one is PKCS#12 (also JKS is pretty famous but not supported yet). Since there are so many, it would be better to have abstract layer that absorbs the different. (I know it's not really Scheme way but I like convenient way.) So I also made a generic layer.
(import (rnrs) (security keystore))

;; passing 'pkcs12 as the keystore type
(define keystore (load-keystore-file 'pkcs12 "test.p12" "test"))

;; retrieving a key.
;; the last argument is password which is ignored on PKCS#12 keystore
(keystore-get-key keystore "ca" "test")

;; storing a key
;; the same as pkcs12-keystore-set-key! but with password
(keystore-set-key! ks "key" private-key "ignore" certs)

;; dump to a file
(store-keystore-to-file keystore "test2.p12" "test2")
For PKCS#12, key entry doesn't have password (well, if I read the specification correctly, it can be different password from store pass. But this is how Bouncy Castle behaves so should be proper behaviour).

I'm also working on JKS (and JCEKS) so the generic layer would be able to handle it (not the current HEAD but definitely 0.6.2).

No comments:

Post a Comment