Security & Verification

signed by Lollysecurity.htmlHTMLAI generatedgenerated by ClaudeПровери самGet the signed filepixels, not shapes13 KB

A security reviewer's summary of the cryptography behind Lolly's Content Credentials, verification and encryption - the standards it implements, the primitives it uses, how trust is earned and how all of it is tested. This is the public companion to the deeper Content Credentials - Engineering guide. The operator narrative lives in Lolly for Operators.

The short version: verification is entirely on-device, the crypto is standards-based and built on the platform's own WebCrypto engine, and every claim is backed by a test - known-answer vectors, adversarial forgery/replay tests, fuzzing and conformance against independent tools.

Verification is on-device

Everything Lolly verifies, it verifies locally, offline, without uploading the file. Dropping a file on /verify (or lolly validate <file>) parses it, walks its Content Credential, re-checks the signature and the byte-hash binding and renders a verdict. It all runs in your browser or on your machine. There is no verification server.

The Verify screen - nothing but a drop target, no upload button, no account, because the check runs where the file already issigned by Lollyvector SVGПровери самGet the signed file13 paths~7.6k nodes14 groups84 KBThe Verify screen - nothing but a drop target, no upload button, no account, because the check runs where the file already issigned by Lollyvector SVGПровери самGet the signed file13 paths~7.6k nodes14 groups84 KB

Here is a real check, start to finish. This is the generated Queensland storm from our AI stance. It is a Gemini image Lolly opened, resized and exported to WebP. Drop it on /verify and the whole story comes back: a green Made with Lolly verdict, the two key validations (credential intact, bytes unchanged), the provenance scorecard and an honest GEN AI flag because a machine made the pixels. None of it left your device to get there.

The full Verify verdict for the generated storm image - the image itself, a green Made with Lolly pill, the intact-credential and unchanged-bytes badges and the provenance scorecardsigned by Lollyvector SVGAI generatedПровери самGet the signed file145 paths~9.8k nodes72 groups2 images339 KBThe full Verify verdict for the generated storm image - the image itself, a green Made with Lolly pill, the intact-credential and unchanged-bytes badges and the provenance scorecardsigned by Lollyvector SVGAI generatedПровери самGet the signed file145 paths~9.4k nodes72 groups2 images258 KB

AI declares itself in the same verdict, as a badge nobody has to go looking for. The file was generated, and its credential says so. Lolly reads that assertion back out and surfaces it plainly, alongside the note that a Google model very likely stamped an invisible SynthID watermark into the pixels too.

The GEN AI flag Verify raises for the storm image - a labelled badge reading that the image was AI-generated, with the SynthID notesigned by Lollyvector SVGПровери самGet the signed file12 paths~6.4k nodes9 groups71 KBThe GEN AI flag Verify raises for the storm image - a labelled badge reading that the image was AI-generated, with the SynthID notesigned by Lollyvector SVGПровери самGet the signed file12 paths~6.4k nodes9 groups71 KB

The engine's crypto core is platform-agnostic and uses only globalThis.crypto / WebCrypto. There is no bespoke crypto library, no Node-only APIs and no network calls anywhere in the engine. In the web app, verification makes no network request to any third party. The only fetch it can ever make is the opt-in deep scan's one-time detector download, from the app's own origin. Even a SEAL record whose signing key lives in DNS is reported as "no key resolver" rather than routed through a third-party DNS-over-HTTPS service (the desktop and command-line shells resolve such keys through your own machine's DNS, with no third party involved).

Standards implemented

AreaStandard
Content CredentialsC2PA 2.x (reads v1 + v2 manifests from any producer)
Signing certificatesRFC 5280 (X.509/PKIX), C2PA cert profile, section 14.5.1
Signature containerRFC 9052 / 9360 (COSE_Sign1)
SerializationRFC 8949 (deterministic CBOR)
Key fingerprintingRFC 7638 (JWK thumbprint)
Credential boxingISO 19566-5 (JUMBF)
Video bindingISO 14496-12 (BMFF)
PDF encryptionISO 32000-2, section 7.6.4 (PDF 2.0 AES-256, R6)
Zip encryptionPKWARE APPNOTE + WinZip AE-2
Byte-level signaturesSEAL (verification)
Durable soft bindingAdobe TrustMark (read + write; write off by default)
Supply chainCycloneDX 1.5 (SBOM)

Cryptographic primitives

The export panel's lock card, where Standard and Strong name the actual ciphers rather than hiding them behind a padlock iconsigned by Lollyvector SVGПровери самGet the signed file11 paths~4.4k nodes11 groups1 image51 KBThe export panel's lock card, where Standard and Strong name the actual ciphers rather than hiding them behind a padlock iconsigned by Lollyvector SVGПровери самGet the signed file11 paths~4.4k nodes11 groups1 image51 KB

All of the above run on the platform's audited WebCrypto implementation. The two symmetric ciphers use a small in-house block layer only because WebCrypto exposes no raw AES block. This layer is used encrypt-only, over your own content, never as a decryption oracle.

How "trusted" is earned

Lolly reports the trust a file can actually prove, in explicit tiers:

Trust anchors are public certificates only. They are the C2PA ecosystem roots (Google, Adobe, the CAI trust list, camera makers, AI providers) plus Lolly's own public root. Presence on the list never confers trust by itself. Trust always requires the live chain walk and signature check above. Chain walking is bounded (a capped number of intermediates, parsed defensively) so a hostile certificate chain can't exhaust resources.

There is no timestamp authority yet, so an authentic-but-expired signature surfaces the signer's identity while staying trusted: false. It proves who, not when. An RFC 3161 timestamp countersignature is on the roadmap.

Complementary provenance signals

Beyond the C2PA credential, Verify surfaces several read-only signals. Each is an honest heuristic that only ever adds confidence, never a false alarm:

Lolly's provenance strategy is read-broad, embed-narrow: it reads many signals but writes only three - C2PA, its own Imprint and an opt-in durable mark in Adobe's TrustMark format (a neural pass plus a one-time model download, so it is off by default). That keeps the write-side attack surface small, and it is exactly what the export panel shows: three named switches, each a separate mechanism, rather than one blanket "protect this" claim.

The Content protection group on a PNG export, with the credential, the Imprint and the durable mark as three separate switchessigned by Lollyvector SVGПровери самGet the signed file21 paths~1.5k nodes35 groups4 images25 KBThe Content protection group on a PNG export, with the credential, the Imprint and the durable mark as three separate switchessigned by Lollyvector SVGПровери самGet the signed file21 paths~1.5k nodes35 groups4 images25 KB

How it's assured

An automated test in the repository (npm test) backs every cryptographic claim above:

The cryptography and parsers are additionally undergoing SUSE's enterprise-scale security hardening. They are strong by design today. Where a contract calls for certified assurance, deploy Lolly as one layer of defence-in-depth.

Design boundaries (worth having straight)

Reporting a vulnerability

Found something? Report it privately: fitzy+security@suse.com, the Report a vulnerability button on any lolly-tools repository or the machine-readable /.well-known/security.txt. The full policy, scope and safe-harbour statement live in SECURITY.md. We practise coordinated disclosure and credit reporters in the fix notes.

Where to go next