6 ms·
Good job releasing your project! It's a cool idea and surprisingly minimalist. That said, I've found a number of cryptographic flaws in the application source.
by vngzs 2y ago
Good job releasing your project! It's a cool idea and surprisingly minimalist. That said, I've found a number of cryptographic flaws in the application source. This should not be used in instances where the encryption is mission-critical.
1) You generate a random key [0] and then feed it into PBKDF2 [1] to generate a 32-byte AES-GCM key. If you can generate 32 random bytes instead of 10 reduced-ASCII characters and a key stretch, just do that. PBKDF2 is for turning a password into a key, and it's far from the recommended algorithm nowadays; prefer scrypt if you need to do this sort of thing.
2) AES-GCM with random 12-byte nonces. Never use random IVs with GCM; this breaks the authentication [2] [3]. Given the pitfalls of AES-GCM with respect to random nonces, you might prefer switching to XSalsa20+Poly1305. The advantage of XSalsa is it has an extended nonce length, so you can use random nonces without fear.
3) Random key derivation with a restricted character set can make brute force attacks easier. You should have a 256-bit random key, and if you want that key to be within a certain character set, then encode the byte output from the CSPRNG using that character set.
4) 1fps achieves symmetric key distribution via a URL with a fragment identifier ("#") which IIRC is not sent to the server. Therefore it assumes you have a secure key distribution channel - the link contains the key, so it's important that only the intended recipient can view the part after the "#". If the server is truly malicious, it can deploy client-side Javascript to send the fragment to the server, allowing the server to access the key (and thus cleartext communication).
[0]: https://github.com/1fpsvideo/1fps/blob/main/1fps.go#L99 https://github.com/1fpsvideo/1fps/blob/main/1fps.go#L99
[1]: https://github.com/1fpsvideo/1fps/blob/main/1fps.go#L287 https://github.com/1fpsvideo/1fps/blob/main/1fps.go#L287
[2]: https://eprint.iacr.org/2016/475.pdf https://eprint.iacr.org/2016/475.pdf
[3]: https://soatok.blog/2020/05/13/why-aes-gcm-sucks/ https://soatok.blog/2020/05/13/why-aes-gcm-sucks/
- RomanPushkin 2y agoThat's pretty cool and this is exactly why I am here :) To have this kind of advice. I'll implement these changes as soon as I can.
- mass_and_energy 2y agoThis is such a healthy interaction, it makes me so happy to see people lifting each other up like this
- Teknomancer 2y agoLove to see things like this on HN.
- vngzs 2y agoYou will still need to get the nonce and key generation right, but I'd recommend using Golang's nacl/secretbox [0] for a project such as this. It's designed to be relatively misuse-resistant compared to using underlying primitives directly, and under the hood it's XSalsa20+Poly1305 - so you can use random nonces with negligible collision risk. [0]: https://pkg.go.dev/golang.org/x/crypto/nacl/secretbox https://pkg.go.dev/golang.org/x/crypto/nacl/secretbox
- red0point 2y agoI feel like there are so many pitfalls when designing this - is there something standard and trusted (would TLS work?) that you could build your application on top of?
- yyyfb 2y agoI guess TLS has a dependency on the public key infrastructure (eg Let's Encrypt, or whoever issues wifey accepted certs). Which makes end to end encryption between users harder (most of this stuff is intended for server auth and encryption)? But otherwise big +1 not to reimplement crypto when the are alternatives. Another option for secret key stuff might be ssh?
- bawolff 2y agoThere is no requirement to use TLS with webPKI if you are making your own application (not the browser), you can use TLS with custom certificate mangement. You still need to figure out how you handle trust and key authentication somehow, but that is true of all cryptographic protocols.
- dathery 2y agoIt would be hard to do end-to-end TLS (where the server proxies the raw connection) because (a) you can't share one TLS connection to the host between multiple clients; if you wanted multi-client support while preserving end-to-end TLS, the host would need to maintain a TLS connection with each client and waste bandwidth re-uploading the same image (b) there is no client software requirement, so you would have to do the TLS decryption clientside in the browser (maybe via WASM) unless you're OK with having viewers download software
- beltsazar 2y ago> there are so many pitfalls when designing this Agree. When people hear the adage "don't roll your own crypto", they often think it refers to crypto primitives only. In reality, it's also hard to design a secure crypto protocol, even if the underlying crypto primitives are secure.
- 2y ago
- MoonObserver 2y ago> Never use random IVs with GCM; this breaks the authentication [2] [3]. Given the pitfalls of AES-GCM with respect to random nonces, you might prefer switching to XSalsa20+Poly1305. The advantage of XSalsa is it has an extended nonce length, so you can use random nonces without fear. Those papers are a bit over my head. Could you please explain what's wrong with using random IVs here? What should we do instead (assuming we can only use GCM, and not switch to chacha)
- jszymborski 2y agoNot an expert, but this is my understanding. 1. It is necessary for nonces to never be re-used for a given key lest you open yourself to a certain class of attacks that can decode all messages using that key. This is specific to AES-GCM due to how it internally reuses nonces. 2. AES-GCM uses very small nonces, making the probability of randomly using the same nonce unacceptably as the number of messages encoded with a given key increases (as it would with each frame sent on 1fps). You can avoid all this by using a different primitive with a longer nonce such as XSalsa (a version of Salsa with a 192-bit nonce)
- conradludgate 2y agoThere's two issues. Background: the key+IV define a keystream which is xor-ed against the message. The same key+IV generate the same keystream. Thus you can XOR two cipher texts and reveal information from the two plaintext. AES-GCM is authenticated encryption. To combat known-ciphertext-attacks, you want to have authenticated cipher texts. AES-GCM specifically is vulnerable to an attack with a reused IV to recover the authentication key. Allowing you to forge authentication tags and employ a KCA. The solution, if you're stuck with aes, is to switch to XAES-GCM or better AES-GCM-SIV. Alternatively you must use a counter or checkes system to not reuse IV. Since this is in the context of 1fps, you could use unix timestamp + random bytes to reduce the chance of collisions.
- hatsunearu 2y agoIs the statement just that if you use a random value for a nonce rather than some guaranteed never-used-once value, it's possible to get a collision faster than the "natural" block collision complexity (half block size or something like that)?
- lulzury 2y agoThank you for sharing this and recommending XSalsa20+Poly1305. I have always been interested in cryptography, so learning about the many ways why one shouldn't roll their own crypto AND protocol is very cool. Out of curiosity, is the primary reason you don't recommend fixing the nonce issue in this specific case due primarily to the pitfalls in doing so or is it more nuanced and related to the general issues mentioned in the articles above? A naive perspective could be that one uses AES-GCM because it is used in so many places, such as TLS or SRTP, and someone who is not very well versed in cryptography assumes it can be the way to go.
- vngzs 2y agoAES-GCM has more issues than merely the nonce reuse in the context of random nonces. For instance, the short tag issue[0] leaks authentication (not encryption) keys after a probabilistic "forged" message. In general, the move in modern cryptography engineering is to assume the end user does not know what they are doing. For GCM, you have to get the nonces right and you need the right tag length, and the design uses lookup tables so it's prone to timing attacks in many implementations. Later on I didn't just recommend an algorithm but a specific implementation (at least if we can find a better method of symmetric key distribution): nacl/secretbox [1]. This is a cryptographic library designed to be misuse-resistant, a property of cryptographic designs that makes implementation errors more difficult. nacl is a few years behind the curve inasmuch as it arguably gives the end-user too much control over key generation, but it permits random nonces (being based upon XSalsa) and provides a simple API that is difficult to mess up. AES-GCM is secure with a correct implementation, but to build a correct implementation you often need to know the specific library inputs and configuration settings to produce your desired outcome. Something like secretbox doesn't give you those options: you get one relatively secure configuration ... and that's it! [0]: https://csrc.nist.gov/csrc/media/projects/block-cipher-techniques/documents/bcm/comments/cwc-gcm/ferguson2.pdf https://csrc.nist.gov/csrc/media/projects/block-cipher-techn... [1]: https://pkg.go.dev/golang.org/x/crypto/nacl/secretbox https://pkg.go.dev/golang.org/x/crypto/nacl/secretbox
- NotPractical 2y agoDo you have a recommendation to address #4? That seems like an intrinsic problem for web apps, see also ProtonMail.
- deleted 2y ago[deleted]
- vngzs 2y agoYou're very right! Luckily, we can resolve the vulnerability in this instance, although it's a challenging problem to resolve in general webapps. The technical explanation for our issue is that the client-side Javascript in our webapp is trusted. To quote the late Ross Anderson [0, pg. 13], "a trusted system or component is one whose failure can break the security policy." In this case, our security policy is that the server must not be capable of viewing our screenshots. Our goal is to make that trusted Javascript more trustworthy: that is, closer to a system that can't fail. We're at an advantage in this case: there's an open-source application on GitHub with eyeballs[1] on it that users must run on their endpoint machines. Given that we already have source-available local code running, we could instead serve the UI from the local Go application and use CORS[2] to permit access to the remote server. If the local application is trustworthy, and we're only sending data (not fetching remote Javascript), then the local client UI is trustworthy and won't steal your keys. If users run binaries directly from 1fps (as opposed to building from source), then you would want some multi-party verification that those binaries correspond directly to the associated source [3]. Protonmail is almost surprising: it's supposed to be end-to-end encrypted, but it's not end-to-end encrypted in the presence of a malicious server. If, say, a government order compelled Protonmail to deploy a backdoor only when a particular client visited the site, most users would be unaffected and the likelihood of discovery would be low. [0]: https://www.cl.cam.ac.uk/~rja14/book.html https://www.cl.cam.ac.uk/~rja14/book.html [1]: https://en.wikipedia.org/wiki/Linus%27s_law https://en.wikipedia.org/wiki/Linus%27s_law [2]: https://stackoverflow.com/a/45910902 https://stackoverflow.com/a/45910902 [3]: https://en.wikipedia.org/wiki/Reproducible_builds https://en.wikipedia.org/wiki/Reproducible_builds
- refulgentis 2y ago
- somat 2y agoWith regard to point 4 (secure key distribution channel), as far as I can tell there is no good pki built into the browser, My point being. any pki tooling has to be shipped by the server and you have to trust the server to supply you honest tools. The saving grace is that this does not really matter and each domain could send you totally broken tools and only be able to steal keys produced for their domain. footnote: there are client side certs, however because there is no tooling for them built into the browser usability sucks, I want to try to get public key auth working on my toy js application and the browser tooling for user generated keys sucks. I am tempted to use ssh keys(I like ssh keys), but will probably see if I can get hoba working. https://datatracker.ietf.org/doc/html/rfc7486 https://datatracker.ietf.org/doc/html/rfc7486 I got all excited about hoba when I first read about it, but am now a bit bitter when as found out that there is zero internal browser support.
- ww520 2y agoThis is an excellent analysis! It's amazing what can be found with a minimal source code review.
- icanhasjonas 2y agoCame here to point out the PBKDF use in each frame but found this fantastic write up
- sensanaty 2y agoAny tips on how/where one can learn more on these topics? I find cryptography fascinating, but whenever I've tried looking for some resources on my own, they all flew hilariously above my head, with dozens of acronyms and terms I've never even heard of before even as a native English speaker.
- catoc 2y ago"Never use random IVs with GCM; this breaks the authentication" Why could one not use Encrypt-then-HMAC and HMAC-then-Decrypt with a random IV ? (Serious question. It definitely sounds like you know what you are talking about, I just can't see what I am missing here)