17 ms·
I know this opinion won't be popular, and I know encryption is a very complex topic, but ... TLS is simply vastly too complicated. How many of us here could wri
by byuu 11y ago
I know this opinion won't be popular, and I know encryption is a very complex topic, but ... TLS is simply vastly too complicated. How many of us here could write a TLS library even if we wanted to? So you end up with code so complex that even the smartest people can barely understand it, let alone debug it, and you get terrifyingly long CVE lists like for OpenSSL as a result.
Compare that to a basic unencrypted HTTP server, which you can write in ~10KiB of code. Complexity breeds these kinds of problems as a natural consequence.
I do know that verifiability is significantly easier than all of this (signatures; hashing), but it's quite possible there is no simpler solution for the secrecy aspect of TLS. I certainly wish there was more support for HTTP+integrity, for those who didn't need the secrecy component. These constant CVEs in every TLS library put our servers at risk in cases where secrecy simply isn't necessary.
- quonn 11y ago> Complexity breeds these kinds of problems as a natural consequence. But the bugs described are not complex - they are local problems that can be understood by just reading one function. The problem here is not complexity, but size (not enough people spend enough time to review all of the code) and the fact that the library is written in a language with manual memory management and unsafe memory access. > I do know that verifiability is significantly easier than all of this (signatures; hashing), but it's quite possible there is no simpler solution for the secrecy aspect of TLS. In this case, the affected component was related to the identity part (certificates), which are needed for verifiability. It was not directly related to secrecy.
- byuu 11y ago> the library is written in a language with manual memory management and unsafe memory access. C's simplicity is certainly a blessing and a curse. Right now, I'm of the opinion that C++ is the best we've got, even if not perfectly ideal. RAII, shared pointers and smart containers with bounds checking allows you to keep nearly all of the performance without the drastic downsides of tracing garbage collectors (obscene amounts of memory usage, nasty stalls, etc.) And when you get into the really high-level languages (Python, Ruby), they simply don't scale. Everyone's darling right now is Rust. I still think it's too early in its life to know how it'll play out (hot new languages follow a predictable path of gaining negative baggage and shortcomings as they increase in real-world usage), but I guess we'll see. Maybe it will indeed be a great panacea to these issues. > In this case, the affected component was related to the identity part (certificates), which are needed for verifiability. It was not directly related to secrecy. Sure, but I'm generalizing here. I can (and did) write a SHA256 hashing algorithm in 3KiB of code. Combined with a package gist updater (these use signing with local keys for updates), that's enough to secure binary package downloads on the BSDs over plain-text HTTP. Surely we can come up with a less complex system for verification alone. Something akin to signify, perhaps. I know that doesn't solve how to universally handle anonymously verifying public key authenticity, but surely we can make something less complex than the clusterfuck that is TLS and the CAs. Yet it doesn't seem there's much, if any, interest in even trying. Everyone has hitched their wagons to HTTP/2 and mandatory TLS; which to me feels like a huge step backward by means of making tech vastly more complex.
- Tepix 11y agoBuilding a system for verification alone seems like a bad idea. You end up with something like DNSSEC and then there's no easy way to add privacy later on.
- riffraff 11y ago> And when you get into the really high-level languages (Python, Ruby), they simply don't scale. I think you need to qualify what "scale" means in this context. Otherwise java is, for all its warts, more or less as high level as ruby and python, and it's probably been proven to scale up (to big machines, or many developers) reasonably well.
- taspeotis 11y agohttp://martinfowler.com/articles/lmax.html http://martinfowler.com/articles/lmax.html > The system is built on the JVM platform ... in fact they ended up by doing all the business logic for their platform: all trades, from all customers, in all markets - on a single thread. A thread that will process 6 million orders per second using commodity hardware
- royjacobs 11y agoTo be fair, one of the ways they achieved this is by using off-heap memory which needs to be handled in a way similar to how a C allocator would handle it.
- byuu 11y agoJust as a random example: https://www.reddit.com/r/programming/comments/3p6r2v/i_wrote_a_c_preprocessor_in_python_its_25_times/ https://www.reddit.com/r/programming/comments/3p6r2v/i_wrote... I've constantly had similar experiences. I tried to write the GUI portion of my programs with Python and PyGTK. I needed to write a simple function that scaled up a bitmap from 256x224 to 512x448. A nearest-neighbor pixel doubler with no interpolation, color conversion, or anything else. It ended up running at around 30fps with nothing but the scaling, on a Core i7-2600k processor. And when I asked for help in optimizing it, nobody could really improve the Python, and they recommended I write "the slow parts" in C as a shared library, and invoke that from the Python GUI. It's okay to be 10%, 30% or even 50% slower than C. But to be 2500% slower or more is completely unacceptable for production code. That level of performance only works on websites with small amounts of traffic, or on the simplest of applications. The root problem here is of course dynamic typing. That makes scaling both performance and code size much more challenging. Java is certainly vastly better, but the garbage collection and its stalls, wasteful memory usage (I've seen our production servers bog down with Tomcat eating up all the RAM on the server for simple programs), and overall extreme negatives of the language itself (no unsigned integers, limited to single inheritance, terrible support for generics [maybe this has changed recently?], etc), plus the legal issues that Oracle is saddling the language with, make it an unacceptable alternative. C# might have been better if Microsoft ever cared about any platform other than Windows. Both dynamic typing and garbage collection are the wrong ways to solve the problems of C. Rust is the closest I've seen to addressing the real problems, but it coming from Mozilla (with their terrible record with Firefox), and the syntax being so radically different from C, I think will chase a lot of people off.
- Phemist 11y agoAs far as http+integrity goes: Integrity checks are also based on a shared secret, see https://en.wikipedia.org/wiki/Hash-based_message_authentication_code https://en.wikipedia.org/wiki/Hash-based_message_authenticat.... So for http+integrity, without the secrecy aspect of TLS, ie the hmac key being public, it would be trivial to generate your own valid integrity hash.
- wolf550e 11y agoPublic hmac key is same as posting hash of iso next to the ISO on ftp severs without gpg signature of the hash. No protection at all.
- byuu 11y agoI'm not the right person to design the entire system, obviously. But as a starting point, I'd consider using a PGP signing key on responses from a server. Your keys would be hosted on an HTTPS server somewhere. Let's say httpi.org or something. signify also looks really promising. Get the key down to the size of a QR code, and you could separate the issue of signing from signature validation entirely ... post it on your HTTPS Twitter feed, put it on your business card, whatever. I think it would be a positive step to get users to think about how they are verifying integrity themselves and the sources they trust. You could even have a dozen sources and let there be a little button in the URL bar to show you which sources agree on a public key provided by a server.
- masklinn 11y agoIs it TLS specifically or X509 (both by itself and because it uses ASN.1)? I dimly remember X509 and ASN.1 being commonly criticised for their complexity, does TLS pile on additional complexity or just inherit it?
- viraptor 11y agoIt's everything. ASN.1 is complex - people still make mistakes in the DER parsers as seen in this CVE. X509 is even more complex - it's not just ASN.1. It can be DER in DER in DER (parameters of certificate extensions). Have fun with that and memory ownership! (you have to recalculate and replace an object 2 levels above what you're actually changing) TLS is even worse, because it includes X509 as a format and then a ton more of actual processing logic, state machines, cryptography code, ... I don't trust any implementation of it that uses unmanaged code. (yes, pretty much assuming everything based on openssl will be broken time and time again)
- alricb 11y agoIn this case it's definitely ASN.1; the problem is that "objects" are defined with OIDs, which are sequences of integers (called arcs numbers) like { 1 2 840 113549 1 }. The first integer is always 0, 1 or 2, and with 0 or 1, the second is between 0 and 39. But the other integers can be arbitrarily large, and it's important not to overflow: https://www.viathinksoft.de/~daniel-marschall/asn.1/oid_facts.html#chap7 https://www.viathinksoft.de/~daniel-marschall/asn.1/oid_fact... You need to use some sort of bignum function if you want to display large arc numbers in decimal. Which is what OpenSSL and LibreSSL do, and that involves creating and destroying BIGNUM objects. The problem is that someone in LibreSSL moved the free() to outside the loop body handling the arc numbers while they were cleaning up. So only the last BIGNUM used gets freed. Oh, did I tell you that arc numbers are encoded in base 128, with the first bit of every octet used to signal whether it's the last octet of that arc number? Because they are.
- masklinn 11y agoWell these are ASN.1 facts I did not need to know and I would like to not subscribe to that mailing list, but regardless thank you for the explanation.
- MichaelGG 11y agoThis doesn't seem to be a case of a complicated spec causing a logic error. Just another case of a memory unsafe language in action. So it's more an issue of people wanting fast, runtime-free, portable code, and being OK with the security implications C brings in exchange. (A TLS lib written in Rust might eventually be an answer, maybe.)