Skip to content

C2PA Ruby Library Release

Published: at 01:30 PM

Ruby + Rust + C2PA

tldr;

I created (with Claude’s help) a Ruby gem to use the native C2PA Rust bindings.

What is C2PA and why should I care?

C2PA is a standard for adding “content credentials” to digital media. Think of it like a tamper-evident label for an image, video, audio file, or document. It does not magically prove that something is true, but it can help show where the file came from, how it was made, and whether its history has been changed or stripped.

As for why you should care: AI-generated media is getting good enough that “just look at it” is no longer a reliable way to know where something came from. As forged images, voices, videos, and likenesses become easier to create, creators and audiences need better ways to establish trust. C2PA is one of the strongest standards we have right now for that trust layer: not by proving that content is “true,” but by giving files a verifiable record of their origin, edits, and provenance.

This is also becoming less theoretical. At Google I/O 2026, Google announced expanded support for verifying C2PA Content Credentials alongside SynthID in products like Gemini, Search, and Chrome. That matters because provenance only becomes useful when normal people can actually see and check it in the tools they already use.

The backstory

About a week ago, I watched a YouTube video from Coffeezilla surrounding AI deepfakes and it immediately got me thinking about how we’re going to be able to trust media in the future.

My initial thought was, “well we already have TLS certificates so why can’t we somehow use those?”. After some initial investigation, it turns out that there is already a mechanism to do this; C2PA. Since Ruby is still my preferred programming language and there wasn’t a library for that out there, I decided to create my own. That said, there is no reason to reinvent the wheel, so I decided to use Magnus to call out to the official Rust C2PA library.

The agentic coding challenge

If you look at the history of the gem on Rubygems, you might notice that I yanked the first version of the gem. This is because my agent of choice (Claude) didn’t understand the assignment and wrote an implementation that didn’t work (I also didn’t like the implementation regardless). 😅 So I yanked that first version and then published a new one after some more focused prompting.

Where to find it

It’s available on Github and of course Rubygems.


Next Post
Using JSON Web Tokens in a Rails API - Part Two