[HN Gopher] Psychic Signatures in Java
       ___________________________________________________________________
        
       Psychic Signatures in Java
        
       Author : 19870213
       Score  : 287 points
       Date   : 2022-04-19 21:09 UTC (2 days ago)
        
 (HTM) web link (neilmadden.blog)
 (TXT) w3m dump (neilmadden.blog)
        
       | pluc wrote:
       | Not a good few months for Java
        
       | tptacek wrote:
       | This is probably the cryptography bug of the year. It's easy to
       | exploit and bypasses signature verification on anything using
       | ECDSA in Java, including SAML and JWT (if you're using ECDSA in
       | either).
       | 
       | The bug is simple: like a lot of number-theoretic asymmetric
       | cryptography, the core of ECDSA is algebra on large numbers
       | modulo some prime. Algebra in this setting works for the most
       | part like the algebra you learned in 9th grade; in particular,
       | zero times any algebraic expression is zero. An ECDSA signature
       | is a pair of large numbers (r, s) (r is the x-coordinate of a
       | randomly selected curve point based on the infamous ECDSA nonce;
       | s is the signature proof that combines x, the hash of the
       | message, and the secret key). The bug is that Java 15+ ECDSA
       | accepts (0, 0).
       | 
       | For the same bug in a simpler setting, just consider finite field
       | Diffie Hellman, where we agree on a generator G and a prime P,
       | Alice's secret key is `a mod P` and her public key is `G^a mod
       | P`; I do the same with B. Our shared secret is `A^b mod P` or
       | `B^a mod P`. If Alice (or a MITM) sends 0 (or 0 mod P) in place
       | of A, then they know what the result is regardless of anything
       | else: it's zero. The same bug recurs in SRP (which is sort of a
       | flavor of DH) and protocols like it (but much worse, because
       | Alice is proving that she knows a key and has an incentive to
       | send zero).
       | 
       | The math in ECDSA is more convoluted but not much more; the
       | kernel of ECDSA signature verification is extracting the `r`
       | embedded into `s` and comparing it to the presented `r`; if `r`
       | and `s` are both zero, that comparison will always pass.
       | 
       | It is much easier to mess up asymmetric cryptography than it is
       | to mess up most conventional symmetric cryptography, which is a
       | reason to avoid asymmetric cryptography when you don't absolutely
       | need it. This is a devastating bug that probably affects a lot of
       | different stuff. Thoughts and prayers to the Java ecosystem!
        
         | DyslexicAtheist wrote:
         | > Thoughts and prayers to the Java ecosystem!
         | 
         | some very popular PKI systems (many CA's) are powered by Java
         | and BouncyCastle ...
        
           | nmadden wrote:
           | BouncyCastle has its own implementation of ECDSA, and it's
           | not vulnerable to this bug.
        
         | na85 wrote:
         | >infamous ECDSA nonce
         | 
         | Why "infamous"?
        
           | Dylan16807 wrote:
           | I'm not particularly knowledgeable here, but I know it's
           | extremely fragile, far beyond just needing to be unique. See
           | "LadderLeak: Breaking ECDSA With Less Than One Bit of Nonce
           | Leakage"
        
           | SAI_Peregrinus wrote:
           | It's more properly called 'k'. It's really a secret key, but
           | it has to be unique per-signature. If an attacker can ever
           | guess a single bit of the nonce with probability non-
           | negligibly >50%, they can find the private key of whoever
           | signed the message(s).
           | 
           | It makes ECDSA _very_ brittle, and quite prone to side-
           | channel attacks (since those can get attackers exactly such
           | information.
        
             | Mindless2112 wrote:
             | There's an easy fix for that though -- generate k
             | deterministically using the procedure in RFC6979 [1].
             | 
             | [1]
             | https://datatracker.ietf.org/doc/html/rfc6979#section-3.2
        
             | dilippkumar wrote:
             | > If an attacker can ever guess a single bit of the nonce
             | with probability non-negligibly >50%, they can find the
             | private key of whoever signed the message(s).
             | 
             | This doesn't seem right. Why wouldn't someone guess a bit
             | 0, see if the recovered message makes sense, and if it
             | doesn't, then try bit 1?
             | 
             | It would make the entire scheme useless no? Am I missing
             | something?
        
               | Thorrez wrote:
               | I think they have to get the bit repeatedly and then
               | combine the biased signatures together mathematically to
               | get the key.
        
             | drexlspivey wrote:
             | That makes no sense, how can you get the private key from
             | knowing 1 bit of the nonce?
        
               | tptacek wrote:
               | See, cryptography engineering is sinking in!
               | 
               | Here you go:
               | 
               | https://toadstyle.org/cryptopals/62.txt
               | 
               | What's especially great about this is that it's very easy
               | to accidentally have a biased nonce; in most other areas
               | of cryptography, all you care about when generating
               | random parameters is that they be sufficiently (ie, "128
               | bit security worth") random. But with ECDSA, you need the
               | entire domain of the k value to be random.
        
               | drexlspivey wrote:
               | Ok but for this scheme you need a large amount of
               | signatures from the same biased RNG which makes sense. I
               | thought that the GP was suggesting that you can recover
               | the key from one signature with just a few bits.
        
               | tptacek wrote:
               | When these bugs first came into fashion, the "bias" of
               | the RNG was an implementation artifact, not some bug in
               | /dev/random: it was the code you used to fill a bignum
               | uniformly in the size of the nonce. So mentally
               | substitute "same biased RNG" for "same implementation,
               | with same keys".
               | 
               | Yes, the attacks require many signatures. Like the
               | infamous Bleichenbacher RSA attack, which was originally
               | dubbed "The Million Message Attack", in part as a jab at
               | how impractical they were presumed to be, collecting
               | thousands of signatures is often a very realistic attack;
               | for instance, any system that generates signed messages
               | automatically.
        
               | cbhl wrote:
               | "same biased RNG" largely reduces to "I use the same
               | computer to generate all my signatures"; for example see
               | the Debian RNG bug from 2008
               | 
               | and "large amount of signatures" could be "I sign every
               | email I send to a mailing list" or "I use this key to
               | sign some widely distributed software every two weeks"
        
               | na85 wrote:
               | I guess like so:
               | 
               | https://cryptopals.com/sets/8/challenges/62.txt
               | 
               | E: Thomas beat me to it
        
         | Zababa wrote:
         | Thank you for that, that was a great explanation.
        
         | loup-vaillant wrote:
         | Interestingly, EdDSA (generally known as Ed25519) does not need
         | as many checks as ECDSA, and assuming the public key is valid,
         | an all-zero signature will be rejected with the main checks.
         | All you need to do is verify the following equation:
         | 
         |  _R = SB - Hash(R || A || M) A_
         | 
         | Where _R_ and _S_ are the two halves of the signature, _A_ is
         | the public key, and _M_ is the message (and _B_ is the curve 's
         | base point). If the signature is zero, the equation reduces to
         | _Hash(R || A || M)A = 0_ , which is always false with a
         | legitimate public key.
         | 
         | And indeed, TweetNaCl does not explicitly check that the
         | signature is not zero. It doesn't need to.
         | 
         |  _However._
         | 
         | There are still ways to be clever and shoot ourselves in the
         | foot. In particular, there's the temptation to convert the
         | Edwards point to Montgomery, perform the scalar multiplication
         | there, then convert back (doubles the code's speed compared to
         | a naive ladder). Unfortunately, doing that introduces edge
         | cases that weren't there before, that cause the point we get
         | back to be invalid. So invalid in fact that adding it to
         | another point gives us zero half the time or so, causing the
         | verification to succeed even though it should have failed!
         | 
         |  _(Pro tip: don 't bother with that conversion, variable time
         | double scalarmult https://loup-vaillant.fr/tutorials/fast-
         | scalarmult is even faster.)_
         | 
         | A pretty subtle error, though with eerily similar consequences.
         | It _looked_ like a beginner-nuclear-boyscout error, but my only
         | negligence there was messing with maths I only partially
         | understood. (A pretty big no-no, but I have learned my lesson
         | since.)
         | 
         | Now if someone could contact the Whycheproof team and get them
         | to fix their front page so people know they have EdDSA test
         | vectors, that would be great.
         | https://github.com/google/wycheproof/pull/79 If I had known
         | about those, the whole debacle could have been avoided. Heck, I
         | bet my hat their ECDSA test vectors could have avoided the
         | present Java vulnerability. They need to be advertised better.
        
       | ptx wrote:
       | Apparently you have to get a new CPU to fix this Java
       | vulnerability, or alternatively a new PSU.
       | 
       | (That is to say: a _Critical Patch Update_ or a _Patch Set
       | Update_. Did they really have to overload these TLAs?)
        
       | danmur wrote:
       | It's crazy that the check for this was right there in the
       | original code and was obviously missed when porting to Java.
       | Great example of why unit tests are part of the code (and were
       | missing in both in this case).
        
       | lobstey wrote:
       | Not that a lot of companies are using the Java 15+. People
       | generally stick to 8 or 11.
        
         | needusername wrote:
         | I believe Oracle 11 is affected.
        
           | stolsvik wrote:
           | I do not believe so. The "affected list" which includes 11 is
           | for the complete set of the "CPU" - Critical Patch Update.
           | 
           | This specific one was introduced with the rewriting of these
           | parts of the code from C++ to Java, and that happened with
           | Java 15.
        
       | benazzi wrote:
        
       | benazzi wrote:
        
       | cesarb wrote:
       | And once again, you'd be saved if you stayed on an older release.
       | This is the third time this has happened recently in the Java
       | world: the Spring4Shell vulnerability only applies to Java 9 and
       | later (that vulnerability depends on the existence of a method
       | introduced by Java 9, since all older methods were properly
       | blacklisted by Spring), and the Log4Shell vulnerability only
       | applies to log4j 2.x (so if you stayed with log4j 1.x, and didn't
       | explicitly configure it to use a vulnerable appender, you were
       | safe). What's going on with Java?
        
         | KronisLV wrote:
         | > ...the Log4Shell vulnerability only applies to log4j 2.x (so
         | if you stayed with log4j 1.x, and didn't explicitly configure
         | it to use a vulnerable appender, you were safe)
         | 
         | Seems like someone likes to live dangerously: using libraries
         | that haven't been updated since 2012 is a pretty risky move,
         | especially given that if an RCE is discovered now, you'll find
         | yourself without too many options to address it, short of
         | migrating over to the new release (which will be worse than
         | having to patch a single dependency in a backwards compatible
         | manner): https://logging.apache.org/log4j/1.2/changes-
         | report.html
         | 
         | Admittedly, i wrote a blog post called "Never update anything"
         | a while back, even if in a slightly absurdist manner:
         | https://blog.kronis.dev/articles/never-update-anything and
         | personally think that frequent updates are a pain to deal with,
         | but personally i'd only advocate for using stable/infrequently
         | updated pieces of software if they're still supported in one
         | way or another.
         | 
         | You do bring up a nice point about the recent influx of
         | vulnerabilities and problems in the Java ecosystem, which i
         | believe is created by the fact that they're moving ahead at a
         | faster speed and are attempting to introduce new language
         | features to stay relevant and make the language more inviting
         | for more developers.
         | 
         | That said, with how many GitHub outages there have been in the
         | past year and how many other pieces of software/services have
         | broken in a variety of ways, i feel like chasing after a more
         | rapid pace of changes and breaking things in the process is an
         | industry wide problem.
        
           | yardstick wrote:
           | > using libraries that haven't been updated since 2012 is a
           | pretty risky move
           | 
           | I disagree. Some libraries are just rock solid, well tested
           | and long life.
           | 
           | In the case of log4j 1.x vs 2.x, has there been any real
           | motivator to upgrade? There are 2 well known documented
           | vulnerabilities in 1.x that only apply if you use extensions.
        
             | KronisLV wrote:
             | A sibling comment mentions the reload4j project, so clearly
             | someone thought that 1.x wasn't adequate to a degree of
             | creating a new project around maintaining a fork. Can't
             | speak of the project itself, merely the fact that its
             | existence supports the idea that EOL software is something
             | that people would prefer to avoid, even if they decide to
             | maintain a backwards compatible fork themselves, which is
             | great to see.
             | 
             | Here's a bit more information about some of the
             | vulnerabilities in 1.x, someone did a nice writeup about
             | it: https://www.petefreitag.com/item/926.cfm
             | 
             | I've also dealt with 1.x having some issues with data loss,
             | for example, https://logging.apache.org/log4j/1.2/apidocs/o
             | rg/apache/log4... which is unlikely to get fixed:
             | DailyRollingFileAppender has been observed to exhibit
             | synchronization issues and data loss.
             | 
             | (though at least in regards to that problem, there are
             | alternatives; though for the most part EOL software implies
             | that no further fixes will be available)
             | 
             | But at the end of the day none of it really matters: those
             | who don't want to upgrade won't do so, potential issues
             | down the road (or even current ones that they're not aware
             | of) be damned. Similarly, others might have unpatched
             | versions of 2.x running somewhere which somehow haven't
             | been targeted by automated attacks (yet) and might continue
             | to do so while there isn't proper motivation to upgrade, or
             | won't do so until it will be too late.
             | 
             | Personally, i dislike the idea of using abandoned software
             | for the most part, when i just want to get things done - i
             | don't have the time to dance around old documentation, dead
             | links, having to figure out workarounds for CVEs versus
             | just using the latest (stable) versions and letting someone
             | else worry about it all down the road. Why take on an
             | additional liability, when most modern tooling and
             | framework integrations (e.g. Spring Boot) will be built
             | around the new stuff anyways? Though thankfully in regards
             | to this particular case slf4j gives you more flexibility,
             | but in general i'd prefer to use supported versions of
             | software.
             | 
             | I say that as someone who actually migrated a bunch of old
             | monolithic Spring (not Boot) apps to something more modern
             | when the versions had been EOL for a few years and there
             | were over a hundred CVEs as indicated by automated
             | dependency/package scanning. It took months to do, because
             | previously nobody actually cared to constantly follow the
             | new releases and thus it was more akin to a rewrite rather
             | than an update - absolute pain, especially that JDK 8 to 11
             | migration was also tacked on, as was containerizing the app
             | due to environmental inconsistencies growing throughout the
             | years to the point where the app would roll over and die
             | and nobody had any idea why (ahh, the joys of working with
             | monoliths, where even logs, JMX and heap dumps don't help
             | you).
             | 
             | Of course, after untangling that mess, i'd like to suggest
             | that you should not only constantly update packages (think
             | every week, alongside releases; you should also release
             | often) but also keep the surface area of any individual
             | service small enough that they can be easily
             | replaced/rewritten. Anyways, i'm going off on a tangent
             | here about the greater implications of using EOL stuff long
             | term, but those are my opinions and i simultaneously do
             | admit that there are exceptions to that approach and
             | circumstances vary, of course.
        
           | cesarb wrote:
           | > especially given that if an RCE is discovered now, you'll
           | find yourself without too many options to address it, short
           | of migrating over to the new release
           | 
           | Luckily, there's now an alternative: reload4j
           | (https://reload4j.qos.ch/) is a maintained fork of log4j 1.x,
           | so if you were one of the many who stayed on the older log4j
           | 1.x (and there were enough of them that there was sufficient
           | demand for that fork to be created), you can just migrate to
           | that fork (which is AFAIK fully backward compatible).
           | 
           | (And if you do want to migrate away from log4j 1.x, you don't
           | need to migrate to log4j 2.x; you could also migrate to
           | something else like logback.)
        
         | ragnese wrote:
         | Was Spring4Shell Java's fault, or Spring's fault? Log4Shell was
         | obviously (mostly) log4j's fault.
         | 
         | This one, I gather, is actually Java's fault.
         | 
         | It sounds like three unrelated security bugs from totally
         | different teams of developers.
        
           | znep wrote:
           | Spring4Shell is entirely a flaw in Spring, however is
           | somewhat understandable because it was only exploitable due
           | to a new feature in Java (modules) that added new methods to
           | java.lang.Class, which is a very significant change. You
           | could argue the very existence and nature of Java object
           | serialization deserves blame as well, but that gets nuanced
           | quickly.
           | 
           | Modules are also part of the reason why so many folks got
           | "stuck" on java 8.
           | 
           | It is definitely an interesting study in the challenges of
           | trying to make advances in a platform when a lot of the
           | ecosystem is very much in maintenance mode and may not have a
           | lot of eyes on the combination of existing libraries vs new
           | versions of Java.
        
           | brazzy wrote:
           | I think they other two are considered "Javas's fault" because
           | the frameworks they occurred in are so pervasive in the Java
           | ecosystem that you might as well consider them part of the
           | standard library.
        
         | jatone wrote:
         | _gasp_ new code can introduce bugs... whatever will one do?!
        
         | taeric wrote:
         | You make this sound like it is unique to java. I remember
         | heartbleed had similar, in that the lts I was on did not have
         | the vulnerable library.
         | 
         | At some level, as long as releases add functionality, the basic
         | rules of systemantics will guarantee unintended interactions.
        
       | ccbccccbbcccbb wrote:
       | Q: Which type of cryptography is implied to be unsafe in the
       | following sentence?:
       | 
       | "Immediately ditch RSA in favor of EC, for it is too hard to
       | implement safely!"
        
         | tedunangst wrote:
         | What's java's RSA history look like?
        
       | vlowrian wrote:
       | What puzzles me most is that two days after the announcement of
       | the vulnerability and the release of the patched Oracle JDK,
       | there is still no patched version of OpenJDK for most
       | distributions.
       | 
       | We're running some production services on OpenJDK and CentOS and
       | until now there are only two options to be safe: shutdown the
       | services or change the crypto provider to BouncyCastle or
       | something else.
       | 
       | The official OpenJDK project lists the planned release date of
       | 17.0.3 as April 19th, still the latest available GA release is
       | 17.0.2
       | (https://wiki.openjdk.java.net/display/JDKUpdates/JDK+17u).
       | 
       | Adoptium have a large banner on their website and until now there
       | is not a single patched release of OpenJDK available from them
       | (https://github.com/adoptium/adoptium/issues/140).
       | 
       | There are no patched packages for CentOS, Debian or openSUSE.
       | 
       | The only available version of OpenJDK 17.0.3 I've seen until now
       | seems to be the Archlinux package
       | (https://archlinux.org/packages/extra/x86_64/jdk17-openjdk/).
       | They obviously have their own build.
       | 
       | How can it be that this is not more of an issue? I honestly don't
       | get how the release process of something as widely used as
       | OpenJDK can take more than 2 days to provide binary packages for
       | something already fixed in the code.
       | 
       | This shouldn't be much more effort than letting the CI do its
       | job.
       | 
       | Edit: Typo.
        
         | Razhan wrote:
         | Amazon had releases of Corretto available on April 19th,
         | Corretto 17 was released before 10am PDT, less than one hour
         | after the announcement
        
         | gunnarmorling wrote:
         | For folks on RHEL, the java-17-openjdk package for RHEL 8 has
         | been updated: https://access.redhat.com/errata/RHSA-2022:1445.
         | 
         | > The official OpenJDK project lists the planned release date
         | of 17.0.3 as April 19th, still the latest available GA release
         | is 17.0.2
         | 
         | > (https://wiki.openjdk.java.net/display/JDKUpdates/JDK+17u).
         | 
         | I don't think there 17.0.3 ever will be available from
         | openjdk.java.net; there's no LTS for upstream builds, and since
         | Java 18 is out already, no further builds of 17 should be
         | expected there. IMO, this warrants some clarification on that
         | site though.
        
         | ptx wrote:
         | Azul published updated packages yesterday, including for some
         | older non-LTS Java versions:
         | https://www.azul.com/downloads/?package=jdk#download-openjdk
        
           | vlowrian wrote:
           | Thanks for the info! That's very interesting since they
           | usually only provide out-of-cycle critical fixes for their
           | paid tiers. On the other hand - this only proves that it's
           | actually possible to provide a hot-fixed OpenJDK in time.
           | 
           | Unfortunately, I assume that a very common case is just using
           | the distribution provided openjdk-package and configuring the
           | system for auto updates. So the main issue here is that a
           | serious number of systems is relying on the patch process of
           | the distribution to fix issues like this and they are still
           | vulnerable at this moment.
        
             | vips7L wrote:
             | I wouldn't use your distros version of OpenJdk. If you want
             | fast updates, you need to be using Azul or some other
             | provider who is dedicated to it.
        
               | vlowrian wrote:
               | I can see how this would have helped in this case.
               | 
               | As I see it, the distributions are mostly relying on the
               | upstream provisioning of the openJDK project. So if they
               | fix this issue, it shouldn't take long until we see
               | updated packages in all major distributions. This might
               | be a problem specific to the openJDK build process, so a
               | different package source would help in that case.
               | 
               | But as mentioned above, Azul usually doesn't provide out-
               | of-cycle critical fixes without a paid plan. And most
               | people will still use whatever the distribution provides
               | - so this is still an issue regardless of alternative
               | package sources.
               | 
               | And since I assume that many or most running JDK
               | instances actually are coming from the distributions
               | repository rather than an alternative source, and there
               | is literally no outcry regarding the missing packages
               | whatsoever - I fear that there are a lot of vulnerable
               | software systems of people not knowing about it right
               | now.
        
       | RandomBK wrote:
       | Does anyone know why this was only given a CVSS score of 7.5?
       | Based on the description this sounds way worse, but Oracle only
       | gave it a CVSS Confidentiality Score of "None", which doesn't
       | sound right. Is there some mitigating factor that hasn't been
       | discussed?
       | 
       | In terms of OpenJDK 17 (latest LTS), the issue is patched in
       | 17.0.3, which was release ~12h ago. Note that official OpenJDK
       | docker images are still on 17.0.2 as of time of writing.
        
         | tptacek wrote:
         | CVSS is a completely meaningless Ouija board that says whatever
         | the person authoring the score wants it to say.
        
       | m00dy wrote:
        
         | 0des wrote:
         | I want to live in this world, but no.
        
       | [deleted]
        
       | stolsvik wrote:
       | The title of the blogpost is now updated to "CVE-2022-21449:
       | Psychic Signatures in Java" - maybe this HN post could too?
        
         | vemv wrote:
         | Agreed (@dang)
        
       | bertman wrote:
       | The fix for OpenJDK (authored on Jan. 4th 22):
       | 
       | https://github.com/openjdk/jdk/blob/e2f8ce9c3ff4518e070960ba...
        
         | MrBuddyCasino wrote:
         | I spot no test or comment in the code on why this assertion is
         | important.
        
           | bertman wrote:
           | It's literally what the whole bug is about. From OP's
           | article:
           | 
           | >This is why the very first check in the ECDSA verification
           | algorithm is to ensure that r and s are both >= 1. Guess
           | which check Java forgot?
        
             | MrBuddyCasino wrote:
             | Yes I just think it's insane they fixed it without adding a
             | test or comment.
        
         | sdhfkjwefs wrote:
         | Why are there no tests?
        
         | drexlspivey wrote:
         | with commit message "Improve ECDSA signature support" :D
        
           | baobabKoodaa wrote:
           | I'm guessing the commit message is obscured to give people
           | more time to update before it's exploited in the wild.
        
       | tialaramex wrote:
       | This is the sort of dumb mistake that ought to get caught by unit
       | testing. A junior, assigned the task of testing this feature,
       | ought to see that in the cryptographic signature design these
       | values are checked as not zero, try setting them to zero, and...
       | watch it burn to the ground.
       | 
       | Except that, of course, people don't actually do unit testing,
       | they're too busy.
       | 
       | Somebody is probably going to mention fuzz testing. But, if
       | you're "too busy" to even write the unit tests for the software
       | you're about to replace, you aren't going to fuzz test it are
       | you?
        
         | tptacek wrote:
         | The point of fuzz testing is not having to think of test cases
         | in the first place.
        
           | kasey_junk wrote:
           | This is true in principle but in practice most fuzz testing
           | frameworks demand a fair bit of setup. It's worth it!
           | 
           | But if you are in a time constrained environment where basic
           | unit tests are skipped fuzz testing will be as well.
        
           | loup-vaillant wrote:
           | You still need your tests to cover all possible errors (or at
           | least all _plausible_ errors). If you try random numbers and
           | your prime happens to be close to a power of two, evenly
           | distributed random numbers won 't end up outside the [0,n-1]
           | range you are supposed to validate. Even if your prime is far
           | enough from a power of two, you still won't hit zero by
           | chance (and you need to test zero, because you almost
           | certainly need two separate pieces of code to reject the =0
           | and >=n cases).
           | 
           | Another example is Poly1305. When you look at the test
           | vectors from RFC 8439, you notice that some are specially
           | crafted to trigger overflows that random tests wouldn't
           | stumble upon.
           | 
           | Thus, I would argue that proper testing requires some domain
           | knowledge. Naive fuzz testing is bloody effective but it's
           | not enough.
        
             | cliftonk wrote:
             | That's all true, but fuzz testing is very effective at
             | checking boundary conditions (near 0, near max/mins) and
             | would have caught this particular problem easily.
        
               | loup-vaillant wrote:
               | Do you mean fuzz testing does _not_ use even
               | distributions? There's a bias towards extrema, or at
               | least some guarantee to test zero and MAX? I guess that
               | would work.
               | 
               | Also, would you consider the following to be fuzz
               | testing? https://github.com/LoupVaillant/Monocypher/blob/
               | master/tests...
        
               | yencabulator wrote:
               | The usual trick is coverage-guided fuzzing.
               | https://google.github.io/clusterfuzz/reference/coverage-
               | guid...
        
               | dwohnitmok wrote:
               | No, most fuzz testing frameworks I know of these days do
               | not use even distributions. Most use even more
               | sophisticated techniques such as instrumenting the code
               | to detect when state transitions are triggered to try to
               | maximize hitting all code paths in a program instead of
               | repeatedly fuzzing the same path.
        
           | tialaramex wrote:
           | [Somebody had down-voted you when I saw this, but it wasn't
           | me]
           | 
           | These aren't alternatives, they're complementary. I
           | appreciate that fuzz testing makes sense over writing unit
           | tests for weird edge cases, but "these parameters can't be
           | zero" isn't an edge case, it's part of the basic design.
           | Here's an example of what X9.62 says:
           | 
           | > If r' is not an integer in the interval [1, n-1], then
           | reject the signature.
           | 
           | Let's write a unit test to check say, zero here. Can we also
           | use fuzz testing? Sure, why not. But lines like this ought to
           | _scream out_ for a unit test.
        
             | tptacek wrote:
             | Right, I'm just saying: there's a logic that says fuzz
             | tests are easier than specific test-cases: the people that
             | run the fuzz tests barely need to understand the code at
             | all, just the basic interface for verifying a signature.
        
           | solarengineer wrote:
           | If we write an automated test case for known acceptance
           | criteria, and then write necessary and sufficient code to get
           | those tests to pass, we would know what known acceptance
           | criteria are being fulfilled. When someone else adds to the
           | code and causes a test to fail, the test case and the
           | specific acceptance criteria would thus help the developer
           | understand intended behaviour (verify behaviour, review
           | implementation). Thus, the test suite would become a
           | catalogue of programmatically verifiable acceptance criteria.
           | 
           | Certainly, fuzz tests would help us test boundary conditions
           | and more, but they are not a catalogue of known acceptance
           | criteria.
        
           | anfilt wrote:
           | While fuzz testing is good and all, when it comes to
           | cryptography, the input spaces is so large that chances of
           | finding something are even worse than finding a needle in a
           | hay stack.
           | 
           | For instance here the keys are going to be around 256 bits in
           | a size, so if your fuzzer is just picking keys at random,
           | your basically never likely to pick zero at random.
           | 
           | With cryptographic primitives you really should be testing
           | all known invalid input parameters for the particular
           | algorithm. A a random fuzzer is not going to know that.
           | Additionally, you should be testing inputs that can cause
           | overflows and are handled correctly ect...
        
             | tptacek wrote:
             | Yes, but here we're just looking for (0,0).
        
         | hsbauauvhabzb wrote:
         | The issue is the assumption juniors should be writing the unit
         | tests, sounds like you might be part of the problem.
        
           | tialaramex wrote:
           | I think I probably technically count as a junior in my
           | current role, which is very amusing and "I don't write enough
           | unit tests" was one of the things I wrote in the self-
           | assessed annual review.
           | 
           | So, sure.
        
             | hsbauauvhabzb wrote:
             | It's more unit testing is _everybodies_ job, especially
             | complex cryptographic functions, which should really have
             | at least two sets of eyes, or even two test case sets where
             | each developer doesn't see the other developers test cases
             | to reduce the likelihood that positive bias may overlook
             | missed tests.
             | 
             | But i say that as someone who regularly audits code with
             | almost certainly no unit tests based on the quality of the
             | applications, just one set would do me fine.
        
       | [deleted]
        
       | dynamite-ready wrote:
       | Wonder if someone can add a little more info to the title of this
       | story. It's would probably draw more clicks if the title wasn't
       | so cryptic. This is essentially a Java dev infosec post.
        
         | pas wrote:
         | Just wait a few days and it'll be on the news like the log4j2
         | vulnerability :) (Though it might not, because in practice
         | BouncyCastle is used in a most big/old Java software - as far
         | as I know.)
        
       | LaputanMachine wrote:
       | >Just a basic cryptographic risk management principle that
       | cryptography people get mad at me for saying (because it's true)
       | is: don't use asymmetric cryptography unless you absolutely need
       | it.
       | 
       | Is there any truth to this? Doesn't basically all Internet
       | traffic rely on the security of (correctly implemented)
       | asymmetric cryptography?
        
         | fabian2k wrote:
         | I've seen this argument often on the topic of JWTs, which are
         | also mentioned in the tweets here. In many situations there are
         | simpler methods than JWTs that don't require any cryptography,
         | e.g. simply storing session ids server-side. With these simple
         | methods there isn't anything cryptographic that could break or
         | be misused.
         | 
         | The TLS encryption is of course assumed here, but that is
         | nothing most developers ever really touch in a way that could
         | break it. And arguably this part falls under the "you
         | absolutely need it" exception.
        
           | jaywalk wrote:
           | Server-side session storage isn't necessarily a replacement
           | for JWTs. It can be in many cases, but it's not one to one.
           | JWTs do have advantages.
        
             | fabian2k wrote:
             | That's why I wrote "in many cases". The problem is more
             | that for a while at least JWT were pretty much sold as the
             | new and shiny replacement for classic sessions, which
             | they're not. They absolutely have their uses, but they also
             | have additional attack surface.
        
           | [deleted]
        
           | slaymaker1907 wrote:
           | You can still use encryption with JWTs if you use a symmetric
           | key. I believe HS256 just uses a symmetric key HMAC with
           | SHA256. If you go beyond JWT, Kerberos only uses symmetric
           | cryptography while not being as centralized as other
           | solutions. Obviously, the domain controller is centralized,
           | but it allows for various services to use common
           | authentication without compromising the whole domain if any
           | one service is compromised (assuming correct configuration
           | which is admittedly difficult with Kerberos).
        
           | er4hn wrote:
           | The biggest problem with JWTs is not what cryptography you
           | use (though there was a long standing issue where "none" was
           | something that clients could enter as a client side
           | attack...) but rather revocation.
           | 
           | x509 certificates have several revocation mechanisms since
           | having something being marked as "do not use" before the end
           | of its lifetime is well understood. JWTs are not quite there.
        
             | codebje wrote:
             | JWT is just a container for authenticated data. it's
             | comparable to the ASN.1 encoding of an x509 certificate,
             | not to the entire x509 public key infrastructure.
             | 
             | You could compare x509 with revocation to something like
             | oauth with JWT access tokens, though.
             | 
             | In that case, x509 certificates are typically expensive to
             | renew and have lifetimes measured in years. Revocation
             | involves clients checking a revocation service. JWT access
             | tokens are cheap to renew and have lifetimes measured in
             | minutes. Revocation involves denying a refresh token when
             | the access token needs renewing. Clients can also choose to
             | renew access tokens much more frequently if a 'revocation
             | server' experience is desirable.
             | 
             | Given the spotty history of CRLDP reliability, I think
             | oauth+JWT are doing very well in comparison. I'm pretty
             | damn confident that when I revoke an application in Google
             | or similar it will lose access very quickly.
        
               | tialaramex wrote:
               | > x509 certificates are typically expensive to renew and
               | have lifetimes measured in years
               | 
               | In the Web PKI thanks to Certificate Transparency we can
               | measure, the typical X509 certificate was issued by ISRG
               | (Let's Encrypt) and thus cost well under one dollar (free
               | to the subscriber, that cost is borne by the donors) and
               | has a lifetime of precisely 90 days.
        
               | codebje wrote:
               | > In the Web PKI thanks to Certificate Transparency we
               | can measure, the typical X509 certificate was issued by
               | ISRG (Let's Encrypt) and thus cost well under one dollar
               | (free to the subscriber, that cost is borne by the
               | donors) and has a lifetime of precisely 90 days.
               | 
               | Yes, it's true that in the past few years Let's Encrypt
               | has substantially altered the typical lifetime of web
               | server certificates, as well as substantially eased the
               | burden of refreshing a certificate in what I would guess
               | to be the majority of use cases.
               | 
               | Revocation, however, is still a mess. OCSP services are
               | slow and a privacy leak, and are largely ignored by
               | browsers - in 2021 Firefox was still checking OCSP
               | services but given they're so unreliable if it can't
               | contact a service it assumes the certificate is fine.
               | OCSP winds up being a trade-off between allowing an
               | attacker to conduct a denial of service on all
               | certificates or blocking revocations.
               | 
               | In practice the major browser vendors all do more or less
               | the same thing - build their own proprietary list of
               | revoked certificates and distribute it to browsers from
               | time to time, with varying sources and granularity on
               | what they will and won't include in their centralised
               | CRLs. I would have little faith in a timely revocation of
               | a compromised server certificate.
        
               | Sirened wrote:
               | Not to mention OCSP stapling provides a revocation escape
               | hatch that allows a certificate to continue to be used
               | even after it has been revoked and the revocation has
               | been streamed to all relevant OCSP servers.
        
         | Sirened wrote:
         | It's generally good to use symmetric cryptography wherever
         | possible because it usually (!) is faster and simpler. More
         | complex crypto systems provide interesting properties but if
         | you can pull off whatever you're doing without it, why bother.
         | The author tries to make a security claim for this but IMO
         | that's not even the real issue
        
         | lazide wrote:
         | Initial connection negotiation and key exchange does, anything
         | after that no. It will use some kind of symmetric algo
         | (generally AES).
         | 
         | It's a bad idea (and no one should be doing it) to continue
         | using asymmetric crypto algorithms after that. If someone can
         | get away with a pre-shared (symmetric) key, sometimes/usually
         | even better, depending on the risk profiles.
        
           | loup-vaillant wrote:
           | > _It will use some kind of symmetric algo (generally AES)._
           | 
           | AES-GCM, you mean. Let's not forget the authentication in _"
           | authenticated encryption"_. I'm nitpicking, but if a beginner
           | comes here it's better to make it clear that in general,
           | encryption alone is not enough. Ciphertext malleability and
           | all that.
        
             | lazide wrote:
             | Plenty of stuff still uses CBC (or other modes) with
             | another authentication method. AES-GCM is nice in that it
             | combines both explicitly, but a lot of stuff just combines
             | other methods and it's fine.
             | 
             | AES-GCM has the annoying property of output size > input
             | size for instance.
        
               | loup-vaillant wrote:
               | I was just trying to mention the most widespread method.
               | Sure you can use AES-CBC or AES-CTR, and combine it with
               | HMAC or keyed BLAKE2...
               | 
               | but as tptaceck pointed out, all authentication methods
               | are going to increase your message size. It's
               | unavoidable: to get authentication you need some
               | redundancy, and the only general way to get that
               | redundancy is to have a message bigger than the
               | plaintext. We do have attempts at length preserving
               | authenticated encryption, but as far as I know they're
               | not as well studied as the classical "encrypt-then-mac"
               | methods such as AES-CBC + HMAC or AES-GCM.
               | https://security.googleblog.com/2019/02/introducing-
               | adiantum...
        
               | tptacek wrote:
               | All secure encryption has an output size greater than its
               | input size.
        
               | lazide wrote:
               | How so? All symmetric crypto algorithms at their basic
               | level that I am aware of do not change the message size
               | at all. If you have an example, that would be helpful.
               | I'm not referring to padding. If you're referring to IV,
               | then I see what you're saying, but most algorithms derive
               | that from positional data or treat it like a semi-public
               | part of the key, which I'm not referring to.
               | 
               | AES-GCM (as a method) is unusual this way, because it
               | combines encryption and validation at the same time, in
               | each block. They're two steps - you have the cipher text
               | and the validation data separate.
               | 
               | It's encrypting + signing everything, essentially, for
               | each block. It stores the data for it directly in each
               | block, which is why the inflation.
               | 
               | For why this is both great, and terrible depending on the
               | use case - for problem cases, imagine full disk
               | encryption. If you naively encrypt the block using AES-
               | GCM, any block you encrypt will no longer fit in the
               | device. If you encrypt a file (like a database file)
               | which relies on offsets or similar hard coded byte wise
               | locations to data, those no longer work.
               | 
               | In both cases you'd need a virtualization layer which
               | would map logical offsets to physical ones. Definitely
               | not impossible. Not as straightforward as replacing your
               | read/write_blk method with read/write_encrypted_blk
               | though.
               | 
               | As for why it's awesome, it greatly simplifies and
               | strengthens the real world process of encrypting or
               | decrypting data where the size of the input and output
               | are not fixed by some hardware constraint or fixed
               | constant, where you have a virtualization layer, or where
               | you don't need to care as much (or can remap) offsets.
               | Which is often.
        
               | loup-vaillant wrote:
               | > _How so? All symmetric crypto algorithms at their basic
               | level that I am aware of do not change the message size
               | at all._
               | 
               | That's because you are not aware of the importance of
               | authentication.
               | 
               | Without authentication, your system is not secure: an
               | attacker might intercept messages, and modify them
               | _undetected_. The key word here is  "ciphertext
               | malleability". And once they can do that, they can cause
               | the recipient to react in ways it should not, and in some
               | cases the recipient might even leak secrets.
               | 
               | Sometimes (like disk encryption) the size overhead is
               | really really _really_ inconvenient, and the risk of
               | interception is lower, so you break the rule and skip it
               | anyway. But unless you are in a similar situation (you
               | probably aren 't), you must use authentication. It's only
               | professional.
               | 
               | In practice, that means you should use authenticated
               | encryption. Authenticated encryption is used _everywhere_
               | , including HTTPS. And yes, it has a small size overhead.
               | Usually 16 bytes per message, like AES-GCM and RFC 8439
               | (ChaPoly). Per _message_. Not per block. So the actual
               | overhead is very low in practice. And again, it 's the
               | price you have to pay to get a secure system.
               | 
               | ---
               | 
               | Use authenticated encryption.
               | 
               | Accept the overhead like everyone else.
               | 
               | Resistance is futile.
        
               | lazide wrote:
               | Oh I am quite aware.
               | 
               | You do not seem to be aware of the practical constraints
               | around an actual attack like ciphertext malleability in
               | this context, or have thought through how you would
               | implement direct disk encryption on a block device with
               | AES-GCM without, you know, doing block based AES-GCM for
               | individual blocks?
               | 
               | Which is exactly what I was referring to?
               | 
               | For block based, the best way is simple to use a
               | validating filesystem like ZFS on top of whatever block
               | based crypto is being used, if you need random IO. If you
               | don't, a simple fixed size signature (seperate from the
               | data) is sufficient, and out of band is fine.
               | 
               | In either case, including AES-GCM, the validation and
               | authentication is not, itself, the symmetric encryption
               | algorithm. They wrap approved block ciphers which do
               | that.
               | 
               | As per the Standard, anyway. [https://nvlpubs.nist.gov/ni
               | stpubs/Legacy/SP/nistspecialpubli...]
               | 
               | I'm not against AES-GCM, not at all. It's awesome! I'm
               | pointing out that it has implementation tradeoffs.
        
               | tptacek wrote:
               | No matter how you're encrypting, if you're
               | authenticating, you have to store the authenticator.
               | Which is why GCM "expands" the size of the message. If
               | you're not authenticating, you're not encrypting
               | securely.
               | 
               | The fact that XTS isn't authenticated is a huge problem
               | with full-disk encryption.
               | 
               | https://sockpuppet.org/blog/2014/04/30/you-dont-want-xts/
        
               | lazide wrote:
               | You can (and folks do) authenticate in ways that don't
               | make individual blocks bigger.                 And any
               | decent structural validation of the data still makes it
               | reasonably secure even without per-block validation.
               | 
               | GCM is also opened up to different types of attacks due
               | to it's structure. Such as if the data is gone, it may be
               | impossible to figure that out without additional
               | signature or metadata.
               | 
               | Without the correct key for AES, it is exceedingly
               | difficult to construct a value that can result in a
               | successful attack after decryption even for the simplest
               | file systems (as compared to a very visible crash or disk
               | corruption issue even without validation), and that blog
               | post way oversimplifies the actual process. It also makes
               | numerous flat out false statements about many encryption
               | modes.
               | 
               | a trivial answer that solves every one of the attacks
               | mentioned in that blog is using ZFS on top of a encrypted
               | block device.
               | 
               | In each of these cases, for a successful attack, you'd
               | need to generate a new block, or identify an existing
               | block to replace a known block with, that would produce
               | the attackers desired outcome. All GCM does is make it
               | more detectable in the encrypted data if that happens.
               | 
               | Some modes mentioned, if watching the actual disk
               | activity and doing chosen plaintext attacks, it could be
               | possible to shorten the time to recover the underlying
               | volume keys, but that is not helped immensely by GCM
               | (necessarily).
               | 
               | It is going to be obvious in the system itself without
               | the right key if someone tries to swap in a bogus block,
               | because it will be gibberish/corrupt, if it is data used
               | by anything or checked by anything.
               | 
               | AES-GCM just means you can tell when you pick something
               | up, vs when you look at it if it's damaged. And it does
               | it at the trade off of adding a signature on everything.
               | Sometimes that's worth it, sometimes it's not.
        
               | loup-vaillant wrote:
               | > _You can (and folks do) authenticate in ways that don't
               | make individual blocks bigger._
               | 
               | First, name one example.
               | 
               | Second, what do you mean by "individual blocks"?
               | 
               | AES-GCM adds one authentication tag _per message_. A
               | single message may contain millions of AES blocks, and
               | the total overhead of AES-GCM over it will still be a
               | single authentication tag (16 bytes). That makes it very
               | similar to pretty much any authenticated encryption
               | scheme out there.
        
               | lazide wrote:
               | Ah, your second question is a good one, and probably gets
               | to the root of the disagreements.
               | 
               | I was specifically referring to the context of things
               | like block devices. There is no single message (in a sane
               | way, anyway) for the device. Each low level block is the
               | message, in the sense you are referring to. That's when
               | inputsize != outputsize is a problem, as that 'message'
               | is also fixed size.
               | 
               | When I am referring to authenticating in a way that
               | doesn't make individual blocks bigger, I'm referring to a
               | HMAC signature in filesystem metadata or similar in this
               | type of scenario. Out of band information. Practically
               | speaking, even a basic CRC of metadata and file contents
               | would make most attacks impractical.
               | 
               | Which you could do with AES-GCM of course, by storing the
               | tag separately. I currently know of no implementations
               | that do so however, but I'm sure there are ones out
               | there. It would require storing the tag per block, which
               | doesn't sound fun or performant.
               | 
               | To answer your second question in that context -
               | everything from SSL to PGP/GPG, S/MIME, etc.
        
               | tptacek wrote:
               | People have been saying stuff like "even a CRC would make
               | attacks impractical" for decades, and what all they've
               | managed to accomplish is an obstacle course for early-
               | career academic cryptographers. Which, by all means,
               | carry on: it produces great papers, and it's a great way
               | to get new people into the field. But if you care about
               | security, your ciphertext needs to be authenticated.
               | 
               | Which brings me back to: all secure encryption expands
               | the size of the ciphertext. If you're using XTS in a new
               | design, you are doing something very wrong.
        
         | formerly_proven wrote:
         | I wouldn't be particularly worried of someone decrypting a file
         | encrypted in the 80s using Triple DES anytime soon. I don't
         | think I'll live to see AES being broken.
         | 
         | I wouldn't bet on the TLS session you're using to have that
         | kind of half life.
        
           | loup-vaillant wrote:
           | There are two sides to this coin: one is the actual strength
           | of the primitives involved. RSA is under increasingly
           | effective attacks, and though elliptic curves are doing very
           | well for now, we have the looming threat of Cryptographically
           | Relevant Quantum Computers. Still, without CRQC there's a
           | good chance that X25519 and Ed25519 won't be broken for
           | decades to come.
           | 
           | The other side is the protocol itself. Protocols are
           | delicate, and easy to mess up in catastrophic ways. On the
           | other hand, they're also _provable_. We can devise security
           | reductions that prove that the only way to break the protocol
           | is to break one of its primitives. Such proofs are even
           | mechanically verified with tools like ProVerif and Tamarin.
           | 
           | Maybe TLS is a tad too complex to have the same half life as
           | AES. The Noise protocols however have much less room for
           | simplification. That simplicity makes them rock solid.
        
         | smegsicle wrote:
         | if people were getting mad at him, he must have been pretty
         | obnoxious about it because i don't think there's much
         | controversy- Asymmetric encryption is pretty much just used for
         | things like sharing the Symmetric key that will be used for the
         | rest of the session
         | 
         | of course it would be more secure to have private physical key
         | exchange, but that's not a practical option, so we rely on RSA
         | or whatever
        
         | nicoburns wrote:
         | > Is there any truth to this?
         | 
         | Yes, symmetric cryptography is a lot more straightforward and
         | should be preferred where it is easy to use a shared secret.
         | 
         | > Doesn't basically all Internet traffic rely on the security
         | of (correctly implemented) asymmetric cryptography?
         | 
         | It does. This would come under the "unless you absolutely need
         | it" exception.
        
           | adgjlsfhk1 wrote:
           | note that symmetric encryption is also really hard. it wasn't
           | until 2010 or so that GCM mode came around and provided a
           | system that is somewhat easy to implement without
           | accidentally breaking everything.
        
             | 0xdeadb00f wrote:
             | GCM is not without it's own pitfalls though, however.
        
       | lobstey wrote:
       | I doubt how many companies are actually using java15+. Many still
       | sticks to 8 or 11
        
       ___________________________________________________________________
       (page generated 2022-04-21 23:02 UTC)