The internet has been abuzz this week with talk of the so-called “psychic signature” vulnerability in Java. This vulnerability allows an attacker to easily bypass security checks requiring ECDSA signatures. Neil Madden, who discovered this vulnerability, compares this vulnerability to Doctor Who’s “psychic paper,” blank paper that tricks others into seeing valid credentials.
As part of the Sigstore community, we wanted to know: Does the psychic signature vulnerability also affect Sigstore, a code artifact signing and verification project?
The short answer is NO!
The Sigstore infrastructure and Cosign are written in Go. The Go cryptography libraries were not affected by this bug, and furthermore Rekor, the Sigstore transparency log, rejects attempted psychic signatures. In fact, Sigstore actually helps check whether attackers have attempted to exploit bugs like this! The rest of this post illustrates how Sigstore rejects physic signatures and exposes an attacker that attempts to exploit this vulnerability.
Setting the Scene: Sigstore and Psychic Signatures
Sigstore. Sigstore is an OpenSSF project that aims to make signing artifacts (especially the artifacts in the software supply chain) as easy as logging in to your email account—literally. It provides a tool, Cosign, which allows developers to sign container images and other artifacts without managing signing keys. Instead, users use OIDC to log in to the Sigstore infrastructure, which securely associates a temporary signing key with their identity (for instance, their GitHub, Google, or Microsoft account). The component of Sigstore that we’ll be talking about the most today is Rekor, which stores every signature that’s considered valid in the Sigstore ecosystem in a transparency log. To validate a Sigstore signature, you check that the signature is valid, and that it is stored in Rekor.
Because signatures are an essential part of Sigstore, you might worry that the psychic signature vulnerability affects it. To see why this is not the case, let’s first understand at a high level what signatures are and what the vulnerability is.
Digital signatures. When we say “signatures,” we’re referring to digital signatures using asymmetric cryptography. If Alice wants to sign a message, she generates a “key pair” comprising public and private keys. The private key can be used to “sign” the message, producing a “signature.” Bob can then verify this signature using the public key.
ECDSA and psychic signatures. One common implementation of digital signatures is called ECDSA. This uses some mathematical tricks involving arithmetic on an elliptic curve for signing and verification. In particular, an ECDSA signature is two integers, usually called r and s. The verifier checks an equation involving r, s, the public key, and the message. Implementations are supposed to check that r and s are nonzero. However, the Java implementation of ECDSA signature verification skipped this check. See the blog post announcing the vulnerability for a clear in-depth explanation.
Sigstore Shirks Psychic Signatures
Let’s first demonstrate that Rekor rejects psychic signatures. (The full code for this blog post is available on GitHub.) We can make a psychic signature in ASN.1 DER format (which Sigstore uses under-the-hood):
Then, we can use Cosign to attempt to upload a HashedRekord to Rekor:
When we run this, we get an error:
Rekor doesn’t verify the signature because it isn’t vulnerable to this bug. This means that even a vulnerable implementation would reject these signatures, because they aren’t in the log!
Sigstore Surfaces Suspected Shenanigans
Even if Sigstore had been vulnerable to this bug, Rekor makes it simple to scan for attempted exploitation: at any time, we can enumerate all Sigstore signatures up to that point and check whether they’re affected.
Now imagine that the Go implementation of ECDSA signature verification was actually vulnerable to psychic signatures. While the Sigstore team would have patched the main Rekor deployment immediately, you might still wonder if anyone had ever previously attempted to exploit this bug.
We can easily check that! Start with a CSV file containing all Rekor signatures (reach out in the Sigstore Slack if you’re interested in how we got this). In our example format, the file contains one line per Rekor entry: its UUID, its index in the Rekor log, and the entry’s signature:
We can parse each signature, which is a base64 encoding of r and s (the ECDSA signature) in ASN.1 DER format:
Then, looking for psychic signatures is straightforward:
Let’s try it out on the CSV file from before:
Sigstore is not vulnerable to the “psychic signature bug.” In fact, using Sigstore can help detect exploitation of similar bugs. Finally, because Sigstore rejects psychic signatures, even a vulnerable Java implementation wouldn’t have been affected by the psychic signature bug if it also checked that signatures were present in Rekor.