A 100% client-side suite for proving the authenticity and provenance of digital media. It combines image watermarking (9 algorithms), audio watermarking (8 algorithms), document watermarking (5 techniques), fingerprinting (21 hash algorithms), pixel injection (23 algorithms), C2PA Content Credentials, OpenTimestamps, forensic analysis, Decentralized Identity (DID), Digital Passport certificates, file conversion, ID generation, metadata analysis, and on-device face/iris/voice biometrics — all running locally in your browser or via a Node.js CLI. No data is ever uploaded to a server (except OpenTimestamps, which contacts Bitcoin timestamp servers, and CDN/Hugging Face fetches for model and library files).
Journalists verifying photo authenticity, artists proving ownership of digital artwork, photographers establishing provenance, musicians protecting audio content, forensic analysts examining image integrity, content creators documenting their workflow, developers integrating authenticity checks, legal professionals needing evidentiary documentation, and anyone who needs to demonstrate that a digital file has not been tampered with since a known point in time.
Yes, it is open-source under the GPL-2.0-or-later license (package.json). You can use it, modify it, and distribute it freely, provided you comply with the license terms.
The project is stable. All 6,200+ tests pass across 107 unit test files + 59 E2E suites (Node 22 + 24), 77 CI/CD workflows enforce code quality, 30+ historical CodeQL alerts are resolved, and all core algorithms are functionally complete. The tool is actively maintained (v2.0.0 released 2026-10-07).
The browser version requires an internet connection for the initial page load (CDN libraries: jsPDF, docx, QRious, JSZip, LameJS, FFmpeg.wasm, and for the biometric tools the ONNX runtimes / model files). Local vendor/ copies load first, with CDN as fallback. After that, all processing is local. The CLI version works fully offline once dependencies are installed.
From a clone of the repository:
git clone https://github.com/Redo-San/RedoSan-Authenticity.git
cd RedoSan-Authenticity
npm install
npm link # makes the `redosan` command available globally
redosan --help
Without npm link, run it directly with node cli/index.js <command>. Requirements: Node.js >= 22.14.0. See [Installation] for the full setup guide (tests, dev server, troubleshooting).
Not yet. The package is prepared as redosan-authenticity-cli (v2.0.0, bin wiring and staged-publish workflow in place) but npm view redosan-authenticity-cli returns 404 — publication is staged behind OIDC/trusted-publishing approval. Install from source as described above until it is published.
katex/smol-toml/MCP SDK overrides, two-tier npm-audit policygood first issue tasksEarlier: v1.9 added Voice Biometric, v1.8 added Iris Biometric i18n and quality gates, v1.7.1 hardened Face Biometric (WebAuthn PRF vault, liveness, ArcFace ONNX). See [Changelog] for the complete release history.
| Format | Fingerprint | Watermark | Pixel Inject | C2PA Read | C2PA Write | Audio WM | Doc WM | Metadata | Timestamp |
|---|---|---|---|---|---|---|---|---|---|
| JPEG | Yes | Yes | Yes | Yes | Yes | No | No | Yes | Yes |
| PNG | Yes | Yes | Yes | Yes | Yes | No | No | Yes | Yes |
| BMP | Yes | Yes | Yes | No | No | No | No | Yes | Yes |
| TIFF | Yes | No | No | No | No | No | No | Yes | Yes |
| WebP | Yes | No | No | No | No | No | No | Yes | Yes |
| WAV | No | No | No | No | No | Yes | No | No | Yes |
| DOCX | No | No | No | No | No | No | Yes | No | Yes |
| No | No | No | No | No | No | Yes | No | Yes | |
| TXT | Yes | No | No | No | No | No | Yes | No | Yes |
| Tool | Algorithms |
|---|---|
| Image Watermark | 9 (Spatial LSB, Frequency DCT, Neural SS, Latent DCT, Zero-bit, Multi-bit, Forensic, Fragile, Imatag-style) + auto-detect |
| Audio Watermark | 8 (LSB, Phase Coding, Echo Hiding, DSSS, QIM, DWT Haar, Patchwork, DCT) |
| Document Watermark | 5 (Whitespace, Zero-Width Characters, Synonym, Line-Shift, Word-Shift) |
| Pixel Injection | 23 across 4 categories (Spatial 4, Frequency 4, Deep Learning 5, Professional 5) + 5 analysis modes (statistical detection, ML detection, blind decoding, robustness testing, quality metrics); Auto Detect tries them all |
| Fingerprint | 21 (17 cryptographic + 4 perceptual: pHash, aHash, dHash, wHash) |
| ID Forge | 5 (UUID v4, UUID v7, ULID, NanoID, SWHID) |
| DID | 3 key types (Ed25519, P-256, RSA-2048/RSA-4096) |
| Certificate | 3 output formats (PDF, DOCX, EPUB) |
| Face / Iris / Voice | On-device detection, matching, liveness + anti-spoof, template protection |
RedoSanZeroBit signature)DCT-based watermarking modifies frequency coefficients. JPEG compression reapplies its own DCT with quantization, which alters or destroys the watermarked coefficients. Even at JPEG quality 100, some quantization occurs. This is a fundamental limitation of transform-domain watermarking combined with lossy compression.
Spatial algorithms share the same bit positions, so they can interfere if used on the same image. Frequency-domain algorithms operate on different transform coefficients and can generally coexist, though capacity is reduced. The Simplified Mode pipeline handles this automatically by using different algorithm families for watermarking vs. pixel injection.
C2PA (Coalition for Content Provenance and Authenticity) is an industry standard for embedding provenance metadata in media files. The manifest contains claims about who created the content, when, and with what tools. C2PA must be the last pixel operation because canvas operations (toBlob(), toDataURL(), loadImage()) strip C2PA chunks from image data. If you watermark after C2PA signing, the C2PA manifest is lost.
DID (Decentralized Identifier) provides a way to create self-sovereign digital identities. RedoSan Authenticity supports the DID:key method with Ed25519, P-256, and RSA key types. DIDs can be used to sign file fingerprints, creating a cryptographic link between the file and the identity. The signature can be verified independently.
All browser JavaScript files start with an IIFE that checks window.location.href against a regex allowing only redo-san.github.io, localhost, and 127.0.0.1 (file: URLs are exempt). On untrusted domains the script throws RedoSan Authenticity: This script is protected by GPL license. — so a cloned deployment fails loudly instead of looking functional.
Each tool has its own standalone HTML page at Style/pages/{name}/index.html. The MPA router (mpa-router.js) intercepts internal link clicks, fetches the target page via AJAX, swaps only the content area, and updates the URL via pushState. This preserves the audio player, sidebar state, and all JS state across navigations. The SPA entry point (index.html) remains fully functional with hash-based routing. Removal-tools links are the exception: they always perform a full-page redirect. See [Architecture] for the full design.
Yes. The entire tool runs client-side in your browser or locally on your machine. No images, metadata, or personal information is uploaded to any server. The only network calls are:
Passwords are used to seed a pseudo-random number generator for algorithms that require randomized pixel selection. The CLI additionally uses crypto.pbkdf2Sync with 100,000 iterations for key derivation. Passwords are never sent over the network.
No. Face, iris, and voice templates are stored on-device (local registry / IndexedDB, encrypted — face uses a WebAuthn PRF vault) and matching runs in the browser. Only model files are downloaded from CDNs / Hugging Face. Consent is session-scoped and withdrawable, and all three pipelines include liveness / anti-spoof checks.
All three run in the browser only (no CLI equivalent):
The embedded C2PA key is a well-known test key from the C2PA specification. It is not intended for production use. In a production deployment, you would replace it with your own key pair. Anyone with the test key can create valid C2PA manifests, which is why the tool is designed for transparency (the key is public) rather than cryptographic trust.
The SW intercepts all fetch requests and enforces:
The browser UI includes checkAutomation() which detects headless Chrome, Puppeteer, Playwright, Selenium, and other automation frameworks. When detected, a warning overlay is displayed. Detection methods include checking navigator.webdriver, navigator.plugins.length, and several other automation-specific properties.
The CLI validation can be bypassed with --allow-dangerous. The Service Worker's whitelists are enforced at the SW level and cannot be bypassed by client-side JavaScript (though a motivated user could disable the SW in DevTools). The domain origin self-check is trivially patched by removing the IIFE — it is a deterrent, not a cryptographic safeguard. The full threat model and defense layers are documented on [Security].
30+ CodeQL alerts were resolved across the project's history: incomplete URL sanitization, missing null checks, prototype pollution, XSS via innerHTML, regex denial of service, insecure random number generation, unsigned integer handling, and an iris_ui.js XSS fix shipped in v1.7.1. Intentional patterns (such as the tag-whitelist approach in sanitizeHtml) are documented with suppression comments.
The project tracks zero open alerts across CodeQL, Dependabot, and Secret Scanning, and runs a two-tier npm audit: a blocking npm audit --omit=dev --audit-level=high in the unit-test CI job, a non-blocking full-scope audit in E2E, plus a weekly security-audit.yml run. 22 dependencies are overridden to patched versions (tar 7.5.22, js-yaml 4.3.2, markdown-it 14.3.2, smol-toml 1.9.0, qs 6.16.0, katex 0.18.2, serialize-javascript 7.0.6, uuid 14.0.0, glob 13.0.6, got 11.8.5, tmp 0.2.7, and others — see package.json).
The domain origin self-check in all JS files blocks execution on any domain other than redo-san.github.io, localhost, or 127.0.0.1. Make sure you are accessing via http://localhost:PORT or http://127.0.0.1:PORT (for example the bundled node dev-server.js).
Use the mode toggle buttons in the header. Simplified mode provides a guided 10-step pipeline. Professional mode provides per-algorithm control in individual sections. The mode is persisted in history.state for back/forward navigation.
Click the language toggle button in the top-right corner to switch between 8 languages: Arabic, German, English, Spanish, French, Japanese, Korean, and Chinese. The setting is applied immediately and all UI text is re-translated. RTL/LTR direction is updated automatically.
Yes! Each tool has its own standalone MPA page:
https://redo-san.github.io/RedoSan-Authenticity/Style/pages/watermark/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/audio-watermark/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/fingerprint/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/pixel-injection/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/c2pa/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/did/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/certificate/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/forensic/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/converter/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/id_forge/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/document-watermark/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/face-biometric/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/iris-biometric/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/voice-biometric/https://redo-san.github.io/RedoSan-Authenticity/Style/pages/removal-tools/ (local builds only — see below)Removal_Tools/ and Style/pages/removal-tools/ are gitignored and local-only (commit 6f2b8ee removed them from GitHub Pages). On redo-san.github.io, sanitizeRemovalTools() strips the links from the navigation, the MPA router forces a full-page redirect, and window.RedoSanLoadRemovalTools no-ops. The page shell exists in the whitelist, but the engine script only loads on self-hosted copies where Removal_Tools/removal_tools.js is present.
The PDF is generated client-side using jsPDF, which has limitations in layout rendering compared to HTML/CSS. The PDF prioritizes data completeness over visual fidelity. All hash values, timestamps, user info, C2PA claims, and watermark data are included.
Watermark/watermark_core.jsWatermark/watermark.js (algorithm list + switch case)cli/commands/watermark.jscli/tests/watermark_core_test.jsStyle/lang/i18n-data-en.js to Style/lang/i18n-data-{code}.jsStyle/i18n.js language listJS_WHITELIST in sw.js (and mirror in 404.html)Add the path to the JS_WHITELIST array in both sw.js and 404.html. Note the two files can drift: as of v2.0.0, sw.js additionally lists vendor/docx.umd.min.js and Removal_Tools/removal_tools.js, while 404.html still lists Voice_Biometric/voice_liveness.js (which sw.js does not) and lacks the face-biometric CSS pair and the EXT_WHITELIST. Reconcile both files when editing.
Style/pages/{name}/index.html using _page_template.htmlindex.html)sw.js HTML whitelist (and 404.html)css/style.css and css/responsive.css to the CSS whitelistStyle/navigation.js for standalone mode detectionThere is no redosan menu subcommand. Use the standalone menu script instead:
node cli/menu.js # or double-click start.bat / start.sh
Similarly, ID generation is not a redosan id-forge subcommand — call the library directly:
node cli/lib/id_forge.js uuidv4 5
node cli/lib/id_forge.js all 3 --json
vm.runInContext() instead of require()?The browser JS files use top-level function and var declarations. In Node.js, require() wraps the module in a function scope, making these declarations private. vm.runInContext() executes in the global scope of a new V8 context, making all declarations available to subsequent modules.
node --test cli/tests/did_test.js
node --test cli/tests/fingerprint_test.js
node --test cli/tests/audio_watermark_core_test.js
node --test cli/tests/document_watermark_test.js
npm run test:e2e-all # all Playwright E2E tests
npm run test:e2e-mpa # MPA standalone page tests
npm run check # lint + stylelint + biome + test
npm run check:quick # quick auto-fix + core tests
npm run check:full # full audit (lint, biome, stylelint, markdownlint, cspell, madge, depcheck, tests)
npm run check:fix # auto-fix all lint/format/style issues
npm run lint:ox # oxlint fast gate (errors only)
Husky runs several gates before lint-staged:
git diff --check --cached (whitespace / conflict markers)node scripts/guard-large-files.mjs (warn 5-10 MiB, block >= 10 MiB)scripts/secret-scan-precommit.ps1 (gitleaks probe)lint-staged: JS → oxlint (errors only) then eslint --fix then prettier; CSS → stylelint --fix then prettier; HTML → prettier; JSON → biome then prettier; YAML/MD → biomecommit-msg strips non-noreply Co-authored-by: trailers; pre-push runs commitlint and (for workflow changes) actionlintlocalhost, 127.0.0.1, or redo-san.github.io
Wiki: API Reference
Wiki: Architecture
Wiki: Changelog
Wiki: Face Biometric
Wiki: Home
Wiki: Installation
Wiki: Iris Biometric
Wiki: Security
Wiki: Usage Guide
Wiki: Voice Biometric
Wiki: _Sidebar