4 ms·
Firstly, great writing. Secondly, magic proxies are awesome. And pyca/cryptography instead of something terrible like pycryptodome! All great stuff. Some criti
by lvh 7y ago
Firstly, great writing. Secondly, magic proxies are awesome. And pyca/cryptography instead of something terrible like pycryptodome! All great stuff.
Some critique of the crypto bits, since I'm a crypto person.
1. Do you actually need asymmetric cryptography for this? It seems like at some point the proxy has full authority, and it could just encrypt the token for you symmetrically? (This is valuable because symmetric crypto is a lot less precarious than asymmetric crypto, see next point)
2. Please don't use PKCS1v15 padding for encryption in new systems. It's been known to be busted for about 20 years now. We have workarounds, and they may well be deployed in the exact context you're using it. But they keep breaking, because we just have them to keep the infinite amount of already-deployed software running, not because we think it's fundamentally fixable. This is also the textbook example of a vulnerable service: one that takes ciphertexts and decrypts them on demand. With PKCSv15, I can modify the ciphertext so that _the way you treat the modified ciphertext_ tells me something about how to make private key operations. And in this setup, that means I get the real token, so that sounds bad. The good news is that you've successfully designed around it by adding a signature, so I don't think it's mountable... but. Please, no more PKCS1v15 :-(
3. It feels a little awkward to use JWT for the outside signature but not the inside encryption. But less JWT is a good thing :)
Concrete suggestion: use Fernet (you're already using pyca/cryptography) or libsodium's secretbox and then all of the crypto problems go away. You keep the security engineering dilemma of stateful v stateless proxy (do I want the real token in the proxy at all?) -- but that's another argument.
- theacodes 7y agoThis great feedback. I'm definitely not a crypto expert. I'm happy to update the post with a different padding algorithm if you want to suggest one. I'm a little hesitant on swapping out RSA because I intentionally picked something relatively simple and familiar to folks, but yeah, will still do some research. Others had suggested ECC which I think is totally worth noting in the post one way or another. Thank you!
- lvh 7y agoThe answer to your question is OAEP but I feel like I'd still be doing you a disservice there because I am convinced the answer ought to be box/secretbox or Fernet or AESGCM maybe -- but that hinges on my question about asymmetric cryptography which is elsewhere in the thread :)
- theacodes 7y agoOkay, it's updated to use OAEP and PSS padding. Thank you!
- theacodes 7y agoOh, and we use asym because it's useful for us to be able to inspect the token (and see stuff like it's permissions and expiration client side). I only kinda mention this a bit later, but I might make that a bit clearer.
- porker 7y agoThank you for a superb response! If the length of the token was important, and you wanted to issue the shortest possible (yet secure) token: what would you recommend? I looked at Fernet but the ciphered text is... massive.
- lvh 7y agoYou mean massive in general not relative to the encrypt+sign-JWT combo detailed in the blog post? Any kind of encryption is going to make the ctext be effectively random bits, and is going to add a MAC tag that's some number of bits wide, and introduce some randomization (IV or nonce). You can tweak the size of some of those, but I feel the biggest cost you're paying is probably the b64 encoding. What are you encapsulating this thing in? An HTTP response?
- porker 7y agoYes in general, not the JWT version. I was thinking in terms of issuing API tokens like this, and how the longer they are, the more room for copy and paste errors. SHA256 has been a good length to provide to people, and encrypting real text is going to make it longer than that; but do some ciphers require less padding? Changing the encoding to say b85 will help.
- zimmerfrei 7y ago>> And pyca/cryptography instead of something terrible like pycryptodome! pycrypto is terrible. The pycryptodome fork fixes most problems in it. Also, maybe worth sharing you are listed as fourth contributor [1] to the cryptography library, and your web book is prominent on the project homepage, so this piece of opinion may be biased. >> Concrete suggestion: use Fernet Please don't. Don't use boutique protocols with informal specs and without test vectors generated by a sufficient number of independent implementations. Stick to RFC-backed protocols. Use JWT with rigid parameters. Even other cryptography author states that just supporting JWT and not Fernet would have been better [2]. [1] https://github.com/pyca/cryptography/blob/master/AUTHORS.rst https://github.com/pyca/cryptography/blob/master/AUTHORS.rst [2] https://github.com/pyca/cryptography/issues/2900 https://github.com/pyca/cryptography/issues/2900
- lvh 7y agoI'm not super interested in debating 'zimmerfrei but for everyone else: no, I don't think you should use a library that randomly slaps copyright headers of the fork author on source files [0] and introduces C implementations of MD5 in 2018 [1]. I do think it's ironic that they suggest sticking to RFC'd specs with many competing implementations while defending a project with no mandatory code review, mostly 1 author, and currently failing CI :) [0]: https://github.com/Legrandin/pycryptodome/commit/8675e6f03fc6e12e723467567f3d6d9cd3b0b884 https://github.com/Legrandin/pycryptodome/commit/8675e6f03fc... [1]: https://github.com/Legrandin/pycryptodome/commit/87c2d6aedb3ada1a4729122e4c49441c761680ba https://github.com/Legrandin/pycryptodome/commit/87c2d6aedb3... The number of cryptographers willing to do hours and hours of free, often thankless, open source work is pretty small, so no, I'm also not going to write up a disclaimer every time I tell someone to use a library. Of course I'm going to work on the projects that I think are doing the right thing.