{"id":49434653,"url":"https://github.com/cloudflareresearch/poc-watermark","last_synced_at":"2026-04-29T16:12:58.342Z","repository":{"id":284143292,"uuid":"940702721","full_name":"cloudflareresearch/poc-watermark","owner":"cloudflareresearch","description":null,"archived":false,"fork":false,"pushed_at":"2025-05-21T16:58:36.000Z","size":3838,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-13T12:13:13.708Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloudflareresearch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-28T16:34:30.000Z","updated_at":"2025-05-21T16:58:40.000Z","dependencies_parsed_at":"2025-03-24T11:58:41.518Z","dependency_job_id":"80574e94-62da-4390-ba88-083d66b63dc1","html_url":"https://github.com/cloudflareresearch/poc-watermark","commit_stats":null,"previous_names":["cloudflareresearch/poc-watermark"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cloudflareresearch/poc-watermark","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflareresearch%2Fpoc-watermark","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflareresearch%2Fpoc-watermark/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflareresearch%2Fpoc-watermark/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflareresearch%2Fpoc-watermark/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloudflareresearch","download_url":"https://codeload.github.com/cloudflareresearch/poc-watermark/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflareresearch%2Fpoc-watermark/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32433234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T13:34:34.882Z","status":"ssl_error","status_checked_at":"2026-04-29T13:34:29.830Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-29T16:12:56.918Z","updated_at":"2026-04-29T16:12:58.336Z","avatar_url":"https://github.com/cloudflareresearch.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Proof of Concept: Generate Watermarked Images from Pseudorandom Codes\n\nThis repository demos a watermark for Stable Diffusion using [pseudorandom\nerror-correcting codes](https://eprint.iacr.org/2024/235). For details, see the\ncompanion [blog post](https://blog.cloudflare.com/an-early-look-at-cryptographic-watermarks-for-ai-generated-content/).\n\nThe watermark is similar to [\"An Undetectable Watermark for Generative Image\nModels\" (ICLR 2025)](https://arxiv.org/abs/2410.07369). Our main goal here was\nto try out the simpler (and hopefully faster) DDIM inversion method for\napproximating the initial latent. Check out [their\nimplementation](https://github.com/XuandongZhao/PRC-Watermark).\n\n## Prerequisites\n\n- Python == 3.11 \n- rust \u003e= 1.83\n\n### Local Rust Setup\n\nTo install Rust use the installer script from the [Rust getting started\nguide.](https://www.rust-lang.org/learn/get-started)\n\n### Local Python Step\n\n```\npython -m venv .venv  # requirements are tested for Python 3.11\nsource .venv/bin/activate\npip install -r requirements.txt\n```\n\nNote that we have pinned a specific version of `huggingface_hub` in order to\navoid a [bug introduced in a newer\nversion](https://github.com/easydiffusion/easydiffusion/issues/1851).\n\nThe scripts in the sections below use a watermarking key checked in to this\nrepository. See the section **\"Generate Watermarking Keys\"** for instructions on\ngenerating watermarking keys.\n\n## Building the Watermarking Codes\n\nThis repository contains a Rust crate, `prc` that implements the actual\nwatermark. We use `maturin` for Python bindings:\n\n```\nmaturin develop --release -m prc/Cargo.toml\npython prc/example.py  # make sure we can run the code\n```\n\n## Generate Watermarked Images\n\nThe `generator` module generates a watermarked image, and it's corresponding\ninverted latent. The watermark is encoded in the initial latent used in the\nimage generation process.\n\nBoth the image generation and inversion pipelines are Stable Diffusion\npipelines. The generation pipeline uses a `DDIM` scheduler and the inversion\npipeline that generates the approximate initial latent (of the generated image)\nuses a `DDIM inverse` scheduler. \n\n**Generate Watermarked Image from the Prompt:** *grainy photo of a UFO at night*\n```\npython generator.py --prompt \"grainy photo of a UFO at night\"\n```\n\n**Original Generated Image**\n\n![](examples/d3c0618bc28d4f869bed43e997674783.png)\n\n## Verifying Watermarked Images\n\nThe watermark verifier allows you to check an image for a watermark added to\nimages generated by the `generator`. The verifier is implemented by the\n`verifier` module.\n\nTo run `verifier`, pass it the path of an image you want to check\nfor a watermark. The verifier can only verify watermarks added to images by\nthe `generator`. The image must have the dimensions of `512x512` to match the\nfixed dimensions of the stable diffusion model used in this PoC.\n\n```\npython verifier.py --image_path examples/d3c0618bc28d4f869bed43e997674783.png\n```\n\n## Performance Evaluation\n\nTo determine how \"robust\" we need to make the pseudorandom code in order to use\nDDIM inversion to recover watermarks, we need to understand how similar the\noriginal initial latent are with the approximate latent. This is provided by\nthe evaluator module, which generates an unwatermarked image and compares the\ninitial latent to the inverted latent:\n\n```\npython evaluator.py --prompt \"grainy photo of a UFO at night\"\n```\n\n## Generate Watermarking Keys\n\nThis writes a file called `watermarking_key` to the current directory, which is\nread by the watermark generator and detector. This only needs to be done once.\n\n```\npython key_gen.py\n```\n\n## Troubleshooting\n\nThere is a bug Apple M1/M2 specific bug where running Stable Diffusion pipelines\nin debug mode in PyCharm with the `mps` as the targeted device raises the\nassertion error below. This error does not happen when `mps` is the target\ndevice and the debug generator, evaluator and detector modules are run from the\ncommand line. To debug in PyCharm set the `debug` command line parameter to\n`True` to set the target device to the CPU.\n\n```\nIOGPUMetalCommandBuffer validate: failed assertion commit an already committed command buffer\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudflareresearch%2Fpoc-watermark","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudflareresearch%2Fpoc-watermark","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudflareresearch%2Fpoc-watermark/lists"}