Sign the manifest
Cryptographically sign the C2PA manifest, proving its authenticity and integrity before embedding it into the image. This ensures that any changes to the manifest can be detected, and the signer’s identity is verifiable.
Inputs
Manifest data – JSON-formatted manifest string (manifest_json) generated in the previous step.
CSC credentials – Client certificate (cert.pem) and private key (key.pem) that identify the signer.
Credential PIN – Secret PIN used to authorize the signing operation via CSC.
Process
Compute a SHA-256 hash of the manifest JSON.
Send this hash to the CSC API along with the credential PIN to request a Signature Activation Data (SAD) token.
CSC verifies the certificate, key and PIN, then returns a signed hash.
This signed hash is used to create a digital signature over the manifest.
Output
Signed manifest hash – A base64-encoded signed hash returned by CSC. This signed hash is ready to be embedded in the image along with the manifest for final content authenticity verification.
Python example
# This script reads a manifest JSON file, computes its SHA-256 hash, sends it to CSC for #...signing using the client certificate, key, credential ID, and PIN, and prints the signed hash #...(SAD). import json import hashlib import base64 import getpass import requests import logging # Configure logging logging.basicConfig(level=logging.INFO) # CSC demo endpoint CSC_BASE_URL = "https://clientauth.demo.one.digicert.com/documentmanager/csc/v1" def get_sad(hash_b64: str, pin: str, credential_id: str, client_cert: str, client_key: str) -> str: """ Request a Signature Activation Data (SAD) token from CSC for signing a hash. """ url = f"{CSC_BASE_URL}/credentials/authorize" payload = { "credentialID": credential_id, "PIN": pin, "hash": [hash_b64], "hashAlgo": "SHA256", "numSignatures": 1 } resp = requests.post( url, json=payload, cert=(client_cert, client_key), headers={"Content-Type": "application/json"}, timeout=10 ) resp.raise_for_status() data = resp.json() return data["SAD" ] def main(): print("=== Sign a Manifest with CSC ===\n") manifest_file = input("Enter path to manifest JSON file: ").strip() client_cert = input("Enter path to client certificate (cert.pem): ").strip() client_key = input("Enter path to client key (key.pem): ").strip() credential_id = input("Enter your credential ID: ").strip() pin = getpass.getpass("Enter your credential PIN: ").strip() # Load manifest with open(manifest_file, "r") as f: manifest_json = f.read() # Compute SHA256 hash of manifest digest = hashlib.sha256(manifest_json.encode('utf-8')).digest() hash_b64 = base64.b64encode(digest).decode('utf-8') logging.info(f"SHA256 hash of manifest (base64): {hash_b64}") # Request CSC to sign signed_hash = get_sad(hash_b64, pin, credential_id, client_cert, client_key) print("\n=== Signed Manifest Hash (SAD) ===") print(signed_hash) if __name__ == "__main__": main()