ProofMode

Simple C2PA for Mobile: Content Credentials To Go!

06 December 2023

Today we would like to share our recent efforts and progress in bringing important capabilities for media file provenance and authentication on mobile devices through the C2PA standard. Our new Simple C2PA project builds upon the powerful C2PA Rust SDK to provide an easy solution for mobile developers to utilize. This library provides straight-forward methods for a camera or media app to add signed C2PA actions, claims, and assertions to media files. It also includes support for generating a private key and self-signed x509 certificate entirely locally on the device.

Many thanks to Darren Clarke for the perseverence and recent breakthroughs on this, and the core c2pa-rs team for the impressive work on that library. Rust is definitely ‘the way’.

The Coalition for Content Provenance and Authenticity (C2PA) addresses the prevalence of misleading information online through the development of technical standards for certifying the source and history (or provenance) of media content. Adobe and other contributors created the C2PA Rust SDK as part of the Content Authenticity Initiative and released it to open source in June, 2022. Another term used to describe this area of work is Content Credentials, which definitely is easier to say and explain!

Simple C2PA is still very much stable alpha/early beta work, and is it the process of being reorganized a bit on the interface front. However, it does function as expected, and can be used today for initial development and testing. We are moving fast to ship a stable release, and integrate it into our production ProofMode apps.

Where to begin

To start, you can view the src/lib.rs file for the current set of capabilities we have implemented. You can also see our example tests to see the full set of capabilities. Here is a quick sample of our approach, in this case using a locally generated key and self-signed certificate.

let root_certificate = create_root_certificate(None, None).unwrap();
let content_credentials_certificate =
    create_content_credentials_certificate(Some(root_certificate.clone()), None, None)
    .unwrap();
...

let file = FileData::new(None, Some(file_data), Some(file_name.clone()));
let app_info = ApplicationInfo::new("SampleApp".to_string(), "1.0.0".to_string(), None);
let cc = ContentCredentials::new(content_credentials_certificate, file, Some(app_info));
cc.add_created_assertion().unwrap();

Of course, where the keys and certs come from, how you store them securely, and who trusts them is all up to you and your particular implementation. For our use in ProofMode, we wanted to give the user the ability to be able to instantly start using C2PA without requiring a centralized authority, and thus supporting self-signed certificates was an important capability.

The library supports any of the media types supported by the core C2PA-RS library, which is quite a few these days. In our testing, it works great with JPEG and MP4 videos, and we are already experimenting with HEIC images, as well as AAC and M4A audio formats.

Using the Android Library

Thanks to the amazing UniFFI project, we are able to generate bindings for the core Rust API in Kotlin and Swift. This is how we’ve made the Android library available.

To use it, first add our Maven repository to your project:

allprojects {
	repositories {
    	...
		maven {
			url = uri("https://gitlab.com/api/v4/projects/51891540/packages/maven")
		}
       	...
    }
}

Then, import the simple-c2pa library, using whatever the current latest tagged release is. You may also need to include the Java Native Access (JNA) library.

implementation("info.guardianproject:simple-c2pa:0.0.13")
implementation("net.java.dev.jna:jna:5.13.0@aar")

For Android, we have already begun integrating this into our proofmode-android app. You can view our C2paUtil helper class and see methods like initCredentials and addContentCredentials.

Here is some sample Android Kotlin code:

var userCertType = CertificateType.ContentCredentials("ProofMode-User", CERT_VALIDITY_DAYS)
var userCertOptions = CertificateOptions(
    userKey,
    userCertType,
    rootCert,
    "[email protected]",
    "0xmyidentitykey"
)

userCert = createCertificate(userCertOptions)
...
val appLabel = getAppName(mContext)
val appVersion = getAppVersionName(mContext)
var appIconUri = APP_ICON_URI
var appInfo = ApplicationInfo(appLabel,appVersion,appIconUri)

var contentCreds = userCert?.let { ContentCredentials(it,mediaFile, appInfo) }

if (isDirectCapture)
    contentCreds?.addCreatedAssertion()
else
    contentCreds?.addPlacedAssertion()

contentCreds?.embedManifest(fileImageOut.absolutePath)

Using the iOS Library

Add the SimpleC2PA Swift package in Xcode with the repository URL

 https://gitlab.com/guardianproject/proofmode/simple-c2pa

Here is some sample Swift code:

let rootCert = try! createRootCertificate(organization: nil, validityDays: nil);
let contentCert = try! createContentCredentialsCertificate(rootCertificate: rootCert, organization: nil, validityDays: nil)
let fileData = FileData(path: imagePath, bytes: nil, fileName: filename)
let cc = ContentCredentials(certificate: contentCert, file: fileData, applicationInfo: nil)
try! cc.addCreatedAssertion()
try! cc.embedManifest(outputPath: outputPath)

You should also keep an eye on our Proofmode for iOS Project, as we will be merging and releasing an update with simple-c2pa integrated soon.

Testing with Verify

The screenshot below shows a sample (intentionally black) image enhanced with Simple C2PA on Android, and verified and displayed by the Content Credentials Verify Tool. We use this tool both for testing our library, and also as a guide to understand how various assertion may be displayed to a typical user.

Simple C2PA screenshot

In our ProofMode Android app, we give the user controls of what metadata is generated for their image or video, including whether or not to include Content Credentials. We also provide an experimental option to embed C2PA AI Training and Machine Learning related assertions to media files to be used for generative AI purposes.

ProofMode Android screenshot

Tell us what you think!

We would love to hear from anyone who finds this interesting and/or useful. You can contact us many ways or find us on the CAI Discord in the Rust room! Also please feel free to file feature requests, bug reports, and other useful input on the various git project trackers