Skip to content

Instantly share code, notes, and snippets.

@rmhrisk
Last active October 31, 2018 15:17
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmhrisk/d876c155a2266aea81e8d65a6635e94d to your computer and use it in GitHub Desktop.
Save rmhrisk/d876c155a2266aea81e8d65a6635e94d to your computer and use it in GitHub Desktop.
Web Crypto is Everywhere!

We do security-oriented development in Javascript on both the server (Node) and in the browser and strive to share code whenever possible. This led us to build a few different libraries based on Web Crypto, the first of which was PKIjs.

The first commit to PKIjs, our PKI library for browsers based on Web Crypto, was in February of 2014. When we started this project Web Crypto was basically only supported by Chrome. Today that picture has changed a lot and all major browsers support it to varying degrees.

Using Web Crypto made sense to use as the cryptographic library for this project for a few reasons, one of the largest being the risks associated with Javascript based cryptography.

Though browser support for Web Crypto has improved significantly there are still a few rough edges in Safari and Edge as well as limited algorithm support in these browsers. You can see what your browser supports here.

These rough edges and limited algorithm support led us to create a polyfill for Web Crypto we call webcrypto-liner. This utilizes Javascript-based cryptography to fill the gaps that exist in these implementations so that it is possible to build cross-browser interoperable applications while we wait for Edge and Safari to catch up.

You can use the drop-down at the top of our Web Crypto Test Page to enable webcrypto-liner for the test run. If you do, keep an eye on the console where you will see when fallback to the Javascript implementations occurs.

Since we wanted to use libraries that utilize Web Crypto in Node we developed a polyfill for node we call node-webcrypto-ossl. This polyfill is a binding to OpenSSL, the same implementation of the algorithms exposed natively in Node.

Our work also often requires us to use Hardware Security Modules and Smart Cards. From this requirement, three other projects emerged, the first of which is a PKCS#11 binding for Node we call PKCS11js.

PKCS11js lets you access the richness of the PKCS#11 support exposed by security modules from within Node, this is great but PKCS#11 is an API designed for another era and there are many implementation gotchas that every application will encounter that can be abstracted away by a higher level library.

That is where the second library comes in, we call it Graphene. Graphene was designed to provide Node applications a simple to use an object-oriented layer for interacting with any PKCS#11 enabled device. We have made sure it works with the most commonly used Hardware Security Modules so you don’t need to worry about it.

But as I said one of our goals is share code wherever possible, this is where the third library comes in node-webcrypto-p11. node-webcrypto-p11 is a layer on top of Graphene that allows your Node applications that use libraries based Webcrypto to utilize HSMs with no virtually no code changes. It is our hope that in the large majority of cases node-webcrypto-p11 will satisfy usage requirements so you do not have to worry about PKCS#11 and it's semantics.

Architecturally this looks something like this:

+------------------------+             +------------------------+            +-------------------------+
| BROWSER                |             | SERVER                 |            | SERVER                  |
|                        |             |                        |            |                         |
| +--------------------+ |             | +--------------------+ |            | +---------------------+ |
| |     Application    | |     <->     | |     Application    | |     OR     | |     Application     | |
| +--------------------+ |             | +--------------------+ |            | +---------------------+ |
| +--------------------+ |             | +--------------------+ |            | +---------------------+ |
| |        PKIjs       | |             | |        PKIjs       | |            | |       PKIjs         | |
| +--------------------+ |             | +--------------------+ |            | +---------------------+ |
| +--------------------+ |             | +--------------------+ |            | +---------------------+ |
| |  webcrypto-liner   | |             | | node-webcrypto-p11 | |            | | node-webcrypto-ossl | |
| +--------------------+ |             | +--------------------+ |            | +---------------------+ |
| +--------------------+ |             | +--------------------+ |            +-------------------------+
| |     Web Crypto     | |             | |      Graphene      | |
| +--------------------+ |             | +--------------------+ |
+------------------------+             | +--------------------+ |
                                       | |      pkcs11js      | |
                                       | +--------------------+ |
                                       | +--------------------+ |
                                       | |   Security Module  | |
                                       | +--------------------+ |
                                       +------------------------+

Though the Web Crypto API is not perfect we believe that when combined with our libraries serves as a fine foundation to build cross-platform crypto-aware applications and libraries that can work both in the browser and on the server as well as with PKCS#11 based security modules.

We have released all of these packages under permissive Open Source licenses with the hope that others will be able to use these projects to build amazing applications of their that utilize these new browser capabilities.

Libraries

Description
PKIjs A pure JavaScript library implementing the formats and standards that are used in PKI applications.
webcrypto-liner A WebCrypto pollyfill that "smooths out" the rough-edges in existing User Agent implementations.
Graphene A simple layer for interacting with PKCS #11 / PKCS11 / CryptoKI for Node in TypeScript.
pkcs11js A Node.js implementation of the PKCS#11 2.3 interface.
node-webcrypto-p11 A WebCrypto Polyfill for Node in TypeScript built on PKCS#11.
node-webcrypto-ossl A WebCrypto Polyfill for Node in TypeScript built on OpenSSL

FAQ

Why did you decide to build on Web Crypto instead of NACL or something simpler than Web Crypto?*

NACL is a great interface but it is not available natively in the browser, it also only exposes modern crypto primitives which results in you not being able to build applications that will interoperate with many existing systems.

Additionally building on a Javascript NACL interface in the browser would require distributing a library that supports those interfaces. While today, on some browsers, it is necessary to ship a polyfill like webcrypto-liner, in the future it will not be required. This means building on NACL requires size overhead that Web Crypto will not ultimatley.

If I write a library or application in the browser, based on Web Crypto, can I use it in Node also?

Yes. This is exactly why we did node-webcrypto-ossl and node-webcrypto-p11.

How is your test page different than diafygi's webcrypto-examples?

Diafygi's webcrypto-examples are just that examples (though great ones). Our WebCrypto Tests are intended to be tests, as a result, we try many different options and key lengths for each capability.

I noticed that not all tests pass on your test page pass when using webcrypto-liner, why is that? webcrypto-liner was designed to use the native webcrypto implementation wherever possible. There are some cases where you can not mix-and-match javascript and native algorithms to create a working suite due to the way the interfaces are defined.

Additionally, for size reasons we have only implemented the things we believe browsers do not currently support well and might be needed for interoperability, for example, we only support two of the four key export modes and do not add support for RSA PKCS#1.5 based signatures.

Can I use node-webcrypto-p11 in the browser?

No. This module will only work in Node.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment