Giter Site home page Giter Site logo

rubycrypto / rbnacl Goto Github PK

View Code? Open in Web Editor NEW
982.0 38.0 85.0 1.02 MB

Ruby FFI binding to the Networking and Cryptography (NaCl) library (a.k.a. libsodium)

License: MIT License

Ruby 100.00%
cryptography nacl libsodium ruby x25519 ed25519 salsa20 chacha20

rbnacl's People

Contributors

aadavids avatar abom avatar ajlai avatar anakinj avatar anirishduck avatar ankane avatar apotheon avatar asmod4n avatar bitdeli-chef avatar bkmgit avatar douglasdollars avatar edwardbetts avatar elijh avatar fudanchii avatar gdwrd avatar grempe avatar hieuk09 avatar jedisct1 avatar jshawl avatar kron4eg avatar mjio avatar namelessjon avatar nijikon avatar noraj avatar orien avatar razorinc avatar shaicoleman avatar tarcieri avatar valthon avatar vipulnsward avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rbnacl's Issues

PrivateKey constructor: does it need 2 args?

I'd like for the second arg of the key constructors to specify an encoding, e.g.:

Crypto::PrivateKey.new(str, :base58)

...but I see Crypto::PrivateKey takes a public key as its second argument. I don't think this should be necessary as you should be able to calculate the private key with Curve25519 multiplication, so there shouldn't ever be a need for the user to pass it in themselves.

Needs crypto_secretbox bindings

But I'm tempted to rename it SymmetricBox, since it is that. And also to avoid confusion with you not using a SecretKey for a SecretBox.

Also, could I have the commit bit on this repo, please? New features should stay in PRs, but for docco fixes and other similar things, it would be easier. Also that way we can divide up the API by issues and assigned to's.

Blake2b KEYBYTES_MIN incorrect?

RbNaCl::Hash::Blake2b::KEYBYTES_MIN is presently 16 and any keys that are less than 16 bytes are rejected. However, this is not correct according to the Blake2b paper:

http://eprint.iacr.org/2013/322.pdf

Key byte length (1 byte): an integer in [0,64] for BLAKE2b, in [0,32]
for BLAKE2s (set to 0 if no key is used)

Provide non-raising versions of the decrypt function

Emitting ⊥ could also be returning false or nil, since that is not a valid string. In situations where you're checking anyway, this could be cheaper than raising. This should be implemented in a manner consistent with the bang methods for authentication tag and signature checking.

FFI::NotFoundError: Function 'crypto_onetimeauth_poly1305_ref' not found in [libsodium.so]

libsodium-0.4.3 installed from source, make check passes
Ubuntu 13.04 (GNU/Linux 3.8.0-29-generic x86_64)
(Vagrant VM, also fails on remote server (ubuntu 12.10))
ruby 2.0.0-p247 installed via rbenv

require 'rbnacl' fails in IRB, Pry, and from file with:

