I don't know what "being a stream" has to do with anything (you should virtually always use "stream" modes of AES); the meaningful distinction between CBC and GCM is that GCM authenticates the ciphertext, so you can't tamper with it.
Also I checked the code quickly, they do Cbc-hmac, and they check the Mac before decrypting so it seems fine.
The 1000 rounds only of pbkdf2 on something that's essentially going to be available without any access control (since the encryption is the access control here) might be more annoying as the password can be human generated.
... if the API provided is correctly designed, and either the language made it practical to design the API in a misuse-resistant way /or/ the programmer was actually careful and used it properly.
We both know it's way more likely the problem in your actual system is "Oops, we use the bogus plaintext here despite the validation error" than "Dastardly enemy cryptographers have made a breakthrough in cryptanalysis to attack our product".
I'm not thinking very hard about it; there is just never a reason to use unauthenticated encryption modes. When I wrote that comment, I hadn't even looked to see if they'd manually authenticated their ciphertext (spoiler alert: you can guess).
SubtleCrypto (Web Cryptography API) will simply throw an exception if the authentication fails for AES-GCM, so there's no way to even get at the bogus plaintext.
I think you might be referencing that the incorrect use of CBC leads to chosen-plaintext attacks, chosen-ciphertext attacks, or padding oracle attacks. GCM is AEAD, providing ciphertext authentication. [1]
For those reasons that you mention, use of encryption should always have a design review.
In fact an incorrect implementation of CBC mode famously caused a vulnerability in Microsoft's ASP.NET in 2010 (https://learn.microsoft.com/en-us/security-updates/securityb...). The margin for error is small and even subtle mistakes or incorrect design can cripple security. Even Microsoft got it wrong once (although they handled remediation very well).
Or... you can have a more nuanced viewpoint and note that CBC is really, really, really easy to implement, and _really_ doesn't fall into that category of discussion.
The reason you don't implement your own block ciphers is because side-channel attacks are damn near impossible for normal programmers to understand. Especially timing attacks.
But block-modes of operation? Some of them are really easy. I've ever heard of a bad implementation of CBC causing a security bug.
-------
I'd say you shouldn't implement your own GCM mode. GCM is quite complex, and the Galois Field's authentication bits could be side-channeled if you don't know what you're doing.
CBC? Where's the flaw? Its so stupid simple I don't think that even a novice would make a critical error.
You keep saying "the Galois Field" as if that was a thing. It's GCM. The components of GCM are CTR mode and the GMAC authentication code, which is based on GHASH. If you're afraid of Galois fields, you don't get to use AES at all! Nobody should be implementing any of these primitives themselves, very much including CBC, which, as you saw downthread, left both you and the author of this project with an insecure cryptosystem.
Vulnerabilities in CBC systems were for a long time during the 2000s the most common crypto vulnerabilities on the Internet. There are more things that go wrong with CBC mode than just forgetting to authenticate it!
> You keep saying "the Galois Field" as if that was a thing
You're kidding, right? You've never looked at how GCM-mode works? The entire set of math is inside of the GF(2^128) field. That's why its called a Galois Counter Mode.
I don't think anyone should be implementing their own GCM mode. Its very subtle and potentially full of traps. CBC on the other hand is pretty dumb and simple, and surprisingly secure and robust
> Vulnerabilities in CBC systems were for a long time during the 2000s the most common crypto vulnerabilities on the Internet. There are more things that go wrong with CBC mode than just forgetting to authenticate it!
If they're so common, you shouldn't have much of an issue naming one such vulnerability.
The math used in AES (Rijndael) utilize operations in GF(2^8) tho, so you're doing operations using Galois fields whether your utilizing GCM or CBC. I don't really see how adding the GCM mode utilizing GF(2^128) on top is significantly more difficult or error prone than implementing the AES block cipher itself. You should still be familiar with operations over Galois fields regardless if you've for some reason (foolishly imo) decided you want to implement AES cryptographic primitives on your own.
Regardless there's no good reason not to use a vetted open source implementation instead, preferably with an even higher level of abstraction so your not having to worry about ciphers or modes of operation at all[1].
The library used in this Javascript widget has AES already implemented, but not GCM mode.
> Regardless there's no good reason not to use a vetted open source implementation instead, preferably with an even higher level of abstraction so your not having to worry about ciphers or modes of operation at all[1].
I think that's generally the preferred solution, yes.
It's a CBC padding oracle, intrinsic to the operation of CBC --- if you PKCS7-pad some other mode, you do not get the same attack --- the single best-known cryptographic vulnerability on the Internet, and the parent commenter took the time to give you the most famous instance of it. For the record: that's also not the only CBC vulnerability.
The padding is a key part of using a block cipher in CBC mode.
I’m not sure why you’re ferociously defending the practice of implementing your own cryptography. It’s well known that this is a horrible idea for good reason.
> Furthermore, padding oracles are completely irrelevant to data at rest, like as described in this topics use case. So it really is a bit of a non sequitur too.
That's not true and extremely dangerous to say. In an offline, black-box scenario no server is needed for a padding-oracle. You are thinking of a side-channel oracle. A padding-oracle attack can absolutely be feasible in many cases.
I appreciate your efforts at actually elevating this discussion. Yes, I said something too general when I really was just trying to describe _this_ particular HTML-page encryption implementation.
You're right that its possible that an offline decryption algorithm could in fact be a padding oracle under the right scenario. But I still posit it probably doesn't apply to this static-HTML page generator.
As the old quote goes - "if you are typing "AES" into your code at any point, and you are not a world-renowned crypto expert - you will get this wrong, guaranteed".
There are so few cases of people who are not seasoned crypto engineers getting everything 100% correct that it's basically a myth, and in crypto, getting things "almost right" is the same as getting them wrong...
I too loved playing with crypto - read a ton of books, attended some crypto classes in University, implemented some crypto systems which I thought were secure, etc. - but nowadays I wouldn't dare use anything that isn't considered secure by a large audience unless I had extremely good reason to do so.
Because CBC mode is easier to implement, you'll find it in far more libraries. And honestly, if your underlying block-cipher is secure (that's the hard part: where your side-channels all exist), then CBC mode is really the easy part and can be safely implemented yourself. It really is that simple.
-----------------
CBC doesn't have authentication. So add on an HMAC. Done. It takes up a few more bytes but that's not a big deal these days.
So use WebCrypto, instead of the cabinet of curiosities that is crypto-js. (Or, better yet, don't do stuff like this at all, because a browser window is simply an awful setting for serious cryptography).
If you're talking about sending these files around via email/messenger, most browsers treat localhost as a secure context, so this doesn't seem like that significant of a limitation.
If you are serving out an encrypted HTML page insecurely, your users are already hosed, because someone on the path could inject a script that sends the password to evil[.]com when they type it in.
Mostly because we have a bloody simple use case in this topic.
HTML uses some Javascript to encrypt a file. Then later, the Javascript decrypts the file and returns it to normal.
This is a "beginner level" cryptography situation. Yes, I know there's all sorts of traps all around the field of cryptography. But I also know that this particular use case is simple enough that beginners can try their hand at it, and probably make something useful. And with low-probability of a critical error.
-------------
Don't write your own AES-GCM implementation. Don't write your own TLS1.2 implementation. Etc. etc. There's all kinds of subtle errors involved. IVs, Padding, side-channels, man-in-the-middle... more than I can count and very subtle to think about.
The fact that this subthread has gone down a rabbit-hole of hypotheticals that are _COMPLETELY IRRELEVANT_ to the use-case discussed in this github is proof enough. The community is a bit rabid over its "advice" on this subject.
> The fact that this subthread has gone down a rabbit-hole of hypotheticals that are _COMPLETELY IRRELEVANT_
I see what you’re saying, but the fact is that these hypotheticals are not irrelevant. They’re important intricacies and potential trip mines associated with implementing your own encryption.
There are a myriad of encryption libraries that have been implemented, reimplemented, and redesigned by various hackers.
In any case, I think reimplementing CBC is absolutely beginner level as far as implementation is concerned. Yes, you can be tripped up by various _uses_ of CBC, but the failure modes are extremely well studied at this point.
Of course, a proper AEAD implementation would avoid that. But AEAD is commonly established today with GCM, which is not beginner level. So now we're trapped. What am I supposed to tell a young programmer who is interested in playing around with encryption on their own?
Perhaps you wish to stop anyone from studying that subject. But on the contrary, I think the only way a programmer can truly learn this stuff is to implement the easiest stuff and try it out themselves from the ground up.
--------
The _proper_ advice, is... don't write your own production encryption. But... if you have to, stick with the simplest implementation that avoids the most common errors (side channels, timing attacks, etc. etc.), and focus on the simplest use cases that have the largest amount of history.
Of course, there's an entire class of crypto-bugs these days are found at the higher levels, in the "use of encryption" (ex: SSL3.0, TLS1.0, TLS1.1, etc. etc.). Nonce reuse, IV generation, in-advertent side channels due to padding oracles, etc. etc.
Even a "perfect" implementation of CBC will come across these crypto-bugs (and is why modern algorithms do focus on AEAD from the ground up these days, which largely avoids the problem).
So yes, there are a lot of traps and footguns in the world of encryption. But that's true of programming in general. Eventually, someone will want to make their own encryption, maybe the library doesn't work out just right (as is in this case: the Crypto-library doesn't have GCM mode implemented), and other modes need to be used. The use of CBC seems to be done properly here for static-HTML encryption.
> What am I supposed to tell a young programmer who is interested in playing around with encryption on their own?
Tell them to stop if they’re trying to do it for anything real, or do it as a toy protect that never sees the light of day. And if they select the latter, then they may as well try GCM.
Tell them to leave encryption writing to the professionals.
This entire subthread started because the github repo here used CBC mode (which was supported by the original writer's crypto library), rather than GCM mode (which was unsupported).
We're well deep into a "professional" discussion about the pros and cons of particular implementation details of cryptography.
------------
Go back to the top. Look at the Github code. See that it uses a crypto-library. What should have the original writer have done differently?
The answer is absolutely not "write their own implementation of GCM". They chose correctly: using a well known, well supported CBC mode of operation with AES. (And IMO, _IF_ CBC mode were unsupported, the correct move would have been to write CBC themselves, as it is far less complex than GCM, which includes GHASH and other such side-channel issues).
There's context to everything. From my understanding of this current situation, the CBC choice was perfectly valid.
This GCM sideshow is a consequence of the project using crypto-js, which is not fit for purpose. If your cryptography library doesn't support any AEADs, replace it with one that does. This is a browser project, so all it actually needs is WebCrypto. The whole discussion on this thread has been super weird. Don't ever encrypt with non-authenticated cipher modes.
You're misleading a lot of people with poor comments about implementation vs. design correctness. Design of systems that use crypto requires a specific kind of attention to detail.
Thanks for the feedback! We had an issue opened around that topic where it seems to me that the weak points of CBC do not apply in the context of StatiCrypt. If you have more thoughts on this I'd love to hear them.
As a newer dev later in life, I love to learn about inter-disciplinary snobbery/riffing. I learned some of what I know from a full stack dev, who was convinced anyone who couldnt do everything "was shit" and "should be something easier like a web developer or IT guy" instead. I'm excited to learn that pure disciplines also look down on full stack devs
https://security.stackexchange.com/questions/184305/why-woul...
(also, use the built-in WebCrypto API instead of the crypto-js package)