On Jul 23, 2013, at 1:06 PM, Tony Arcieri <
tony.a...@gmail.com> wrote:
> On Tue, Jul 23, 2013 at 12:59 PM, Jonathan Stott <
jonatha...@gmail.com> wrote:
>> I like the idea of doing it this way. Though I don't think we need to
>> go for the fully technically correct 'rb_na_cl'. Is someone really
>> going to make a gem with a Rbnacl constant that would be conflicted by
>> lib/rbnacl.
>
> I don't think there's really a need to use 'rb_na_cl'. The present require directive is for 'rbnacl' which seems fine to me.
>
> A crypto.rb file containing the Crypto constant also seems fine.
Just trying to be technically correct (the best kind of correct). :)
> Yes, although something like Stephen's Sodium::Buffer might make sense.
Here be dragons.
I've finally gotten Sodium::Buffer to a reasonable state, but it's taken a lot of effort and many tweaks from the original approach.
Sodium::Buffer now internally allocates its own memory for the buffer, and stores its location in an FFI::Pointer (to avoid the garbage collector copying its bytes around, as you warned me about). And Sodium::Buffer#to_s now returns a String copied from that pointer, but wrapped inside of a proxy that handles the memory management. Without doing it this way, I don't believe there's a way to wipe the String's memory on garbage collection without introducing a circular dependency on something in the finalizer itself, preventing the String from ever being collected.
It's not perfect (lots of Ruby functions implemented in C expect honest-to-god Strings, not proxy-object-that-forwards-all-methods-to-a-string Strings), but it's as good as I think is possible in Ruby. You're welcome to the code, or if you have an idea for a better approach, I encourage you to try.
> Yeah, it makes a lot of sense. Less tied to the specific
> implementation, as long as they duck type closely. Unless you're
> specifically checking for what class you're getting (and we should
> encourage the use of the symbol names instead) it shouldn't break
> things.
They can all duck-type identically, from my experience.
The trick, in my experience, was to make RbNaCl::Box (for example) respond exactly as if it is an RbNaCl::Box::WhateverTheDefaultImplementationIs. And you can call RbNaCl::Box.implementation[:curve25519xsalsa20poly1305] to explicitly ask for a particular implementation.
> I think we can keep RbNaCl::Box and RbNaCl::SecretBox and make the other implementations in pluralized modules, e.g.: RbNaCl::Boxes::Curve25519XSalsa20Poly1305 and RbNaCl::SecretBoxes::XSalsa20Poly1305
Not a fan. But that might just be me.
> I also think we should return specialized objects which can e.g. tell
> you the primitive used, which also respond to #to_str, #to_s etc and
> are generally pretty stringlike. This information could then be used
> by a higher level construct. Maybe it isn't needed though.
That might be a bit much. As long as RbNaCl::SecretBox (and friends) respond to #primitive, you should be good. And that way is a lot simpler.
> Should we support calling sodium_init()?
In Sodium, I just call sodium_init() when the library is first loaded.
https://github.com/stouset/sodium/blob/master/lib/sodium/ffi/crypto.rb#L99
Technically, it's not threadsafe, but just document that you shouldn't require the library in independent threads. Since 99% of Ruby code doesn't dynamically load libraries, I consider it not too big a deal.
--
Stephen Touset
ste...@touset.org