FFI::NotFoundError: Function 'crypto_onetimeauth_poly1305_ref' not found in [libsodium.so]
from /home/vagrant/.rbenv/versions/2.0.0-p247/gemsets/vod-gemset/gems/ffi-1.9.0/lib/ffi/library.rb:251:in `attach_function'

Bad namespace citizen

This gem uses the Crypto module namespace, despite the gem being named differently.

I have been in the process of releasing a similar library based on NaCl, for which I'd already reserved the gem name cryptography. I'd be more than happy to yield ownership of that gem name (and thus the Cryptography namespace) to this project, since it largely implements my intended goals.

RbNaCl::SecretBuffer backed by sodium_malloc

libsodium 0.7.0 adds sodium_malloc(), sodium_allocarray(), and sodium_free() which manage buffers with guard pages, along with sodium_mprotect_noaccess(), sodium_mprotect_readonly(), and sodium_mprotect_readwrite() for changing memory permissions.

Given these primitives, it should be possible to construct an RbNaCl::SecretBuffer for managing things like keying material (and potentially plaintexts) which keeps buffers off-heap and preferentially marks them as PROT_NONE when they're not in use.

Full libsodium 0.7.0 release notes

Library is broken on rubinius

Seriously broken! It doesn't even encrypt(!) due to a difference in how rubinius handles the memory for strings, apparently. I think for rubinius, we will will need to use MemoryPointers, not strings. Though it works for ruby and jruby, apparently.

In addition, the rbx version of ffi is missing some nice functions on FFI::MemoryPointer like put_bytes and get_bytes so you end up with constructions like:

m.put_array_of_uchar(0, msg.bytes.to_a)
# or ...
ct.get_array_of_uchar(0, ct.total).pack('c*')

Which is fixed in rbx-head, by the looks of things, but is broken even on rc-1.

Ship it

This is a tracking ticket for the remaining tasks prior to the first release (which I'd like to call 1.0.0)

AFAIK, these tasks are just finishing the README:

Documentation

  • Crypto::RandomBoxNonce
  • Crypto::Box
  • Crypto::Scalar
  • Authenticators (done-"ish")

Other tasks

  • Factor out all test vectors into a shared file (done-"ish")
  • Add a "power-on self test" (skip for now?)

I can tackle the scalar documentation right away ;) (Edit: done!)

Stop referencing specific implementations directly

Presently we bind to the _ref implementations of algorithms everywhere, e.g.:

https://github.com/cryptosphere/rbnacl/blob/master/lib/rbnacl/nacl.rb#L51

We should not be doing this. libsodium has a compat.c to support this legacy API which we are presently thunking through:

https://github.com/jedisct1/libsodium/blob/master/src/libsodium/sodium/compat.c

We should call the implementation-agnostic API directly instead. It's available in libsodium 0.4+

Update documentation to reflect the RbNaCl 2.0.0 API

This is a tracking ticket for documentation changes that need to happen before we ship RbNaCl 2.0.0:

Landed in master

  • Remove all usage of the Crypto namespace, changing it to RbNaCl
  • New verify/authenticator API with transposed "tag" and "signature" arguments

Pending

  • Renamed constants from #74

Lock RbNaCl 2.0.0 to libsodium 0.4.5+?

libsodium is now updated to 0.4.5 in Homebrew. Should we lock RbNaCl to libsodium 0.4.5+ to ensure compatibility?

We can note that users who want to use an earlier libsodium can continue to use the 1.x version, and possibly do some 1.x releases to backport certain features.

Release a new gem version

Would love a new gem release, the last release 1.1.0 was back in April and there's been some features and fixes since then we rely on :)

Future plans

Are there any plans to create a higher-level library on top of RbNaCl?

One of my plans for my cryptography gem was to both build NaCl bindings as well as provide extremely high-level APIs to access the exposed functionality.

There are still many pitfalls a developer can find themselves in when working with a library at the level currently exposed. Best crypto practice is to never reuse a key across cryptographic primitives — my library, when generating keys, would encode them in a way that limited their use to only the primitive that they were generated for (e.g., Cryptography::SecretBox.key could only be used for secret boxes.

Similarly, the results of operations (generating keys, creating secret boxes, etc.) would be actual Ruby objects and not merely strings. Those objects can be serialized to and deserialized from things like hashes, JSON, binary strings, Base64 strings, etc. A secret box, for instance, would serialize to include the cryptographic algorithm used, the nonce, and the ciphertext itself.

This has several advantages. If a primitive is ever compromised, NaCl allows for swapping out the implementation with another one. If the ciphertexts and other cryptographic outputs are always stored with the algorithms used to generate them, upgrades can be seamless: new data will be encrypted with better algorithms, but old data can still be decrypted (with a loud warning generated) with no code changes on the user's part. Not simply storing outputs as strings also allows for "natural" operations like comparing auth tokens using ==. Since it's an object, the method can be implemented with constant timing.

I know this is getting long, so I'll cut it short here. Do you have any plans to write even higher-level adapters as part of this library?

Change outer namespace to RbNaCl

We can include a crypto.rb file if people want the original. I've also contacted the current owner of the "crypto" gem about letting us have the name.

Keys need refactoring

They're currently sharing a lot of functionality and can be simplified, as either a super class, or as a module which implements the common functions

Dynamically determine crypto constants

Right now, the values of a bunch of constants from libsodium (e.g., crypto_auth_hmacsha256_BYTES) are hardcoded in the RbNaCl source due to FFI not giving access to C headers.

Is there any interest in determining these dynamically instead? I have code already written for a C extension that copies them over into relevant modules.

void Init_constants(void) {
    VALUE mSodium       = rb_const_get(rb_cObject, rb_intern("Sodium"));
    VALUE mSodiumAuth   = rb_const_get(mSodium,    rb_intern("Auth"));
    VALUE mSodiumBox    = rb_const_get(mSodium,    rb_intern("Box"));

    VALUE mSodiumAuthHmacsha256 = rb_const_get(mSodiumAuth, rb_intern("HMACSHA256"));
    rb_define_const(mSodiumAuthHmacsha256, "PRIMITIVE", rb_str_new2("hmacsha256"));
    rb_define_const(mSodiumAuthHmacsha256, "VERSION",   rb_str_new2(crypto_auth_hmacsha256_VERSION));
    rb_define_const(mSodiumAuthHmacsha256, "BYTES",     INT2NUM(crypto_auth_hmacsha256_BYTES));
    ...

Crypto::SecretBox API suggestions

Right now the secret box API looks like:

crypto_secret_box.box(nonce, message)

But perhaps it could be

def box(message, options = {})
  options[:nonce] ||= Crypto::Random.random_bytes(24)
...
end

This would generate a random nonce by default. Convention over configuration!

I know we discussed this on IRC before, but I'm thinking it might make a lot of sense to prepend the nonce to the message (especially in the case of the above API where it's practically necessary), and automatically remove it when decrypting the message. This feels like another one of those "on Rails" things I think would really help expedite people using the library. With a 24-byte nonce there's really little risk of a random nonce causing problems (unless people have shitty RNGs) and if they really want to use a monotonic counter or something they can input their own nonces.

Regarding the open method, I'd recommend it works like this:

def open(message, options = {})
  ..
end

Perhaps the user could pass options[:nonce] if they got the nonce through some other channel than prepending it to the message, but by default, it'd just interpret the beginning of the message as the nonce.

The goal of all of this is to make the library easy to use by avoiding users even having to think about nonces by default, which given XSalsa20's unusually large 192-bit nonces is a fairly safe bet. This would make Crypto::SecretBox as easy to use as the "ezcrypto" gem (which doesn't provide authenticated encryption o_O)

What do you think?

variable-length verify

The CurveCP handshake needs to compare domain names for equality, and they can be a variable length up to 256.

A variable length verify method would be useful for this. One possibility would be to pad A and B then compare each 32-byte chunk.

This would also be useful for the hello packet which needs to verify a string of 64 null bytes.

Base58 encoding

More compact than base32, more readable than base64. All the current base58 implementations only take integers, but there's nothing inherent in the encoding that doesn't allow raw bytes.

Crypto::VerifyKey#verify and authenticator operand order

I know I was the one who advocated for the "verify with " ordering, but I now feel like this ordering is backward and we should've just used the same order as NaCl :(

This is how the APIs are designed consistently everywhere else, e.g. (key, message) or (nonce, message). It should also be (signature, message)

Mea culpa :(

I would suggest this change for RbNaCl 2.0

Cannot load library due to missing onetimeauth_ref function

When loading RbNaCl (1.1.0) against newer versions of libsodium (0.4.3, 0.4.5) the library fails to load with the error

/home/vagrant/.rvm/gems/ruby-1.9.3-p484/gems/ffi-1.9.0/lib/ffi/library.rb:251:in `attach_function': Function 'crypto_onetimeauth_poly1305_ref' not found in [libsodium.so] (FFI::NotFoundError)

