Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Elliptic curve crypto in IPNS" #1

Closed
daviddias opened this issue Sep 21, 2015 · 11 comments
Closed

"Elliptic curve crypto in IPNS" #1

daviddias opened this issue Sep 21, 2015 · 11 comments

Comments

@daviddias
Copy link
Owner

Ian and I started chatting recently about the idea of using Tweetnacl for the crypto operations on libp2p and we agreed to move the discussion to a github thread so everyone could participate:

Email thread:


Hi David,

It was great to meet you at container camp yesterday. The crypto library I mentioned is:
http://tweetnacl.cr.yp.to/
There is a Javascript port at:
https://github.com/dchest/tweetnacl-js
I've independently verified the results of the JS version against the origninal C version and my own Java version.

Tweetnacl is the only elliptic curve crypto that I would consider using. DJB is a legend, and the NSA had no hand in authoring it. One of the best demonstrations of its strength is that Tor uses it, and thus a lot of organisations have put a lot of effort into cracking it.

You said you were using the default node crypto. I understand it uses openssl under the hood, which doesn't appear to have curve25519 yet:
openssl/openssl#309

I'd love to hear your thoughts,
Ian


Hi Ian!

I share the same feeling, it is always good to put a face to the people we meet and work on the Internet :)

I’ve looked at tweetnacl in the past with Max Ogden because we wanted to have a standard module to upgrade any stream to a encrypted stream, but haven’t touched it since then.

The points you make are extremely valid and the first question I have in my head is that we need more than the crypto library from Node.js, because after all we need it to run in the browser, so what I started doing/drafting is a WebCrypto module that works both in Node.js and in the Browser, using the crypto module and the WebCryptoAPI. Would it be good to have a way to shim tweetnacl and expose it using the same interface? So that the users could pick the best crypto module for their case? This gives me the idea of creating an abstract-crypto, following the idea of https://github.com/diasdavid/abstract-stream-muxer and https://github.com/diasdavid/abstract-record-store.

What do you think! Also, maybe we can move this email thread to a github issue? ipfs/ipfs would be a good point, let me know if you are ok with it.

Cheers!
David


Yep, feel free to start an issue, and include some of my suggestions. Certainly exposing tweetnacl, but I was suggesting more, use it by default wherever you need a crypto choice. Apart from "post quantum" crypto (which have enormous keys) curve25519 wins on every metric against RSA and other ECC curves. Faster encryption, decryption, signing, unsigning, harder to crack, simpler to implement, smaller keys.

Ian


@daviddias
Copy link
Owner Author

I'm starting to feel that more and more the ideia of having 'abstract-crypto' for crypto module is the way to goo, so that devs can pic their own implementation, as long as it respects the spec and the interface (for convenience) it will be easy to swap in and out, check perf and avoid being locked to one specific implementation.

For example, in libp2p and the IPFS Node.js implementation case, it is imperative that we have a version that both works in the browser and in Node.js, but since we also want to support more languages, being spec compliant helps developers contribute and use implementations available on their ecosystems.

@ianopolous
Copy link

A crypto interface sounds great. something along the lines of (largely taken from https://github.com/dchest/tweetnacl-js):
box(message, nonce, theirPublicKey, mySecretKey)
box.open(box, nonce, theirPublicKey, mySecretKey)
sign(message, secretKey)
sign.open(signedMessage, publicKey)
secretbox(message, nonce, key)
secretbox.open(box, nonce, key)

Maybe a separate interface for key generation:
box.keyPair()
sign.keyPair()
secretbox.key()

It might make sense to split these into three interfaces for the three different types of crypto.

Are we considering any kind of keystore interface for storing keys?

@daviddias
Copy link
Owner Author

@dominictarr @substack, @jbenet and I just talked and he informed me you have already did some work towards this goal (having a crypto thing that works across platforms) and that also supports the DJB crypto primitives, where can I find more info about that? :)

@ianopolous
Copy link

That thing is TweetNaCl. We use it in Peergos for all our crypto.
Original C from DJB:
http://tweetnacl.cr.yp.to/software.html

Javascript port:
https://github.com/dchest/tweetnacl-js

Java port:
https://github.com/ianopolous/tweetnacl-java

@dominictarr
Copy link

there is also https://www.npmjs.com/package/libsodium-wrappers which wraps the emscripten version sodium. It's the fastest sign/verify, but it's also 3 megabytes of javascript, and it's almost the same api as
http://npm.im/sodium * (the main problem is that it uses UInt8Arrays instead of node Buffers) which means the same code doesn't run in both places... I started on https://www.npmjs.com/package/sodium-browserify to fix this, but since I don't actually need that for anything right now, it's not very far along.

  • the sodium module exposes a core api (which is just like the C api) and a "highlevel" "nice" api, I don't use the "nice" api because then the sodium docs still apply, and consistency is the most important thing.

