PGP Key Generator — TypeScript source
Generate PGP key pairs (ECC or RSA) in your browser. Download your public and private keys. Powered by OpenPGP.js.
This is the TypeScript implementation — the same logic the interactive tool runs, in a shareable, citable form.
import { generateKey, readKey } from 'openpgp';
/**
* PGP key pair generation (pure lib, no React/DOM) — a thin wrapper around
* openpgp.js `generateKey`. Keys are generated in the caller's context; the
* island runs this entirely client-side, so the private key never leaves the
* browser.
*/
/** Algorithm choices: ECC Curve25519 (default), RSA-2048, or RSA-4096. */
export type PGPKeyGenAlgorithm = 'ecc' | 'rsa2048' | 'rsa4096';
export interface PGPKeyGenOptions {
/** User's real name (goes into the key's user ID packet). */
name: string;
/** User's email (goes into the key's user ID packet). */
email: string;
/** Optional passphrase. If given, the private key is encrypted with it. */
passphrase?: string;
algorithm: PGPKeyGenAlgorithm;
}
export interface PGPKeyPair {
/** ASCII-armored public key (BEGIN PGP PUBLIC KEY BLOCK). */
publicKey: string;
/** ASCII-armored private key (BEGIN PGP PRIVATE KEY BLOCK). */
privateKey: string;
/** v4 fingerprint, 40 lowercase hex chars, no spaces. */
fingerprint: string;
/** ASCII-armored revocation certificate. */
revocationCertificate: string;
}
/** Accepts `foo@bar.tld`-style addresses: one @, non-empty local + domain, a dot in the domain. */
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
/** Validate the identity that goes into the key's user ID. Throws on invalid input. */
export function validateKeyGenIdentity(name: string, email: string): void {
if (!name.trim()) throw new Error('Name is required.');
if (!email.trim()) throw new Error('Email is required.');
if (!EMAIL_RE.test(email.trim())) throw new Error('Invalid email address.');
}
/** Generate an ASCII-armored PGP key pair. ECC (Curve25519) is fast; RSA-4096 can take a few seconds. */
export async function generatePGPKeyPair(options: PGPKeyGenOptions): Promise<PGPKeyPair> {
const { name, email, passphrase, algorithm } = options;
validateKeyGenIdentity(name, email);
// Concrete literal params per branch — generateKey's overloads reject a
// spread of the ecc/rsa param union.
const userID = { name: name.trim(), email: email.trim() };
// An empty-string passphrase would still encrypt the key; only a real
// passphrase should.
const pass = passphrase ? passphrase : undefined;
const { publicKey, privateKey, revocationCertificate } =
algorithm === 'ecc'
? // v6 API: modern X25519/Ed25519 keys are requested via type 'curve25519'
// (the `curve` field is for legacy named curves only).
await generateKey({
type: 'curve25519',
userIDs: [userID],
passphrase: pass,
format: 'armored',
})
: await generateKey({
type: 'rsa',
rsaBits: algorithm === 'rsa4096' ? 4096 : 2048,
userIDs: [userID],
passphrase: pass,
format: 'armored',
});
// With format 'armored' generateKey returns only the armored strings — parse
// the public key back to read its fingerprint.
const key = await readKey({ armoredKey: publicKey });
return {
publicKey,
privateKey,
fingerprint: key.getFingerprint(),
revocationCertificate,
};
}
Also available in 8 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →