Shopify / ejson

EJSON is a small library to manage encrypted secrets using asymmetric encryption.
MIT License
1.35k stars 62 forks source link

Go implementation #13

Closed burke closed 9 years ago

burke commented 9 years ago

I'd PR this, but it has no code in common with the previous ruby implementation, so it wouldn't provide a whole lot of value.

Instead, see https://github.com/Shopify/ejson

Highlights:

I'll keep poking at this over the next couple of days, but it's basically ready for feedback. The code is pretty well compartmentalized and documented; I don't think it'll be very hard to grok what's going on. Start with README.md, then ejson.go and cmd/ejson/*.go.

Review/cc any combination of: @Shopify/stack, @Shopify/secops. It can easily wait until BFCM if you're busy.

mutemule commented 9 years ago

Implements EJSON v1.0 RFC except with nacl/box instead of PKCS7

:heart:

I am a huge fan of NaCl, and quite wary of the PKCS standards.

EiNSTeiN- commented 9 years ago

djb :100:

burke commented 9 years ago

I added manpages which are installed with the debian package and vendored with the rubygem (unfortunately rubygems can't install manpages globally). ejson help, ejson help encrypt, etc., will now launch man for the relevant manpage.

eapache commented 9 years ago

What happens if you try to encrypt:

"_starts_with_an_underscore": {
  "no_leading_underscore": "123123123123123123123"
}

I'm assuming it does the simple thing, and encrypts the value anyways, I'm just wondering if that's the nicest behaviour or if it should at least be documented?

burke commented 9 years ago

@eapache it's not in the manpage, but it is in README.md: https://github.com/Shopify/ejson/tree/go-impl#format (see point 6). I'll add it to ejson.5.

burke commented 9 years ago

(I want to err on the side of encrypting too much rather than too little, so this is the behaviour I want, though I'm open to argument on that point)

eapache commented 9 years ago

:+1: to explanation and documenting it

burke commented 9 years ago

https://github.com/Shopify/ejson/commit/61c5d48cb697255bc5f02a29fa5304670dde2f01

burke commented 9 years ago

Also fun: http://shopify.github.io/ejson/

sirupsen commented 9 years ago

@burke any plans to add schemas to the Go version?

burke commented 9 years ago

Yeah, but I plan to do that in a separate codebase, probably just a gem that plugs in to rails. There's no reason that bit has to clutter the ejson codebase.

eapache commented 9 years ago
burke commented 9 years ago
  1. :+1:, will change.
  2. That's just there because Go doesn't really support implicitly rewriting a file with the current mode. I have to fetch the current mode and pass it to ioutil.WriteFile, that's all.
  3. I hadn't really factored that into my threat model, but it's probably worth thinking about. I'll do something a little smarter.
  4. That error is directly displayed to CLI users so I wanted the message to be specific, but it would be nice to embed the old err.Error() into the new error string. Will do.
burke commented 9 years ago

Actually, I think it's unreasonable to prevent traversal here: The only input value is the keydir, which is allowed to be anywhere on the system.

I made the other two changes.

eapache commented 9 years ago

The only input value is the keydir, which is allowed to be anywhere on the system.

The other input is the key; is there an escalation where a user can generate a fake public key to escape the key-dir?

burke commented 9 years ago

I don't think so; if they do, they've found a bug in printf's %x formatter, not so much in ejson. I don't personally feel we need to be quite that defensive. I like the train of thought though, that hadn't occurred to me.

eapache commented 9 years ago
burke commented 9 years ago
  1. Done; I just moved that printf up to the cmd/ejson package.
  2. Surprisingly, with all the type assertions you need to accomplish it the read-manipulate-dump way in Go's type system, this method is actually simpler -- though I'll take another run at trying to simplify that code this afternoon.

Also, I really like that the current system preserves the input formatting. Explicit ordering would interfere with semantic grouping, might put _public_key in a weird place in the file, and would just generally violate user expectations.

I'll try to make the json stuff better, but I don't think there's a better option than the scanner.

eapache commented 9 years ago
eapache commented 9 years ago
eapache commented 9 years ago

Lots of minor comments, but on the whole I really like this, :+1:

burke commented 9 years ago
eapache commented 9 years ago

especially when reading from /dev/random is so trivial. Thoughts?

It is, I think, the only thing keeping the library part here from being cross-platform (making the whole thing cross-platform would also require ripping out the man-page bits). Security-specific discussion has been taken offline.

burke commented 9 years ago

I replied to your email, but TL;DR: It's not the hugest of deals but I figured I'd do it right.

burke commented 9 years ago

I have no real desire to support this on Windows, so I don't feel too bad about reading from /dev/* directly in that regard.

sirupsen commented 9 years ago

I'll take a look at this, this is cool.

burke commented 9 years ago

Back to crypto/rand: https://github.com/Shopify/ejson/commit/629edb0e177a5b230f5b6357dcfb1e8ea3177139

burke commented 9 years ago

To summarize our discussion offline, /dev/urandom is fine but Go's PRNG is not. Go will use /dev/urandom on linux, and probably only falls back to the bad implenetation on Windows and maybe plan9.

sirupsen commented 9 years ago

First of all, it's a nicely commented and structured project. Good job!

Few comments reading through it:

With this, I'm not sure I'm seeing how schemas could be built on top of it in a reasonable way where everything isn't encrypted?

burke commented 9 years ago
burke commented 9 years ago

Also, it's probably worth pointing out that gojson is actually the builtin encoding/json library, only with some lowercase letters made uppercase to expose the scanner API.

eapache commented 9 years ago

Also, it's probably worth pointing out that gojson is actually the builtin encoding/json library

...from some unspecified point in the past. Better than something hand-rolled I guess, but still a bit icky. Alas.

burke commented 9 years ago

...from some unspecified point in the past. Better than something hand-rolled I guess, but still a bit icky. Alas.

Agree on all counts.