@daviddias
Copy link
Owner Author

Thanks for jumping in @dominictarr ! :)

So, just organize thoughts, we have several contenders:

ThingBrowserNode.jsGoOther langs (at least possibly)
WebCryptoAPI
Node.js Crypto
TweetNaCl
libsodium~~✔~~✔

Digging more into this and trying to get some justified conclusions

@dominictarr
Copy link

@diasdavid you should put a tick, or some character that means "slow" for node.js crypto in the browser.
After some considerable effort, we do have an effectively complete polyfil for the crypto lib implemented at crypto-browserify. (there may be some obsecure settings that arn't supported, but all the basic primitives are implemented)

Another factor worth taking into account is that webcrypto and node expose ciphers needed to implement tls, but you couldn't implement a compatible tls using nacl. (maybe you could support 1 or two ciphersuits)
nacl does not provide a selection of algorithms, it just uses the best algorithms. If you have to make your cryptoapp backwards compatible with legacy software then you probably need webcrypto/node crypto,
but if you are building a new system, use nacl. If you don't use nacl, you'll need to learn a great deal about how the various primitives work in order to use them safely. Hint: all the Three Letter Acronyms protocotols have bugs that can bite you if you don't use them correctly (RSA, SHA, AES, TLS, SSH, etc... note that NACL is 4 letters ;)

All the nacl ciphers are designed carefully so that they do not have these surprising edgecases.

The other important factor is speed, although this might not be as important as you think. If your application has javascript crypto, but it's only symmetric crypto (hashes, ciphers) that is still pretty fast and is probably okay even in javascript. If you have lots of asymmetric crypto (like a signature on every update, as in secure-scuttlebutt) that is a problem. If you are using only occasional asymmetric operations then js might be okay.

@jbenet
Copy link

jbenet commented Sep 28, 2015

but if you are building a new system, use nacl.

I really, really dislike statements like this. nacl is one great way to abstract out all crypto (maybe even the best, i sure think so!) -- it's sane, good, fast, well written, safe, etc -- but it simply cannot be the only one for any serious systems aiming to get massive, widespread adoption. You will inevitably run into users with requirements outside your bounds.

Hint: all the Three Letter Acronyms protocotols have bugs that can bite you if you don't use them correctly (RSA, SHA, AES, TLS, SSH, etc... note that NACL is 4 letters ;)

Oh no! "ECC", "DHE", "BLS", "OTP", .... even "DJB"!!

SHA

What's the bug in SHA? just that you should use >SHA2?

The other important factor is speed

Indeed! ed25519 should be pretty fast anywhere though-- even

CurveCP

By the way, i looked into CurveCP perf this morning-- turns out all benchmarks show its perf in real networks isn't very good yet. The best benchmarks I found show it getting order(s) of magnitude worse perf than regular TCP. Though of course, none of these benchmarks are recent, and things may have changed. Would be good to have comprehensive benchmark repo.

Also, CurveCP (like TCP) will likely cause buffer bloat. {TLS, ...}/{uTP, LEDBAT} should not, though uTP will yield too aggressively to TCP flows, so it may not be a good solution for low latency applications (inc web requests).

My confidence is redoubled on QUIC-- it's really fast, sane, doesnt have head-of-line blocking (except for HTTP headers-- but i don't care about that), has ECC support, has both symmetric and asymmetric auth, can be used with all the right ciphers (sane AEADs), etc. Re buffer bloat, i'm not sure where QUIC stands on this, but the pluggable congestion control is much more promising than having to recompile kernels, or assuming "Chicago is right". In particular, i'm pretty stoked about pluggin something like Remy into QUIC.

@daviddias
Copy link
Owner Author

Thank you :)

What I'm reaching to a conclusion is that there is a clear separation between the establishment of the encrypted channel and the records signing. For records signing (or at least the ones we create for IPFS, the nature of the MerkleDAG and IPRS should enable other people to use different signing mechanisms), something like NaCl takes the lead as the one that is fast, well built and available in a variety of different platforms.

For the establishment of the encrypted channel, that lives on the transport level and thanks to libp2p, we can isolate and bring some sanity to adopt multiple options as well.

@dominictarr
Copy link

@jbenet sure well I'm just saying that ssl was the right answer ten years ago, but nacl is better today, in another ten years, who knows?

The bug in SHA is length extention. you can compute hash(x+y) if you know hash(x), knowing the length of x but not it's value, for some values of y (if it starts with a valid length padding that hash would append to x). This is why you need to use hmac. sha3 does fix this, though. Also there are lots of different ECC curves, you can't just choose any willynilly... I could go on.

@daviddias
Copy link
Owner Author

So, on the Browser WebCryptoAPI thing, the progress isn't as fast and smooth as we could hope for https://lists.w3.org/Archives/Public/public-webcrypto/2016Jan/0028.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants