Skip to main content

Encode an identifier into an image's pixels; verify a JSON record against any copy

Project description

Mememage

Mememage

Encode an identifier into an image's pixels; verify a JSON record against any copy.

Mememage writes a 2-pixel-tall bar into the bottom rows of an image. The bar holds two values:

  • identifier — a short string that points to a JSON record, stored separately (a server, a CDN, IPFS, a file).
  • content hash — a 64-bit digest (the first 16 hex of SHA-256) over the record. verify recomputes it and compares against the bar.

What's tamper-evident: the record. Change any field and verify fails. Core proves the record-to-image binding — it does not police the pixels (edit the image but leave the bar, and it still verifies) and does not prove authorship (that's a signature's job, out of core's scope).

The bar survives JPEG, resaves, screenshots, and re-uploads, so the identifier reads back from any copy. encode reads any image Pillow can open and writes a lossless PNG; decode and verify work on any format the bar survives. Record fields are arbitrary — captions, credits, generation parameters, links.

pip install mememage                 # encode / decode / verify — Pillow included
# pip install "mememage[encrypt]"    # adds AES-256 field encryption

Quickstart

Three functions, all pure image operations:

import mememage

# encode — write the bar into the image, build the record from your fields
result = mememage.encode("photo.png", {"title": "Morning fog", "by": "catmemes"})
result.identifier            # 'mememage-3dc5f03a747bb38e' (derived from the fields)
result.save("photo.json")    # the record — store or serve it separately

# decode — read the bar back out of the pixels (the inverse of encode)
bar = mememage.decode("photo.jpg")      # any format the bar survived: PNG, JPEG, a screenshot
bar.identifier, bar.content_hash

# verify — does a record match an image? (recomputed hash == the bar's)
mememage.verify("photo.jpg", result.record)        # True if the record is intact

You resolve the record from its identifier — look it up wherever you keep it, then verify:

bar    = mememage.decode("photo.jpg")    # identifier + content hash from the pixels
record = my_store[bar.identifier]        # your storage: a dict, a file, a DB, a URL
mememage.verify("photo.jpg", record)     # True if the record matches the image
  • encode accepts any image — a path, bytes, a PIL Image, or a numpy array (HEIC needs the [heic] extra) — and returns the barred image as Record.image. Given a destination — a path (in place, or a .png sibling for non-PNG), out=<path.png>, or out=<stream> (e.g. BytesIO) — it writes the file. Output is always PNG: the bar is lossless, and a lossy re-encode would corrupt it. An in-memory input with no destination never touches disk.
  • decode / verify accept the same in-memory forms — a path, bytes, a file-like, a PIL Image, or a numpy array. No disk round-trip.
  • No network I/Odecode returns the identifier; you resolve the record. Core is pure pixel + hash operations.

Encrypt private fields

  • Mark fields private to encrypt them (AES-256-GCM via PBKDF2) under a password.
  • The record still verifies without the password — the hash covers the ciphertext.
  • unlock returns the decrypted fields. The password is not stored; only the ciphertext is kept in the record.
result = mememage.encode("photo.png", {"title": "Public", "gps": "45.5,-122.6"},
                         password="hunter2", private=["gps"])
mememage.verify("photo.png", result.record)              # matches — no password
mememage.unlock(result, "hunter2")["gps"]                # '45.5,-122.6'

Command line

mememage encode photo.png --field title="Morning fog" -o photo.json   # write the record
mememage decode photo.jpg --record photo.json                         # VERIFIED (exit 0) / RECORD ALTERED (exit 1)
mememage decode photo.jpg                                             # read the identifier only (no record)

Without -o, the record is written next to the image as <identifier>.json. decode exits 0 on a match.

License

MIT.

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

mememage-0.1.2.tar.gz (49.0 kB view details)

Uploaded Source

Built Distribution

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

mememage-0.1.2-py3-none-any.whl (36.2 kB view details)

Uploaded Python 3

File details

Details for the file mememage-0.1.2.tar.gz.

File metadata

  • Download URL: mememage-0.1.2.tar.gz
  • Upload date:
  • Size: 49.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mememage-0.1.2.tar.gz
Algorithm Hash digest
SHA256 0344c187c3bc37fdd5af6e7d530616818c3b47e1b1dbde80647a00b3e5aae6bc
MD5 3742ce1b4246d7c8d17f5936a34f5541
BLAKE2b-256 c76c9eb72dccf88d601f7442c5cc4f748cf6fccdf596f5eb8366085f9b692d46

See more details on using hashes here.

Provenance

The following attestation bundles were made for mememage-0.1.2.tar.gz:

Publisher: publish.yml on sememtac/mememage

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

File details

Details for the file mememage-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: mememage-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 36.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mememage-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2821f146c370ab75266b69851be5cafa39db7cd0791547e50078dce4267abb73
MD5 5137524e3896e7c8a383a0618a1a879a
BLAKE2b-256 3c9546fda8cdf9f426a60b641a550908ecc74859e31a0228320695ccdfc4c511

See more details on using hashes here.

Provenance

The following attestation bundles were made for mememage-0.1.2-py3-none-any.whl:

Publisher: publish.yml on sememtac/mememage

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

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