My guess is that the crypto_onetimeauth_poly1305_ref function was removed in modern libsodium—it's just the reference implementation of poly1305 anyway. I believe that RbNaCl should be updated to depend on crypto_onetimeauth_poly1305 instead.

Power On Self Test

Write some code which tries a few cryptographic operations the first time the library is required, to verify all is working fine with the library.

  • Encrypt and decrypt a box (and secretbox!)
  • Construct and verify authenticators
  • Sign and verify signatures
  • generate some random numbers bytes and make sure they're not the same?

Argument ordering differs between Signatures and Authenticators

For VerifyKeys' verify method I used the following ordering:

verify(message, signature)

The idea being that you could remember this ordering as "verify message with signature". I also think this is the "natural" ordering for this sort of thing (sign at the end)

This differs from the ordering used in both NaCl and the one you used for the authenticators, which is:

verify(signature, message)

Either ordering works I guess, but they should be consistent. I'd just like to pick one that's easy to remember, and I think "verify message with signature" provides a nice mnemonic. I also remember Red25519 using the other ordering, me looking at that, and going "it really should be the other way around" which is why I did them this way in RbNaCl.

Error on require; crypto_onetimeauth_poly1305_ref_verify not found

I'm receiving the following attempting to require rbnacl on a new system with libsodium 0.4.5 (via brew) and ffi 1.9.3 (just updated after 1.9.2 was pulled). Any help would be greatly appreciated. :-)

/opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/ffi-1.9.3/lib/ffi/library.rb:261:in `attach_function': Function 'crypto_onetimeauth_poly1305_ref_verify' not found in [libsodium.dylib] (FFI::NotFoundError)
    from /opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rbnacl-1.1.0/lib/rbnacl/nacl.rb:30:in `wrap_nacl_function'
    from /opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rbnacl-1.1.0/lib/rbnacl/nacl.rb:29:in `module_eval'
    from /opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rbnacl-1.1.0/lib/rbnacl/nacl.rb:29:in `wrap_nacl_function'
    from /opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rbnacl-1.1.0/lib/rbnacl/nacl.rb:107:in `<module:NaCl>'
    from /opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rbnacl-1.1.0/lib/rbnacl/nacl.rb:14:in `<module:Crypto>'
    from /opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rbnacl-1.1.0/lib/rbnacl/nacl.rb:3:in `<top (required)>'
    from /opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/activesupport-4.0.0/lib/active_support/dependencies.rb:228:in `require'
    from /opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/activesupport-4.0.0/lib/active_support/dependencies.rb:228:in `block in require'
    from /opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/activesupport-4.0.0/lib/active_support/dependencies.rb:213:in `load_dependency'
    from /opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/activesupport-4.0.0/lib/active_support/dependencies.rb:228:in `require'
    from /opt/boxen/rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rbnacl-1.1.0/lib/rbnacl.rb:26:in `<top (required)>'

Expose aes128ctr

Sodium provides aes128ctr:

https://github.com/jedisct1/libsodium/tree/master/src/libsodium/crypto_stream/aes128ctr

While it should be considered a power user feature, CTR mode is not yet universally available via OpenSSL in Ruby, so it might be interesting to expose this to users.

aes128ctr can be trivially combined with HMAC for authentication + SHA-512 for key derivation to produce a robust authenticated encryption system that's "NIST approved". While I would love for everyone to use XSalsa20+Poly1305 for this application, some people may have requirements to the contrary, and may be scared of Poly1305 because it has not received as much scrutiny as HMAC.

If RbNaCl exposed aes128ctr, portable implementations of AES-CTR and HMAC-512256 would be available, and the latter with guaranteed constant time comparisons. This should make it incredibly easy to put together an AES-CTR + HMAC library for people who are afraid to use the djb crypto and prefer the crappier NIST-approved alternatives ;) And best of all, no OpenSSL would be required!

I've also suggested Sodium integrate aes256 as well. @jedisct1 suggested pulling in the aes256estream implementation from SUPERCOP:

jedisct1/libsodium#28

Here's a strawman of how aes(128|256)ctr could be combined into an authenticated encryption primitive:

https://gist.github.com/tarcieri/5351974

Factor README documentation into Wiki?

We have a lot of documentation in the README, which makes it a bit hard to find stuff.

Would it be helpful to factor this documentation into the Wiki instead of the README?

CurveCP support

I would personally like to build a Ruby binding to CurveCP. The question is: does this belong in RbNaCl, or a separate gem?

CurveCP is an experimental "alpha quality" library. I've opened an issue about it on Sodium I'd suggest reviewing:

jedisct1/libsodium#22 (comment)

If we were to add CurveCP support to RbNaCl, I'd suggest making it an optional feature, like:

require 'rbnacl/curvecp'

or perhaps

require 'rbnacl/extremely_dangerous_warning_warning_warning/curvecp'

The documentation would need to make it extremely clear that this is a power-user feature. Perhaps something like this?

DANGER: EXPERIMENTAL

To really answer the question of whether this belongs in RbNaCl or not: CurveCP is the "Networking" portion of the Networking and Cryptography library. Without it, I don't feel the library is complete ;)

Compare keys for equality

>> key = Crypto::PrivateKey.generate
=> #<Crypto::PrivateKey:1117939400065c544cbe19796d7de76a3acc47e81ea776099d3ea12f7a28782c>
>> key2 = Crypto::PrivateKey.new(key.to_bytes)
=> #<Crypto::PrivateKey:1117939400065c544cbe19796d7de76a3acc47e81ea776099d3ea12f7a28782c>
>> key == key2
=> false
>> key.public_key == key2.public_key
=> false
>> key.to_bytes == key2.to_bytes
=> true
>> key.public_key.to_bytes == key2.public_key.to_bytes
=> true

Fails to pass self test under rbx-2.0.0

I've got this easily reproducible here: https://github.com/knewter/rbnacl/tree/feature/rbx-20-test

Anyway, this fails with the following when I try to run the tests:

--(jadams@aye-seven)-(87/pts/6)-(1722/14-Oct-13)--
--($:~/ruby/rbnacl)(feature/rbx-20-test)rbx-2.0.0@rbnacl-- 
$ be rake
/home/jadams/.rvm/rubies/rbx-2.0.0/bin/rbx -S rspec ./spec/rbnacl/authenticators/poly1305_spec.rb ./spec/rbnacl/boxes/curve25519xsalsa20poly1305/private_key_spec.rb ./spec/rbnacl/boxes/curve25519xsalsa20poly1305/public_key_spec.rb ./spec/rbnacl/boxes/curve25519xsalsa20poly1305_spec.rb ./spec/rbnacl/group_element_spec.rb ./spec/rbnacl/hash/blake2b_spec.rb ./spec/rbnacl/hash_spec.rb ./spec/rbnacl/hmac/sha256_spec.rb ./spec/rbnacl/hmac/sha512256_spec.rb ./spec/rbnacl/random_nonce_box_spec.rb ./spec/rbnacl/random_spec.rb ./spec/rbnacl/secret_box_spec.rb ./spec/rbnacl/signatures/ed25519/signing_key_spec.rb ./spec/rbnacl/signatures/ed25519/verify_key_spec.rb ./spec/rbnacl/util_spec.rb
An exception occurred running at_exit handlers

    failed to generate correct ciphertext (RbNaCl::SelfTestFailure)

Backtrace:

                   RbNaCl::SelfTest.box_common_test at lib/rbnacl/self_test.rb:33
                          RbNaCl::SelfTest.box_test at lib/rbnacl/self_test.rb:18
                                  Object#__script__ at lib/rbnacl/self_test.rb:127
                       Rubinius::CodeLoader.require at kernel/common/code_loader.rb:243
                             Kernel(Object)#require at kernel/common/kernel.rb:685
                                  Object#__script__ at lib/rbnacl.rb:82
                       Rubinius::CodeLoader.require at kernel/common/code_loader.rb:243
                             Kernel(Object)#require at kernel/common/kernel.rb:685
                                  Object#__script__ at spec/spec_helper.rb:6
                       Rubinius::CodeLoader.require at kernel/common/code_loader.rb:243
                             Kernel(Object)#require at kernel/common/kernel.rb:685
                                  Object#__script__ at spec/rbnacl/authenticators/poly1305_spec.rb:2
            Kernel(RSpec::Core::Configuration)#load at kernel/common/kernel.rb:427
  { } in RSpec::Core::Configuration#load_spec_files at /media/jadams/ssd/home/jadams/.rvm/gems/rbx-2.0.0@rbnacl/gems/rspec-core-2.14.5/lib/rspec/core/configuration.rb:896
                                         Array#each at kernel/bootstrap/array.rb:66
         RSpec::Core::Configuration#load_spec_files at /media/jadams/ssd/home/jadams/.rvm/gems/rbx-2.0.0@rbnacl/gems/rspec-core-2.14.5/lib/rspec/core/configuration.rb:896
                       RSpec::Core::CommandLine#run at /media/jadams/ssd/home/jadams/.rvm/gems/rbx-2.0.0@rbnacl/gems/rspec-core-2.14.5/lib/rspec/core/command_line.rb:22
                            RSpec::Core::Runner.run at /media/jadams/ssd/home/jadams/.rvm/gems/rbx-2.0.0@rbnacl/gems/rspec-core-2.14.5/lib/rspec/core/runner.rb:80
                 { } in RSpec::Core::Runner.autorun at /media/jadams/ssd/home/jadams/.rvm/gems/rbx-2.0.0@rbnacl/gems/rspec-core-2.14.5/lib/rspec/core/runner.rb:17
                                          Proc#call at kernel/bootstrap/proc.rb:20
                      Rubinius::Loader#run_at_exits at kernel/loader.rb:702
                          Rubinius::Loader#epilogue at kernel/loader.rb:722
                              Rubinius::Loader#main at kernel/loader.rb:857
/home/jadams/.rvm/rubies/rbx-2.0.0/bin/rbx -S rspec ./spec/rbnacl/authenticators/poly1305_spec.rb ./spec/rbnacl/boxes/curve25519xsalsa20poly1305/private_key_spec.rb ./spec/rbnacl/boxes/curve25519xsalsa20poly1305/public_key_spec.rb ./spec/rbnacl/boxes/curve25519xsalsa20poly1305_spec.rb ./spec/rbnacl/group_element_spec.rb ./spec/rbnacl/hash/blake2b_spec.rb ./spec/rbnacl/hash_spec.rb ./spec/rbnacl/hmac/sha256_spec.rb ./spec/rbnacl/hmac/sha512256_spec.rb ./spec/rbnacl/random_nonce_box_spec.rb ./spec/rbnacl/random_spec.rb ./spec/rbnacl/secret_box_spec.rb ./spec/rbnacl/signatures/ed25519/signing_key_spec.rb ./spec/rbnacl/signatures/ed25519/verify_key_spec.rb ./spec/rbnacl/util_spec.rb failed

Signing and verifying keys need docs

I think docs on how to use/not use things in the library are very important. Employing things incorrectly is probably worse than not using them at all.

Diffie-Hellman example review

I'm not 100% certain I got the Diffie-Hellman example correct. Could someone please double check it for me? ;)

(Note: Elliptic curves are o_O)

FFI:NotFoundError when doing require 'rbnacl'

Hey guys, Im using rbnacl from git currently and just ran bundle update. When trying to boot my app I get this error:

../ffi-1.9.0/lib/ffi/library.rb:251:in `attach_function': Function 'crypto_sign_ed25519_seedbytes' not found in [libsodium.dylib] (FFI::NotFoundError)
    from ../rbnacl-f461d4771336/lib/rbnacl/sodium.rb:29:in `sodium_constant'
    from ../rbnacl-f461d4771336/lib/rbnacl/signatures/ed25519.rb:8:in `<module:Ed25519>'
    from ../rbnacl-f461d4771336/lib/rbnacl/signatures/ed25519.rb:3:in `<module:Signatures>'
    from ../rbnacl-f461d4771336/lib/rbnacl/signatures/ed25519.rb:2:in `<module:RbNaCl>'
    from ../rbnacl-f461d4771336/lib/rbnacl/signatures/ed25519.rb:1:in `<top (required)>'
    from ../rbnacl-f461d4771336/lib/rbnacl.rb:45:in `require'
    from ../rbnacl-f461d4771336/lib/rbnacl.rb:45:in `<module:RbNaCl>'
    from ../rbnacl-f461d4771336/lib/rbnacl.rb:13:in `<top (required)>'

Release 2.0.0

cc @namelessjon

We should release 2.0.0! At the very least, we should release 2.0.0.pre. I think we're ready to do that today. There are still a few remaining documentation items to address:

  • Update CHANGES.md

* Non-raising versions of verifiers

Add primitive names to all classes

Putting the algorithm names in each of the classes allows the core algorithms to change while retaining backwards compatibility for those who need it.

I propose the following:

  • RbNaCl::Box => RbNaCl::Curve25519XSalsa20Poly1305::Box
    • RbNaCl::PrivateKey => RbNaCl::Curve25519XSalsa20Poly1305::PrivateKey
    • RbNaCl::PublicKey => RbNaCl::Curve25519XSalsa20Poly1305::PublicKey
  • RbNaCl::SecretBox => RbNaCl::XSalsa20Poly1305::SecretBox
  • RbNaCl::SigningKey => RbNaCl::Ed25519::SigningKey
  • RbNaCl::VerifyKey => RbNaCl::Ed25519::VerifyKey
  • RbNaCl::Point => RbNaCl::Curve25519::Point
  • RbNaCl::Auth::OneTime => RbNaCl::Poly1305::OneTimeAuth
  • RbNaCl::Hash::Blake2b => RbNaCl::Blake2b::Hash
  • RbNaCl::HMAC::SHA256 => RbNaCl::SHA256::HMAC
  • RbNaCl::HMAC::SHA512256 => RbNaCl::SHA512256::HMAC

The original names will be preserved as shorthand aliases to the real algorithms with primitive names. The shorthand aliases will serve as the public-facing API, and those are what we should document.

The tests will work against the public-facing API, since that's what we don't want to break.

Abbreviated string inspect

I originally had the string inspect APIs work like this:

#<Crypto::Point:0900000000000000000000000000000000000000000000000000000000000000>

But as @namelessjon noted, this could potentially disclose private keys. Having a bunch of copies of a key in hex format labeled Crypto::PrivateKey floating around in the VM all super obviously is probably bad.

Perhaps we can avoid this by abbreviating how much of the key is shown:

#<Crypto::Point:090000000>

You know, kind of like git?

Must support specifying / introspecting on primitives

Right now, all the APIs in this library (that I can tell) simply defer to the default implementation in libsodium. This is dangerous, and RbNaCl needs to expose some way to both identify primitives used in an operation and specify that an alternative be used.

For instance, with the crypto_secretbox API, every function is actually a #define to crypto_secretbox_xsalsa20poly1305. What I'm asking for is:

  • calls to Crypto::SecretBox#box default to using crypto_secretbox
  • calls to Crypto::SecretBox#box indicate what low-level primitive was used
  • calls to Crypto::SecretBox#open can specify to use crypto_secretbox_xsalsa20poly1305

(note: Crypto::SecretBox is being used as an example; this also applies to Crypto::Box, Crypto::Auth, et al)

It's important that these features are available immediately. Imagine that tomorrow, XSalsa20Poly1305 is broken. A patch is released to nacl/libsodium to implement crypto_secretbox_aes_256_gcm and to define crypto_secretbox using this primitive. How does a current user of RbNaCl migrate their existing data to a non-broken version?

Even without a complete break, imagine any situation where libsodium changes the default primitive. What happens if a user upgrades libsodium now that the default has changed? RbNacl will start using the new primitive transparently, and users will have a mix of data encrypted with the old and new algorithms, with no way of detecting which ciphertexts were encrypted with which algorithm (other than through trial decryption).

Scenarios like this are exactly why libsodium and nacl make this type of information available to callers. And why RbNaCl must support it as well. RbNaCl doesn't have to make the process transparent, but it must make it possible.

Minor Fix in Wiki Docs

Tony,
Arguments are out of order in the wiki verify signature example.

Thanks,
Andy

# Check the validity of a message's signature
# Will raise RbNaCl::BadSignatureError if the signature check fails
verify_key.verify(message, signature)

It should be:

# Check the validity of a message's signature
# Will raise RbNaCl::BadSignatureError if the signature check fails
verify_key.verify(signature, message)

Method def:
https://github.com/cryptosphere/rbnacl/blob/master/lib/rbnacl/signatures/ed25519/verify_key.rb#L45

Don't deal with Encodings internally

I've brought it up incidentally in other bug reports, but it's worth bringing up separately: I don't believe that RbNaCl should concern itself with encodings.

It's a nice thought, but it has a lot of downsides IMHO. Every class that takes input or produces output now needs to have boilerplate code handling encoding or decoding. It makes the API less "clean". And it's incidental to (what I believe) should be the main focus of this library: crypto.

Cryptographic primitives understand one concept: bytes. Encoding data is, conceptually, a concern of transmission and storage layers. By handling encodings directly, this library takes on responsibilities which I believe are best suited for handling by other layers of an application.

For ease of use by tests (as @tarcieri mentioned earlier), a simple pair of helpers to convert between hex and binary is an easy solution.

In my mind, there is a clear separation of concerns for different parts of the "stack".

  1. NaCl: high-quality crypto implementations
  2. libsodium: cross-platform bundling of NaCl
  3. RbNaCl: straight ruby bindings to libsodium
  4. (various projects): extremely high-level user-facing Ruby libraries built on RbNaCl

I still think that RbNaCl is far too low-level for an average programmer to use safely (and that's okay!). There's still too much that can go wrong: users can use poor sources of randomness for keys, they can reuse nonces, they can use a key across cryptographic contexts, and all sorts of other rookie mistakes. Having documentation that warns against these sorts of things has been repeatedly proven not to be good enough.

I'd much rather RbNaCl be considered a building-block for experienced folk to build "crypto for the masses" on top of, than for it to try and take on too much responsibility.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.