Programming

Built a Firefox PGP extension — honest postmortem on AI-assisted development and cryptographic responsibility

Started by codecave · Jul 20, 2026

#10789
There are legitimate reasons to be skeptical of browser-based PGP tools. I want to address them directly.

Why browser-based at all?

For users who operate primarily in a browser environment — particularly Tor users on live USB setups with no persistent desktop tools — the realistic alternative to a browser extension is often a web-based PGP tool (copy-paste into a website) or skipping PGP entirely. Both of those are worse. A local-only browser extension with no network permissions and an auditable permission manifest is a better option for that specific workflow.

This is not meant to replace GPG on a hardened desktop. It's for the use case where a full GPG setup isn't available or practical.

How it handles key storage:

Private keys are stored in Firefox's extension local storage, encrypted with AES-256 using a master password you set. The master password is never stored — only a hash used for verification. If you don't set a master password, keys are stored unencrypted and you should know that going in.

Cryptographic operations:

All encrypt/decrypt/sign/verify operations use OpenPGP.js. No custom crypto. The library version is vendored and pinned — it does not auto-update separately from the extension.

Key format support:

- RSA and ECC keypairs

- Standard armored PGP blocks

- Import/export of public and private keys

- Subkey support via OpenPGP.js

What it doesn't do:

- Key server integration (by design — no network permissions)

- Web of trust management

- Smartcard/hardware token support

- Automatic key discovery

The honest limitation:

If you don't trust the developer (me), pin a specific version on GitHub, audit that version yourself, and disable automatic updates. The entire extension is under 500 lines of non-library code. An experienced PGP or JavaScript developer can read it in under an hour.

I also want to give an honest response about how this was built because I've gotten criticism calling it "vibe coded," and some of that criticism is fair while some of it conflates different parts of the codebase.

What AI helped with:

UI structure, CSS, form layout, button placement. The popup interface is HTML/CSS with event listeners. AI tools were useful for iterating on layout quickly. This is also the part of the code that does not touch keys or cryptographic operations.

What AI did not write:

I did not use AI to implement cryptographic logic. The reason is simple: I am not qualified to review AI-generated crypto code for subtle vulnerabilities, and neither are most developers. The correct approach for in-browser PGP is to use OpenPGP.js (https://openpgpjs.org), which is the same library used by ProtonMail's web interface and has been independently audited. My code calls OpenPGP.js. It does not reimplement anything.

If you want to evaluate the security-relevant code, pgp-handler.js is the file to read. It's short. The pattern is: take user input → call openpgp.encrypt() / openpgp.decrypt() / openpgp.sign() / openpgp.verify() → return result. There is no clever logic to hide behind.

The manifest:

No content scripts. No host permissions. No webRequest. The extension runs in an isolated context and cannot interact with page content.

What I'd do differently:

Write more explicit comments in the integration layer distinguishing "this is UI logic" from "this touches key material." The current code is readable but doesn't make that separation visually obvious, which contributes to the reasonable suspicion that the whole thing was auto-generated without review.

Mozilla: https://addons.mozilla.org/en-US/firefox/addon/pgpsuite/

Source: https://github.com/ernos/pgpsuite-firefox-tor-extension

Website: https://www.yourdev.net/pgpsuite

Please help contribute through Github! It's fully open source and I will merge any bug fix or new implementation that is worthwhile.