Skip to main content

c2pa-azure-py

Sign files with C2PA content credentials using the Azure Trusted Signing service.

The project ships in two forms from a single codebase:

  • A Python library (c2pa_azure) you can import in your own apps.
  • A standalone CLI (c2pa-azure-sign) you can run from the shell or a container.

Installation

From source

git clone https://github.com/duggaraju/c2pa-azure-py.git
cd c2pa-azure-py
python -m venv .venv
source .venv/bin/activate            # Windows: .venv\Scripts\activate
pip install .                        # add -e for an editable/dev install

As a dependency in another project

pip install c2pa-azure                # once published to PyPI
# or directly from a Git ref:
pip install git+https://github.com/duggaraju/c2pa-azure-py.git

Authentication

Sign in to Azure before running. Any credential supported by DefaultAzureCredential will work (Azure CLI, Managed Identity, environment variables, etc.).

az login
# In WSL or headless environments:
az login --use-device-code

CLI usage

c2pa-azure-sign \
    -i path/to/input.jpg \
    -o path/to/output.jpg \
    -e https://<region>.codesigning.azure.net/ \
    -a <trusted-signing-account> \
    -c <certificate-profile>

Equivalent invocation without an entry-point script:

python -m c2pa_azure -i input.jpg -o output.jpg -e https://... -a acct -c profile

Optional flags:

Flag Description
-m, --manifest Path to a manifest JSON file, or an inline manifest string. Defaults to the bundled manifest.json.
-s, --settings Path to a C2PA settings TOML file.
-f, --force Overwrite the output file if it already exists (default: on).

Library usage

from azure.identity import DefaultAzureCredential
from c2pa import Builder, ContextBuilder
from c2pa_azure import AzureSigner, TrustedSigningClient, TrustedSigningSettings

credential = DefaultAzureCredential()

settings = TrustedSigningSettings(
    certificate_profile="my-cert-profile",
    service_account="my-trusted-signing-account",
    endpoint="https://eus.codesigning.azure.net/",
)
client = TrustedSigningClient(credential, settings)
azure_signer = AzureSigner(client)
signer = azure_signer.to_c2pa_signer()

manifest = """
{
  "claim_generator": "my_app/1.0.0",
  "title": "My Signed Image",
  "assertions": [
    { "label": "stds.schema-org.CreativeWork",
      "data": { "@context": "https://schema.org", "@type": "CreativeWork",
                "author": [{ "@type": "Person", "name": "Jane Doe" }] } }
  ]
}
"""
context = ContextBuilder().with_signer(signer).build()

builder = Builder(manifest, context)
builder.sign_file("input.jpg", "output.jpg")

Loading the bundled manifest

from importlib.resources import files
from c2pa_azure import AzureSigner, TrustedSigningSettings

manifest = files("c2pa_azure.data").joinpath("manifest.json").read_text()

Calling the low-level Trusted Signing client

from azure.identity import DefaultAzureCredential
from c2pa_azure import TrustedSigningClient, TrustedSigningSettings

settings = TrustedSigningSettings(
    "profile", "account", "https://eus.codesigning.azure.net/"
)
client = TrustedSigningClient(DefaultAzureCredential(), settings)
azure_signer = AzureSigner(client)

cert_chain_p7b = client.get_certificate_chain()
signature = azure_signer(b"<data to hash and sign>")

Invoking the CLI from Python

from c2pa_azure.cli import main

exit_code = main([
    "-i", "input.jpg",
    "-o", "output.jpg",
    "-e", "https://eus.codesigning.azure.net/",
    "-a", "my-account",
    "-c", "my-cert-profile",
])

Docker

docker build -t c2pa-azure .
docker run --rm \
    -v "$PWD:/data" \
    -e AZURE_CLIENT_ID -e AZURE_TENANT_ID -e AZURE_CLIENT_SECRET \
    c2pa-azure \
    -i /data/input.jpg -o /data/output.jpg \
    -e https://<region>.codesigning.azure.net/ \
    -a <account> -c <certificate-profile>

Project layout

src/c2pa_azure/
├── __init__.py          # public API: AzureSigner, TrustedSigningClient, TrustedSigningSettings
├── __main__.py          # enables `python -m c2pa_azure`
├── cli.py               # argparse entry point (c2pa-azure-sign)
├── signer.py            # AzureSigner
├── trusted_signing.py   # TrustedSigningClient + TrustedSigningSettings
└── data/                # bundled manifest.json and settings.json

Development

pip install -e ".[dev]"
pytest
python -m build           # produces dist/*.whl and dist/*.tar.gz

Load local module in editable mode (debugging)

When debugging changes in src/c2pa_azure, install this repo in editable mode so imports resolve to your local source tree:

python -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
python -c "import c2pa_azure; print(c2pa_azure.__file__)"

The printed path should point to this checkout (not a site-packages wheel install).

Release a new Python package version

Dependabot opens c2pa-python updates separately. Its pull-request workflow copies the pinned dependency version from requirements.txt to the project version, __version__, and the package's minimum c2pa-python requirement. After that pull request is merged into master, the Release workflow builds the distributions, publishes them to PyPI, and creates the matching GitHub Release.

The workflow verifies all version declarations before publishing. Configure a PyPI trusted publisher for .github/workflows/release.yml and the pypi GitHub environment before the first automatic release. A matching manually published GitHub Release remains supported for recovery or one-off releases.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

c2pa_azure-0.37.10.tar.gz (12.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

c2pa_azure-0.37.10-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

Details for the file c2pa_azure-0.37.10.tar.gz.

File metadata

  • Download URL: c2pa_azure-0.37.10.tar.gz
  • Upload date:
  • Size: 12.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for c2pa_azure-0.37.10.tar.gz
Algorithm Hash digest
SHA256 2e071ac624c4a8997c28f1ac0ba58111e898fda8c3eac94260a09d5b2317c08d
MD5 5d0eea12bc1aceb42bce5fb51918f55a
BLAKE2b-256 0777151a1b5697dd45e446faa95be105568139e4ebdde0b9e83365ac9c6d6760

See more details on using hashes here.

Provenance

The following attestation bundles were made for c2pa_azure-0.37.10.tar.gz:

Publisher: release.yml on duggaraju/c2pa-azure-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file c2pa_azure-0.37.10-py3-none-any.whl.

File metadata

  • Download URL: c2pa_azure-0.37.10-py3-none-any.whl
  • Upload date:
  • Size: 15.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for c2pa_azure-0.37.10-py3-none-any.whl
Algorithm Hash digest
SHA256 e9b9aaa9ee331a218c28a637610b5d9995946fcfbf3dd09591447f5b0b4075dc
MD5 7de0707782cba1ddd6c9f0f383d246f0
BLAKE2b-256 f9cf1a9d918c8d067eb823446a9380fd6e8a4dcd7fca813176fd61245ca5555b

See more details on using hashes here.

Provenance

The following attestation bundles were made for c2pa_azure-0.37.10-py3-none-any.whl:

Publisher: release.yml on duggaraju/c2pa-azure-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.37.10 This release

2 files

0.37.8

2 files

0.37.7

2 files

0.37.4

2 files

0.37.2

2 files

0.36.0

2 files

0.32.6.0

2 files

0.32.3.1

2 files

0.32.3

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page