kbpgp.js

FAQ

There's something missing from this documentation -- how do I ______?

The kbpgp website is brand new, and we're just getting started with the docs. Let us know in the github issues.

What do you mean, "designed for concurrency"?

Crypto is CPU intensive. The worst offender is RSA key pair generation, when we hunt for big-assed prime numbers. This plus JavaScript's single-threadedness equals a nightmare. Consider this fun thing:

weird_sum = ->
  x = 0
  for i in [0...10000000]
    x -= Math.cos Math.PI
  x

console.log weird_sum()

The above function could take a few seconds in a browser, during which it would be unresponsive - no other JavaScript could run, no buttons or links could be clicked, nothing. It would pause your great life experience. In Node.js, your whole process would lock, and you'd go download Go.

One solution in the browser is to farm this process off to a web worker. This often works, although web workers are new and somewhat buggy (at the time of this writing, it's not hard to crash Chrome's), and they have very high overhead. On the Node side, you could run a separate process just for performing math operations, and send RPC's to it. (Aside: this is a good idea anyway.)

Regardless of where you run it, a heavy math operation can be written with single-thread concurrency in mind. You just have to (1) do work in batches, (2) defer to the event loop periodically via setTimeout or process.nextTick, and (3) call back with an answer, instead of returning one. A simple example:

_batch = (a, batch_size, stop_at, cb) ->
  b   = Math.min stop_at, a + batch_size
  sum = 0
  sum -= Math.cos(Math.PI) for i in [a...b]
  if (a = b) is stop_at
    cb sum
  else setTimeout ->
      _batch a, batch_size, stop_at, (sub_sum) ->
        cb sum + sub_sum
  , 0

weird_sum = (cb) -> _batch 0, 100000, 10000000, cb

weird_sum (sum) ->
  console.log sum

Writing code like this - where you call back with an answer - is contagious. If foo calls bar, and bar calls back with an answer, foo can't return that answer. It also must call back.

All of kbpgp is written this way, although a bit prettier than the example above. Further, kbpgp supports abortions and progress hook functions, unlike the examples above. In summary, you can run kbpgp on the same thread as other code, without any problems.

Why do you use CoffeeScript? Or rather, IcedCoffeeScript?

We think CoffeeScript is a great improvement over JavaScript, because it amounts to more concise, easier to read code. As for IcedCoffeeScript, we wrote it! Well, specifically Max forked CoffeeScript. IcedCoffeeScript is the same as CoffeeScript but has two additions ("await" and "defer") that make async programming much nicer. Note the complete lack of a worker function in our above example, converted to Iced:

weird_sum = (cb) ->
  x = 0
  for i in [0...10000000]
    x -= Math.cos Math.PI
    if not (x % 10000)
      await setTimeout defer(), 0
  cb x
      

Of course, kbpgp is compiled to JavaScript as part of our build process, so you do not need to use CoffeeScript to use it.

Why don't you just use OpenPGP.js or Google's End-to-End for Keybase?

At the time of this writing, Google's End-to-End demands elliptic curve key generation -- and that is not compatible with the most popular PGP implementations. kbpgp can generate and handle both RSA and EC keys, so it's designed to work with the GPG and other PGP implementations.

As for OpenPGP.js, in late 2013, we looked at OpenPGP.js. Unfortunately, at the time we saw some things we disliked. This has been discussed elsewhere, and Google's team has also commented on it. We have not reviewed OpenPGP.js in its current state.

We're just getting started with this tutorial and examples. Hit us up on github if anything is missing.