3 ms·
Cool! I've love to hear more about the security and crypto design. I started writing up some questions but after asking so many it feels like I should just chec
by ketralnis 10y ago
Cool! I've love to hear more about the security and crypto design. I started writing up some questions but after asking so many it feels like I should just check out the code and answer some of them for myself. Still, I left the discussion here in case you're interested :)
I've been working on a similar tool in Rust: https://github.com/ketralnis/secrets https://github.com/ketralnis/secrets. My focus has been less APIs and more person-to-person (e.g. sharing the team's twitter password between humans that need to use it) but I'd love to hear how you've solved some of the conceptual problems that I've struggled with in trying to make it secure.
Some issues that I've struggled with:
1. withstanding attacks on the file format, some of which are described in this paper: https://www.cs.ox.ac.uk/files/6487/pwvault.pdf https://www.cs.ox.ac.uk/files/6487/pwvault.pdf. My answer has been the logging system that I talk about in Auditing below but I'd love to hear how you withstand some of these attacks in your system where it looks like you don't even control the file format (is that mysql?)
2. bootstrapping trust. how do I know I haven't been MitM'd, and how can I avoid having to trust the server? My system has a public/private key for every user, so when I share a password with you I'm encrypting it to your public key. The worst possible case then is that I inject my public key claiming to be you because then I get the passwords instead of you. Preventing this while also allowing for public keys to be rotated after a compromise of a client machine is currently stumping me. My current solution is to keep a record of every public key I've seen before, when I see a new one prompt the user to double check it out-of-band (like SSH does), and to just refuse to ever use a new public key for a user that I've seen before. But I bet that users don't actually check this, just like with SSH. And ideally I wouldn't rely on less secure out-of-band communication channels.
3. And speaking of verification, here's how I'm asking users if everything looks right:
=== secrets.vm ===
common name: secrets.vm
fingerprint: b957e10c998faa9909cff3ba4ec35485d04708c3ecc7481fe14d7f07bc0229cd
public key: c15e697e4807793ef8a9461a7b2c6cf2266d1ec1480a594e83b54e7b75e07702
public sign: f1db594eb55fe97657c57f2aa01afd1210a46d42d80d5552ac4d548162d4968e
mnemonic: AM ROBE KIT OMEN BATE ICY TROY RON WHAT HIP OMIT SUP LID CLAY AVER LEAR CAVE REEL CAN PAM FAN LUND RIFT ACME
does that look right? [y/n]
AFAICT these word-based (it's rfc1751) or sentence based (as recommended by https://www.usenix.org/conference/usenixsecurity16/technical-sessions/presentation/dechand https://www.usenix.org/conference/usenixsecurity16/technical...) are the best we have but do users actually verify these? How do you help your users prove that your server is really your server before they store secrets in it, in a way that they'll actually verify?
4. Auditing. How can I, as an end user or as an admin of the server, prove that the server hasn't been tampered with to inject rogue keys? Right now I have a sketch for a merkle tree type log system where the server (1) logs every action (2) links every "fact" (a key, a secret, a user) to an entry in the log and (3) signs every log entry along with the log entry before it. Then a user can reconstruct the current state of the database to make sure that it matches. The upside is that it's pretty hard to forge, but the downside is that it's prohibitively expensive to verify: you really have to check the whole thing so you don't want that happening every time you retrieve a secret. And there are some tricky bits like making sure that the log doesn't have orphan entries that are easy to get wrong. Do you have a good solution to the auditing problem?
5. Keeping the crypto itself simple and auditable. I use libnacl for the actual crypto and openssl for TLS. I've found that simply writing down every way the crypto is used (https://github.com/ketralnis/secrets/blob/master/DESIGN.md https://github.com/ketralnis/secrets/blob/master/DESIGN.md) that I've found a lot of cases where it was too complicated and likely to be messed up. Finding that out made a big difference to me in how I write it: now I describe it first and then write the code and that has made a huge difference in keeping it simple. I don't see really any documentation on your crypto, how do you know you're doing it right?
- e12e 10y agoFor 2,3 the better approach is probably certificates of some form. Ssh supports certificates as well as plain keys (a key with optional meta-data about validity, principals (users,servers etc). And/or you could use some form of Web of trust model (one could say that a CA system is just a very small, highly trusted wot - typically one key with ultimate trust, that signs all valid certs - as opposed to wot that typically scores a key based on signatures by other (semi-)trusted/known keys). Unfortunately Ca/wot/certs doesn't solve the problem - but it reduces "verify all the keys" and "rotate all the keys" to verify/rotate the key (eg: the key that signs your user cert - if you have a cert, you have a xhain of trust). It does however bring with it "maintain a CA" - which really is less work than "synchronise all the various public keys" but frequently ends up being hard to decentralise. The latter is probably solved by realising better is better and having a few people/principals with signing powers (many priest, not just one bishop) and an audit trail, roll-call/revoke - can be a lot safer than ad-hoc trust-on-first-use.
- voltagex_ 10y ago>Ssh supports certificates as well as plain keys (a key with optional meta-data about validity, principals (users,servers etc). Wouldn't validity and principals be best left to something like LDAP? I still haven't found anything that fits in the gap between "I only have one machine" and "I'm comfortable setting up Active Directory et-al". I like reading about all these systems but I've only got 5 or so machines under my direct control (although something that integrates with AWS would be nice for when I'm doing development work there)
- e12e 10y ago> Wouldn't validity and principals be best left to something like LDAP? Yes and no. Even with easier access to caching etc, ldap can still be rather fragile (no (readable) ldap; no login)[1] In general certificates need to be (proof of) principals (the entity that can prove ownership of the secret key X' corresponding to public key X" is X - where X is a uid (eg: e12e) Or a machine or service (login.example.com). But if your use case is simple, and some meta-data can be readily attached to the certificate, it's easy to add limits on where key X is valid from (source ip/host), have access to (services) and when (time of day) -- and adding an expiry. If policy is max lifetime of a week except for CA keys, then that greatly simplifies revocation lists. Generally "trust only this one CA" is simple, and allows moving capability (largely) to certificates. Centralised, on-line catalogs like LDAP make some things simpler. And there might be a balance: perhaps some basic group info is in the cert - and each service can base policy on that (email login ok 24/7 - certain other services only 8-16 -- although I can't think of a compelling need for the latter right now). [1] Of course one should check for revocations, but with an automated system to mint certificates, one can trade off with hour/day/week lifetimes. There was a recentish show hn: sharkey: https://news.ycombinator.com/item?id=12097992 https://news.ycombinator.com/item?id=12097992