Skip to main content

Embed XMP metadata and sign media assets using Swarmauri plugins.

Project description

Swarmauri logotype

EmbeddedSigner

PyPI - Downloads Repo views Supported Python versions License Latest release

EmbeddedSigner composes the dynamic XMP embedding utilities from EmbedXMP with the signing facade exposed by MediaSigner. It embeds metadata into media assets and then routes signing requests to the appropriate media-aware signer in either attached or detached mode. The class orchestrates key provider plugins so that opaque key references can be resolved automatically before signatures are produced.

Features

  • One-shot embed & sign – inject XMP metadata and produce signatures with a single call.
  • Media-aware detection – delegates to all registered EmbedXmpBase handlers so PNG, GIF, JPEG, SVG, WEBP, TIFF, PDF, and MP4 assets are processed consistently.
  • Pluggable signers – forwards signing requests to every SigningBase registered with MediaSigner, including CMS, JWS, OpenPGP, PDF, and XMLDSig providers.
  • Key provider integration – loads providers from the swarmauri.key_providers entry point group and resolves opaque key reference strings (e.g. local://kid@2) before invoking a signer.
  • Attached or detached output – toggle between embedded signatures or detached artifacts via a simple flag.
  • File and byte workflows – operate on in-memory payloads or update files on disk with helpers for embedding, reading, removing, and signing.
  • Command line tooling – bundle a ready-to-use embedded-signer CLI for ad-hoc embedding, signing, and combined workflows.

Installation

Using uv

uv add EmbeddedSigner

Optional dependencies align with the available key providers, EmbedXMP handlers, and MediaSigner backends:

uv add "EmbeddedSigner[local]"      # enable LocalKeyProvider resolution
uv add "EmbeddedSigner[memory]"     # enable InMemoryKeyProvider resolution
uv add "EmbeddedSigner[xmp_png]"    # add PNG embedding support
uv add "EmbeddedSigner[xmp_all]"    # install every EmbedXMP handler
uv add "EmbeddedSigner[signing_pdf]"  # enable PDF signer backend
uv add "EmbeddedSigner[signing_all]"  # install every MediaSigner backend
uv add "EmbeddedSigner[full]"       # bring in all extras and key providers

Using pip

pip install EmbeddedSigner

Extras mirror the uv workflow:

pip install "EmbeddedSigner[local]"
pip install "EmbeddedSigner[memory]"
pip install "EmbeddedSigner[xmp_png]"
pip install "EmbeddedSigner[xmp_all]"
pip install "EmbeddedSigner[signing_pdf]"
pip install "EmbeddedSigner[signing_all]"
pip install "EmbeddedSigner[full]"

Extras overview

Extra name Purpose
local / memory Enable Swarmauri key provider resolution for local filesystem and in-memory secrets.
xmp_gif, xmp_jpeg, xmp_png, xmp_svg, xmp_webp, xmp_tiff, xmp_pdf, xmp_mp4 Pull in the corresponding swarmauri_xmp_* handler so EmbedXMP can embed metadata for that media format.
xmp_all Install every EmbedXMP media handler dependency at once.
signing_cms, signing_jws, signing_openpgp, signing_pdf, signing_xmld Add the matching MediaSigner backend plugin for CMS, JWS, OpenPGP, PDF, or XMLDSig signing.
signing_all Install all MediaSigner backends together.
full Bring in every key provider, EmbedXMP handler, and MediaSigner backend for maximum coverage.

Usage

import asyncio
from pathlib import Path

from EmbeddedSigner import EmbedSigner

xmp_xml = """
<x:xmpmeta xmlns:x="adobe:ns:meta/">
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description rdf:about=""/>
  </rdf:RDF>
</x:xmpmeta>
""".strip()

async def embed_and_sign() -> None:
    signer = EmbedSigner()
    media_bytes = Path("image.png").read_bytes()
    embedded, signatures = await signer.embed_and_sign_bytes(
        media_bytes,
        fmt="JWSSigner",
        xmp_xml=xmp_xml,
        key={"kind": "raw", "key": b"\x00" * 32},
        path="image.png",
        attached=True,
        signer_opts={"alg": "HS256"},
    )
    Path("image.signed.png").write_bytes(embedded)
    print(signatures[0].mode)  # "attached"

asyncio.run(embed_and_sign())

Key provider integration

When you install a key provider plugin such as swarmauri_keyprovider_local, EmbeddedSigner can resolve string key references on the fly:

signer = EmbedSigner(key_provider_name="LocalKeyProvider")
embedded, signatures = await signer.embed_and_sign_file(
    Path("report.pdf"),
    fmt="PDFSigner",
    xmp_xml=xmp_xml,
    key="LocalKeyProvider://a1b2c3@1",
    attached=False,
    signer_opts={"alg": "SHA256"},
)

EmbeddedSigner parses the opaque reference, looks up the provider by name, and retrieves the specified key version using the provider's asynchronous API.

File helpers

EmbedSigner offers mirrored helpers that operate on file paths when you need to persist updates directly on disk:

signer = EmbedSigner()

# Embed metadata into a file and write it back in place.
signer.embed_file("image.png", xmp_xml)

# Read embedded metadata without materialising the bytes in memory.
print(signer.read_xmp_file("image.png"))

# Remove metadata and persist the stripped bytes to a new path.
signer.remove_xmp_file("image.png", write_back=True)

# Sign file contents without manual IO boilerplate.
signatures = asyncio.run(
    signer.sign_file(
        "image.png",
        fmt="JWSSigner",
        key="LocalKeyProvider://img-key",
        attached=True,
    )
)

Command line interface

Installing the package exposes an embedded-signer executable that wraps the most common workflows:

# Embed metadata from a file into an image in place.
embedded-signer embed example.png --xmp-file metadata.xmp

# Read metadata to stdout (non-zero exit if none is embedded).
embedded-signer read example.png

# Remove metadata and write the result to a new file.
embedded-signer remove example.png --output clean.png

# Sign using a key reference exposed by a provider plugin.
embedded-signer sign example.png --format JWSSigner --key-ref local://img-key

# Embed and sign in one step, writing signatures to JSON.
embedded-signer embed-sign example.png \
  --xmp-file metadata.xmp \
  --format JWSSigner \
  --key-ref local://img-key \
  --signature-output signatures.json

Development

  1. Install development dependencies:

    uv pip install -e ".[dev]"
    
  2. Format and lint code with ruff:

    uv run ruff format .
    uv run ruff check . --fix
    
  3. Run the unit tests in isolation:

    uv run --package EmbeddedSigner --directory plugins/embedded_signer pytest
    

Project Resources

License

EmbeddedSigner is released under the Apache 2.0 License. See the LICENSE file for details.

Project details


Download files

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

Source Distribution

embeddedsigner-0.1.4.dev3.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

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

embeddedsigner-0.1.4.dev3-py3-none-any.whl (15.0 kB view details)

Uploaded Python 3

File details

Details for the file embeddedsigner-0.1.4.dev3.tar.gz.

File metadata

  • Download URL: embeddedsigner-0.1.4.dev3.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for embeddedsigner-0.1.4.dev3.tar.gz
Algorithm Hash digest
SHA256 e2c9a967d808566fc7c7aac4b1ad0c398665bf33add709c739faf6b89b211c74
MD5 18479dbf10ea956c49b083ac7255144c
BLAKE2b-256 622b94ab4ce2815623a25fe5be9cd6dbac3264e0c114447aebd2c425dd1d1fa4

See more details on using hashes here.

File details

Details for the file embeddedsigner-0.1.4.dev3-py3-none-any.whl.

File metadata

  • Download URL: embeddedsigner-0.1.4.dev3-py3-none-any.whl
  • Upload date:
  • Size: 15.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for embeddedsigner-0.1.4.dev3-py3-none-any.whl
Algorithm Hash digest
SHA256 30d38b3f90310da4bbe8446c4a906572dcc638958dbc66d280f3e7bf8732538f
MD5 89632cbb600016bbec4c11e8323d0fef
BLAKE2b-256 21e9fe29169aa8c952768cf4f18b3abafe4caa621bf8a0c2bf53801472f8f0b2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page