How to Hack Time, With C2PA
By David Buchanan (aka retr0id), 2nd October 2026
The most impressive hacking stunt from cinema history comes from Kung Fury (2015), in which Hackerman hacks time itself. He uses this power to correct historic misdeeds. But what would I do with the ability to hack time? Personally I'm more afraid of the butterfly effect, so I'd just go back a few hours to tell myself the winning lottery numbers.
As it happens, that's exactly what I did, according to the cryptographically unforgeable C2PA metadata of this image:
Yes, you can tell it's photoshopped. I'm not trying to do actual lottery fraud here.
You can verify the C2PA metadata including the timestamp at https://verify.contentauthenticity.org/ (if you're reading this in the future, maybe they've introduced mitigations).
You can confirm that those are the winning lottery numbers, shown hours before the draw time, at https://www.euro-millions.com/results/28-08-2026.
Background
A typical C2PA manifest contains two signatures. The first is the "claim" signature, and in the case of a camera app the claim might be something like "this is a captured photograph, taken at these GPS coordinates, at this time" (except expressed more formally, per the C2PA spec).
In my previous article I showed that the claim signature is approximately worthless, and we can sign whatever claims we like (at least, we can in the case of flagship C2PA implementations like the Google Pixel Camera app).
But there's usually a second signature, from a Time Stamp Authority (TSA), and this one is more interesting. We don't trust devices to tell their own time, so instead a remote server is consulted, via the RFC 3161 protocol. The server sends back a signature that asserts "yes, I saw this hash at this timestamp", and this response is embedded into the C2PA metadata. As long as we trust that the server isn't misbehaving, this proves that the data being signed existed at-or-before the specified timestamp. The TSA acts like an independent witness.
For the Pixel 10, Google decided that devices can in fact be trusted to tell their own time. I have not evaluated their "on-device trusted time-stamp" implementation yet, but I'm highly sceptical of it.
Despite this, in this article we will not be attacking the TSA: we assume it functions as advertised.
It's Time-Hacking Time
If the TSA mechanism is secure, how are we going to hack time?
We're going to use my favourite bug class: the spec footgun.
The footgun is as follows: C2PA allows for arbitrary "exclusions". These are byte ranges within the file which are excluded from signature calculations. Yup. Really. This is already known (it's literally in the spec), but for some reason nobody's done anything about it yet.
In fact, Dr. Neal Krawertz explicitly called it out in his "Big Bulleted List" of C2PA flaws published June 2025:
- Large exclusion range. The manifest typically excludes a very large byte range from the signatures. Any excluded bytes can be altered without detection.
The only new angle here is that a malicious signer can deliberately use a large exclusion range, rather than merely doing so incidentally. We can exclude the entire file, to produce an entirely valid signature over an empty string. This allows the file to be tampered with after the fact, without invalidating the signature, and without invalidating the TSA's timestamp proof.
Time status: Hacked
So I really did take a picture of a lottery ticket, and attach a valid C2PA signature with a valid trusted timestamp. But I crafted the manifest to exclude the whole file, allowing me to photoshop it (poorly) after the numbers were announced, without invalidating any of the signatures.
Using c2patool -d to dump the manifest of my PoC file, we can see the important part:
1 2 3 4 5 6 7 8 9 10 11 12 | "c2pa.hash.data": { "exclusions": [ { "start": 0, "length": 3995383 } ], "name": "jumbf manifest", "alg": "sha256", "hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", "pad": [] }, |
3995383 is the length of the entire file, and 47DE...uFU= is the hash of an empty string:
$ openssl sha256 -binary /dev/null | base64 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
The claim signature is over that hash, and the timestamp signature is over the claim signature. We're effectively signing nothing at all, but as of today all the C2PA verification tools I can find don't flag anything as unusual.
Can it be fixed?
Not easily! Sure, it's trivial to detect when the entire file has been excluded and report it as invalid, but what if only a small part is excluded? How do you tell whether it's something harmless, or something that could completely change the appearance of the image if modified? (See MD5 hash collision PoCs for examples of the latter).
My first draft of this post ended here with "My recommendation is that the exclusion feature should be excluded from the C2PA spec," but it's not that simple!
The main reason exclusions exist in the first place is that certain file formats effectively require it. For example in PNG files, each chunk has a CRC32 checksum, which needs to be corrected after the signature has been embedded into the file. This would create a circular dependency, unless the CRC32 is excluded from the signature's coverage (ignoring clever mathematical tricks that could avoid invalidating the CRC).
With that in mind I think the right solution here is to carefully and explicitly specify which parts of a file are allowed to be excluded, for each supported file format, and require that verifiers enforce these constraints.
