Skip to main content

Encrypted Image Watermark Injector / Validator

Project description

Pixseal

Encrypted image watermark injector/validator that hides text (optionally RSA encrypted) inside 24-bit PNG or BMP files by modulating the parity of carefully selected color channels.

Features

  • Noise-resistant embedding: Chooses the RGB component whose value is farthest from 127 and nudges it ±1 to match each payload bit, keeping noise visually imperceptible.
  • Sentinel-based framing: Automatically prefixes/suffixes payloads with START-VALIDATION / END-VALIDATION markers so the validator knows where to look.
  • Optional RSA envelope: When you pass a public key, both the sentinels and payload are encrypted with OAEP (SHA-256). Validation decrypts with the matching private key before building a verdict.
  • Pure Python image I/O: SimpleImage reads/writes uncompressed BMPs as well as 8-bit RGB/RGBA PNGs without third-party imaging libraries.

Installation

pip install Pixseal
# or for local development
pip install -e ./pip_package

Python 3.8+ is required. The only runtime dependency is cryptography>=41.0.0.

Usage

Sign an image

from Pixseal import signImage

result = signImage(
    imageInput="original.png",  # accepts a file path or raw PNG/BMP bytes
    hiddenString="!Validation:kyj9447@mailmail.com",
    publicKeyPath="SSL/public_key.pem",  # omit for plain-text embedding
)
result.save("signed_original.png")
  • The payload is looped if it runs out before the image ends, so even small files carry the full sentinel/payload/end pattern.
  • When publicKeyPath is omitted, the payload remains plain text.

Validate and (optionally) decrypt

from Pixseal import validateImage

report = validateImage(
    imageInput="signed_original.png",  # accepts a file path or raw PNG/BMP bytes
    privKeyPath="SSL/private_key.pem",  # omit for plain-text payloads
)

print(report["extractedString1"])
print(report["validationReport"])

validateImage returns:

{
    "extractedString1": "<payload or encrypted blob>",
    "extractedString2": "<truncated payload or encrypted blob>",
    "validationReport": {
        "arrayLength": 4,
        "lengthCheck": True,
        "startCheck": True,
        "endCheck": True,
        "isDecrypted": True,
        "tailCheckResult": True,
        "verdict": True,
        # decryptSkipMessage when a decrypt request was skipped
    }
}

CLI demo script

python testRun.py offers an interactive flow:

  1. Choose 1 to sign an image. It reads original.png, asks for a payload (default !Validation:kyj9447@mailmail.com), optionally encrypts with SSL/public_key.pem, and writes signed_<name>.png.
  2. Choose 2 to validate. It reads signed_original.png, optionally decrypts with SSL/private_key.pem, and prints both the extracted string and verdict.
  3. Choose 3 to benchmark performance. It reads original.png, encrypts it with SSL/public_key.pem, and writes signed_original.png, printing the elapsed signing time. Then it reads signed_original.png, performs extraction/decryption/validation, and prints the elapsed validation time along with the total elapsed time.
  4. Choose 4 to test signing and validation with file-path input option.
  5. Choose 5 to test signing and validation with byte-stream input option.

Key management

Generate a test RSA pair (PKCS#8) with OpenSSL:

openssl genpkey -algorithm RSA -out SSL/private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in SSL/private_key.pem -out SSL/public_key.pem

Point publicKeyPath / privKeyPath to these files.

API reference

Function Description
signImage(imageInput, hiddenString, publicKeyPath=None) Loads a PNG/BMP from a filesystem path or raw bytes, injects hiddenString plus sentinels, encrypting each chunk when publicKeyPath is provided. Returns a SimpleImage that you can save() or saveBmp().
validateImage(imageInput, privKeyPath=None) Reads the hidden bit stream from a path or raw bytes, splits by newlines, deduplicates, optionally decrypts each chunk (Base64 indicates ciphertext), and returns the payload plus a validation report.

Examples

Original Signed (!Validation:kyj9447@mailmail.com)

Validation output excerpt:

[Validate] verdict: True
[Validate] extracted string: !Validation:kyj9447@mailmail.com
[Validate] decrypted with private key: SSL/private_key.pem

Validation Report

{'extractedString1': '!Validation:kyj9447@mailmail.com',
 'extractedString2': 'DMnWAzbd6NFycGAxcPkzzmGjL33WXovG...',
 'validationReport': {'arrayLength': 4,
                      'endCheck': True,
                      'isDecrypted': True,
                      'lengthCheck': True,
                      'startCheck': True,
                      'tailCheckResult': True,
                      'verdict': True}}

(When encrypted, each line appears as Base64 until decrypted with the RSA private key.)

Corrupted after signing

Validation output excerpt:

...
string argument should contain only ASCII characters
string argument should contain only ASCII characters
string argument should contain only ASCII characters
[Validate] verdict: False
[Validate] extracted string: !Validation:kyj9447@mailmail.com
[Validate] decrypted with private key: SSL/private_key.pem

Validation Report

{'extractedString1': '!Validation:kyj9447@mailmail.com',
 'extractedString2': 'hh78IWEsRgfTWMw3Rg02hTnCdErjx0O4...',
 'validationReport': {'arrayLength': 400,
                      'decryptSkipMessage': 'Skip decrypt: payload was plain '
                                            'or corrupted text despite decrypt '
                                            'request.',
                      'endCheck': True,
                      'isDecrypted': True,
                      'lengthCheck': False,
                      'startCheck': True,
                      'tailCheckResult': 'Not Required',
                      'verdict': False}}

Related projects

https://github.com/kyj9447/imageSignerCamera

  • Mobile camera that signs images on capture:
  • Server-side validator that decrypts and verifies payloads.

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

pixseal-0.1.4.tar.gz (12.0 kB view details)

Uploaded Source

Built Distribution

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

pixseal-0.1.4-py3-none-any.whl (11.0 kB view details)

Uploaded Python 3

File details

Details for the file pixseal-0.1.4.tar.gz.

File metadata

  • Download URL: pixseal-0.1.4.tar.gz
  • Upload date:
  • Size: 12.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for pixseal-0.1.4.tar.gz
Algorithm Hash digest
SHA256 75e46cf37e082718b324a994ab2361c69e2e6a3f31a1d8b6b02ca195901e7dc2
MD5 a2b08ec0eb18ebaef7394ff7513f9316
BLAKE2b-256 b7c07284c41160787251cccdd0639eb1a10a69df474223b17d4af6b77f59a3cb

See more details on using hashes here.

File details

Details for the file pixseal-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: pixseal-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 11.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for pixseal-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 87cd94cc76fc85c82ff263a099971430334df27dceca7960bd6fe456616f776d
MD5 bcaad501d02f736d0f59a5609e88bfac
BLAKE2b-256 2d2b7abb9b5303254c2db34d62b514b7c387c9e1f93b122d17db70dbdfd4a2f3

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