This post is about simple-crypt, a Javascript wrapper library for encrypting and signing data.
Here's what I did and didn't want to do with simple-crypt:
- Don't re-implement any cryptographic algorithms.
- Don't get into key exchange protocols.
- Do write extensive unit tests, ideally including some well-known test vectors.
- Do make a consistent API for encrypting and signing data using different types of keys:
- Symmetric keys
- Asymmetric keys
- Password-derived keys
- Do hardcode which encryption and signature algorithms to use:
- HMAC-SHA-256 for symmetric signing.
- RSA-SHA-256 with RSASSA-PSS encoding for asymmetric signing.
- AES-128-CBC for symmetric key encryption.
- RSA, RSAES-OAEP encoding and AES-128-CBC for asymmetric encryption.
- Do add a checksum before encrypting data.
- Do JSON encode data before encrypting or signing it.
- Do make it easy to disable processing and pass plaintext through instead.
- Do make it easy to add metadata so the recipient knows which key to use.
My previous article introduced a Node.js
module, node-jsjws, for performant
generation and verification of JSON Web Signatures and JSON Web Tokens.
Brian J Brennan's python-jws is a
nice module for generating and verifying JSON Web Signatures in Python. I've
already written some unit tests for node-jsjws which show that the JSON Web
Signatures it generates can be verified by python-jws and vice versa.
Note that I had to make some minor changes to python-jws in order to add
support for the RSASSA-PSS signature algorithms (PS256, PS384 and
PS512).
My previous article was really
just a pointer to some enhancements I made to Kenji Urushima's jsjws project. jsjws is an implementation of JSON Web Signatures (JWS) in Javascript.
Although an excellent library, jsjws as it stands isn't usable on Node.js
for the following reasons:
- It uses pure Javascript crypto routines which are slower that those provided by Node.js modules.
- It uses some global functions which are provided by browsers.
- It isn't packaged up as Node.js module.
Last time out, I added support for RSASSA-PSS encoded signatures to the ursa Node.js module. The code I added exposes the OpenSSL implementation of RSASSA-PSS to Node.js programs. RFC 3447 recommends new applications use RSASSA-PSS instead of the older RSASSA-PKCS1-v1_5 scheme.
RFC 3447 also recommends new applications use RSAES-OAEP ciphertext encoding instead of the older RSAES-PKCS1-v1_5 scheme. ursa already exposes the OpenSSL RSAES-OAEP implementation to Node.js programs.
I've been using Tom Wu's RSA Javascript library in a non-Node.js project. Tom's library is pure Javascript (it doesn't wrap native code) and I wanted to contribute something back:
- A Javascript implementation of RSASSA-PSS signature encoding.
- A Javascript implementation of RSAES-OAEP ciphertext encoding.
This post is about encoding schemes for RSA signatures. The Public-Key
Cryptography Standards (PKCS) #1 (RFC 3447) specifies two schemes:
Basically, PSS is the newer scheme and can optionally include some randomness
in the encoding (though it doesn't rely on it). There are no known attacks
against PKCS1-v1_5 but you have to be more careful when using it. PKCS#1
recommends PSS in new applications: