Collaboration/reuse of forge #3

Closed
dlongley opened this Issue Apr 12, 2013 · 6 comments

Comments

Projects
None yet
4 participants

Hi Tim,

I'm not sure if you're aware of the forge project (JavaScript cryptography) or not, but you may want to take a look:

https://github.com/digitalbazaar/forge

Feel free to share/reuse whatever code you want to from forge in cifre or contribute back to the project. I just wanted to let you know it was out there; it might save you some time/effort.

-Dave

Contributor

creationix commented Apr 12, 2013

Thanks @dlongley! I wish I had seen this before. I just spent the last week trying to understand ASN.1 and DER/BER codecs and fighting jsbn to do what I wanted. After reading your blog post I think that I may have something to share with my aes and hash functions, but you RSA code is much better and more complete.

The one thing I've been trying to figure out is the best representation of data. Initially I thought typed arrays were the obvious winner, but after several weeks of working with them, I found they are terribly slow. Also, only newer browsers have them. Is it really safe to store arbitrary binary data in JavaScript strings using one character per byte? If so, I may switch to that format. It's trivial to convert between that as UTF-8 and JavaScript's native UCS-16 encoding. (https://github.com/openpeer/cifre/blob/master/utils.js#L96 and https://github.com/openpeer/cifre/blob/master/utils.js#L107)

What do you think would be a good way to collaborate?

Contributor

creationix commented Apr 12, 2013

@dlongley, for now I just pulled in part of forge that I need for my project into the forge subfolder of cifre. Later when I have more time, I'll better integrate things. I added integration with node's random number generator and will later add in integration for chrome and firefox's native random generator.

Since cifre's scope looks like a strict subset of forge's scope, maybe we could merge and let cifre become a dependency of forge and move all the crypto primitives to cifre? Basically cifre would then be the crypto primitives of forge with any good parts that cifre has to contribute merged in.

@creationix, sorry about that, ASN.1 and DER/BER can definitely be a pain!

Initially I thought typed arrays were the obvious winner, but after several weeks of working with them, I found they are terribly slow.

Yeah, when forge was originally written typed arrays weren't really available. We looked at using arrays of integers but found them to be far slower and use more memory than the alternative we went with, which is, effectively, ensuring all characters are UTF-8 encoded and then stored in JavaScript's native UCS-2 strings. This similar to what you've done in your utils.js link. As I understand it, what that code will do is actually transform the incoming characters to code points that will always begin with 00, such that using charCodeAt on the resulting string will return the correct "byte" value (0-255). Of course, the storage is non-optimal here because two bytes are used for every "byte" we're concerned with (better than using integer arrays though), but it gets the job done ... most of the time. The only caveat is with extremely rare surrogate pairs. JavaScript, when it was originally being standardized, wasn't prepared to deal with code points that were larger than 16 bits. The end result is kind of a mess. If you have a code point that is in the surrogate pair range, the code is going to throw a malformed URI exception:

unescape(encodeURIComponent(String.fromCharCode(0xd800))) // 0xd800 is the first surrogate pair

This is extremely rare (haven't seen it in practice) and is an unfortunate consequence of the history of JavaScript and Unicode. ES6 is trying to fix things related to this. To clarify, this is a problem whenever the above "UTF-8 conversion" code is used, regardless of whether you store the result in an array of integers or a string. A fix for this, I think, would be to search for surrogate pairs first and then do the encoding manually in those cases.

In any case, with forge we just went with what was practical and will work 99.99% of the time. As typed arrays become more performant, we should switch over to them, but someone who recently forked forge, and attempted a minor re-write with typed array support, also indicated that they were still terribly slow. The benchmarks I've seen around the web also support the idea that typed arrays are slow at the moment. Browser devs, I guess, have just done a much better job optimizing string operations and internal string buffering than they have typed arrays, etc. so far. Had forge been written a couple years later (nowish) we probably would have made our buffer API look more like typed arrays so we could switch later -- but provided the string implementation as a way to speed things up behind the scenes for now. I'd recommend something similar to that approach.

Since cifre's scope looks like a strict subset of forge's scope, maybe we could merge and let cifre become a dependency of forge and move all the crypto primitives to cifre? Basically cifre would then be the crypto primitives of forge with any good parts that cifre has to contribute merged in.

That sounds like a plan. We aren't doing too much active development on forge at the moment (we're way too busy with PaySwarm). But it does sound like parts of forge could be merged into cifre and it could become forge's base. We should also keep in mind that the WebCryptoAPI is under development; we ultimately planned to build on top of that whenever it was available.

One more thing I should mention that should really help speed things up for you, since you're using jsbn, is to look at this patch that was just submitted to forge a few days ago: digitalbazaar/forge#19

This site has some benchmarks for various JS crypto toolkits: http://cryptojs.altervista.org/

I also think crypto libs should move towards a WebCrypto API. The PolyCrypt project has made some progress towards that goal: http://polycrypt.net/. If we had more time to work on this stuff I'd be nice to make a WebCrypto layer for forge and/or let forge use WebCrypto API if available. The scope of the WebCrypto API doesn't cover everything in forge so it won't completely replace it.

cadorn added the wontfix label Feb 19, 2015

Contributor

cadorn commented Feb 19, 2015

We use FORGE exclusively now.

cadorn closed this Feb 19, 2015

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