Skip links

Oracle already wins ‘crypto bug of the year’ with Java digital signature bypass

Java versions 15 to 18 contain a flaw in its ECDSA signature validation that makes it trivial for miscreants to digitally sign files and other data as if they were legit organizations.

Cyber-criminals could therefore pass off cryptographically signed malicious downloads and bogus information as if it were real, and affected Java applications and services won’t know the difference.

The scope of the damage that could be done is wide: encrypted communications, authentication tokens, code updates, and more, built on Oracle’s flawed code could be subverted, and as far as vulnerable Java-written programs are concerned, the data looks legitimate and trustworthy.

The blunder was patched this month by Oracle – among more than 500 vulnerabilities addressed by the database giant this quarter – so, as always, update early and update often.

ECDSA stands for Elliptic Curve Digital Signature Algorithm. It uses elliptic curve cryptography, implementations of which have run into a variety of issues over the years.

Although Oracle has only given this latest security weakness (CVE-2022-21449) a severity rating of 7.5 out of 10, security consultancy ForgeRock – which said it became aware of, and privately disclosed, it in November – rates the vulnerability a ten.

Infosec expert Thomas Ptacek already described it as “crypto bug of the year.”

What’s particularly interesting about this issue is that it’s incredibly easy to exploit, and an obvious programming error. The bug was introduced when part of Java 15’s signature-verification code was rewritten from its native C++ into Java itself – including the ECDSA verification code.

To simplify what happened, an ECDSA signature consists of a pair of numbers, referred to as (r, s). To verify a signature, the code performs some math involving a hash (a fingerprint, if you will) of the data, the public key of whichever organization or person digitally signed the data, r, and s; one side of the equation uses r, the other r and s.

Both sides of this computation must equal for the signature check to pass. That would mean the data was digitally signed by the signer’s private key, indicating the data originated from or is approved by the signer. If the signature check fails, that likely means whoever signed the data isn’t who they say they are (as they don’t have access to the secret, private key that corresponds to the given public key) and the data shouldn’t be trusted.

In theory, for a signature to be valid, (r, s) cannot be (0, 0) because some of the math involves multiplying these numbers with other values. The bug arose because the original C++ code checked that both r and s are non-zero, and wouldn’t accept the signature if they were. The new Java code didn’t check, it just went ahead and computed with the values.

You don’t need to know a lot of mathematics to know that anything multiplied by zero equals zero. One part of the calculation involves dividing by s – but, unfortunately, in a way that doesn’t generate an error if you divide by zero.

The upshot is that in the affected versions of the code, anyone who presents a blank signature will be accepted. The normal verification pathway still works fine, which is why this wasn’t noticed two years ago. It just now accepts (0,0), and successfully validates it.

And this is on top of the gazillon remote-code execution flaws, with no authentication needed to exploit, in Oracle’s other products. ®


This flaw has been described by ForgeRock’s Neil Madden as a psychic paper vulnerability, after a plot device from a 2007 Doctor Who episode. Your humble bookish vulture thinks it sounds more like the imp card from A A Attanasio’s 1987 novel In Other Worlds:

You will receive a third and final artifact, an interfacing magnetic plate – an imp. It looks identical to a charge card, only it’s pure white. Insert it into any bank computer system and you will be credited with large sums of real capital.