How to Hack Time, With C2PA


By David Buchanan (aka retr0id), 2nd October 2026

The most spectacular hacking stunt from cinema historical past comes from Kung Fury (2015), by which Hackerman hacks time itself. He makes use of this energy to appropriate historic misdeeds. But what would I do with the flexibility to hack time? Personally I’m extra afraid of the butterfly impact, so I’d simply return just a few hours to inform myself the successful lottery numbers.

As it occurs, that is precisely what I did, in accordance with the cryptographically unforgeable C2PA metadata of this picture:

Yes, you’ll be able to inform it is photoshopped. I’m not attempting to do precise lottery fraud right here.

You can confirm the C2PA metadata together with the timestamp at https://verify.contentauthenticity.org/ (when you’re studying this sooner or later, possibly they’ve launched mitigations).

You can affirm that these are the successful lottery numbers, proven hours earlier than the draw time, at https://www.euro-millions.com/results/28-08-2026.

A typical C2PA manifest accommodates two signatures. The first is the “declare” signature, and within the case of a digital camera app the declare may be one thing like “this can be a captured {photograph}, taken at these GPS coordinates, right now” (besides expressed extra formally, per the C2PA spec).

In my previous article I confirmed that the declare signature is roughly nugatory, and we will signal no matter claims we like (at the least, we will within the case of flagship C2PA implementations just like the Google Pixel Camera app).

But there’s often a second signature, from a Time Stamp Authority (TSA), and this one is extra fascinating. We do not belief units to inform their very own time, so as a substitute a distant server is consulted, through the RFC 3161 protocol. The server sends again a signature that asserts “sure, I noticed this hash at this timestamp”, and this response is embedded into the C2PA metadata. As lengthy as we belief that the server is not misbehaving, this proves that the information being signed existed at-or-before the desired timestamp. The TSA acts like an impartial witness.

For the Pixel 10, Google decided that units can in truth be trusted to inform their very own time. I’ve not evaluated their “on-device trusted time-stamp” implementation but, however I’m extremely sceptical of it.

Despite this, on this article we is not going to be attacking the TSA: we assume it capabilities as marketed.

If the TSA mechanism is safe, how are we going to hack time?

We’re going to make use of my favorite bug class: the spec footgun.

The footgun is as follows: C2PA permits for arbitrary “exclusions”. These are byte ranges inside the file that are excluded from signature calculations. Yup. Really. This is already recognized (it is actually within the spec), however for some motive no person’s executed something about it but.

In truth, Dr. Neal Krawertz explicitly known as it out in his “Big Bulleted List” of C2PA flaws printed June 2025:

  • Large exclusion vary. The manifest usually excludes a really massive byte vary from the
    signatures. Any excluded bytes will be altered with out detection.

The solely unique approach right here is {that a} malicious signer can intentionally use a big exclusion vary, somewhat than merely doing so by the way. We can exclude your complete file, to supply a completely legitimate signature over an empty string. This permits the file to be tampered with after the very fact, with out invalidating the signature, and with out invalidating the TSA’s timestamp proof.


Time standing: Hacked

So I actually did take an image of a lottery ticket, and fasten a legitimate C2PA signature with a legitimate trusted timestamp. But I crafted the manifest to exclude the entire file, permitting me to photoshop it (poorly) after the numbers had been introduced, with out invalidating any of the signatures.

Using c2patool -d to dump the manifest of my PoC file, we will see the vital half:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
"c2pa.hash.knowledge": {
  "exclusions": [
    {
      "start": 0,
      "length": 3995383
    }
  ],
  "identify": "jumbf manifest",
  "alg": "sha256",
  "hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
  "pad": []
},

3995383 is the size of your complete file, and 47DE...uFU= is the hash of an empty string:

$ openssl sha256 -binary /dev/null | base64
47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=

The declare signature is over that hash, and the timestamp signature is over the declare signature. We’re successfully signing nothing in any respect, however as of as we speak all of the C2PA verification instruments I can discover do not flag something as uncommon.

Not simply! Sure, it is trivial to detect when the total file has been excluded and report it as invalid, however what if solely a small half is excluded? How do you inform whether or not it is one thing innocent, or one thing that would fully change the looks of the picture if modified? (See MD5 hash collision PoCs for examples of the latter).

My first draft of this put up ended right here with “My suggestion is that the exclusion characteristic must be excluded from the C2PA spec,” but it surely’s not that easy!

The essential motive exclusions exist within the first place is that sure file codecs successfully require it. For instance in PNG files, every chunk has a CRC32 checksum, which must be corrected after the signature has been embedded into the file. This would create a round dependency, except the CRC32 is excluded from the signature’s protection (ignoring intelligent mathematical tips that would keep away from invalidating the CRC).

With that in thoughts I believe the suitable answer right here is to fastidiously and explicitly specify which components of a file are allowed to be excluded, for every supported file format, and require that verifiers implement these constraints.



Source link