在纯前端实现的 PGP 加解密( firefox 115.12 测试通过) 代码中引用的 openpgp.min.js 是 openpgpjs 在这里发布的项目: https://unpkg.com/openpgp/dist/ 直接下载此 js 文件: https://unpkg.com/openpgp@5.11.1/dist/openpgp.min.js 将以下代码保存成 .html 文件即可 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>OpenPGP.js Demo</title> <script src="openpgp.min.js"></script> <script> function clearTextarea() { switch (event.target.id) { case "btnClearPubKey2": var text = document.getElementById("publicKey2").value = ""; break; case "btnClearPgpMsg2": var text = document.getElementById("pgpmsg2").value = ""; break; } } function copyToClipboard() { switch (event.target.id) { case "btnCopyPubKey": var text = document.getElementById("publicKey").value; break; case "btnCopyPgpMsg": var text = document.getElementById("encrypttext").value; break; } // Create a temporary textarea element var tempTextarea = document.createElement("textarea"); tempTextarea.value = text; document.body.appendChild(tempTextarea); // Select the text in the textarea element tempTextarea.select(); tempTextarea.setSelectionRange(0, 99999); /*For mobile devices*/ // Copy the selected text document.execCommand("copy"); // Remove the temporary textarea element document.body.removeChild(tempTextarea); // Optionally, provide feedback to the user //alert("Copied the text: " + text); } async function pgpencrypt() { // privateKey sign var privateKeyArmored = document.getElementById("privateKey").value; const passphrase = document.getElementById("passphrase").value; const privateKey = await openpgp.decryptKey({ privateKey: await openpgp.readPrivateKey({ armoredKey: privateKeyArmored }), passphrase }); // The other party's public key is used for encryption var publicKeyArmored2 = document.getElementById("publicKey2").value; var plaintext = document.getElementById("plaintext").value; const publicKey = await openpgp.readKey({ armoredKey: publicKeyArmored2 }); const encrypted = await openpgp.encrypt({ message: await openpgp.createMessage({ text: plaintext }), // input as Message object encryptionKeys: publicKey, signingKeys: privateKey // optional }); document.getElementById('encrypttext').value = encrypted; //console.log(encrypted); // '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----' } async function pgpdecrypt() { // Verify digital signature with the opponent's public key var publicKeyArmored2 = document.getElementById("publicKey2").value; const publicKey2 = await openpgp.readKey({ armoredKey: publicKeyArmored2 }); // decryption var privateKeyArmored = document.getElementById("privateKey").value; var encrypted = document.getElementById("pgpmsg2").value; const passphrase = document.getElementById("passphrase").value; // what the private key is encrypted with const privateKey = await openpgp.decryptKey({ privateKey: await openpgp.readPrivateKey({ armoredKey: privateKeyArmored }), passphrase }); const message = await openpgp.readMessage({ armoredMessage: encrypted // parse armored message }); const { data: decrypted, signatures } = await openpgp.decrypt({ message, verificationKeys: publicKey2, // optional decryptionKeys: privateKey }); document.getElementById('decryptedtext').value = decrypted //console.log(decrypted); // 'Hello, World!' // check signature validity (signed messages only) try { await signatures[0].verified; // throws on invalid signature console.log('Signature is valid'); } catch (e) { throw new Error('Signature could not be verified: ' + e.message); } } async function buildpair() { const { privateKey, publicKey, revocationCertificate } = await openpgp.generateKey({ type: 'ecc', // Type of the key, defaults to ECC curve: 'curve25519', // ECC curve name, defaults to curve25519 userIDs: [{ name: 'Jon Smith', email: 'jon@example.com' }], // you can pass multiple user IDs passphrase: document.getElementById("passphrase").value, // protects the private key format: 'armored' // output key format, defaults to 'armored' (other options: 'binary' or 'object') }); document.getElementById('privateKey').value = privateKey; // '-----BEGIN PGP PRIVATE KEY BLOCK ... ' document.getElementById('publicKey').value = publicKey; // '-----BEGIN PGP PUBLIC KEY BLOCK ... ' //console.log(revocationCertificate); // '-----BEGIN PGP PUBLIC KEY BLOCK ... ' } (async () => { const { privateKey, publicKey, revocationCertificate } = await openpgp.generateKey({ type: 'ecc', // Type of the key, defaults to ECC curve: 'curve25519', // ECC curve name, defaults to curve25519 userIDs: [{ name: 'Jon Smith', email: 'jon@example.com' }], // you can pass multiple user IDs passphrase: 'password', // protects the private key format: 'armored' // output key format, defaults to 'armored' (other options: 'binary' or 'object') }); document.getElementById('privateKey').value = privateKey; // '-----BEGIN PGP PRIVATE KEY BLOCK ... ' document.getElementById('publicKey').value = publicKey; // '-----BEGIN PGP PUBLIC KEY BLOCK ... ' //console.log(revocationCertificate); // '-----BEGIN PGP PUBLIC KEY BLOCK ... ' })(); </script> </head> <body> <h1>OpenPGP.js Demo</h1> <hr /> <h3>My temporary PGP key pair</h3> <p> Private key protects passwords<br /> <input id="passphrase" type="password" value="password" /> <button id="btnBuildPair">Build pair</button> </p> <p><textarea id="privateKey" rows="5" cols="70"></textarea></p> <p><textarea id="publicKey" rows="5" cols="70"></textarea></p> <p><button id="btnCopyPubKey">Copy Public Key</button></p> <hr /> <h3>Encrypt Message</h3> <p>The PGP public key of the other party</p> <p><button id="btnClearPubKey2">Clear</button></p> <p><textarea id="publicKey2" rows="5" cols="70"></textarea> </p> <p>Plain Text</p> <p><textarea id="plaintext" rows="5" cols="70"></textarea></p> <p><button id="btnPgpSignEncrypt">Signature & Encrypt</button></p> <p><textarea id="encrypttext" rows="5" cols="70"></textarea></p> <p><button id="btnCopyPgpMsg">Copy PGP Message</button></p> <hr /> <h3>Decrypt Message</h3> <p>PGP Message</p> <p><button id="btnClearPgpMsg2">Clear</button></p> <p><textarea id="pgpmsg2" rows="5" cols="70"></textarea></p> <p><button id="btnPgpDecryptVerifySign">Decrypt & Verify Signature</button></p> <p>Plain Text</p> <p><textarea id="decryptedtext" rows="5" cols="70"></textarea></p> <script> document.getElementById("btnBuildPair").addEventListener("click", buildpair); document.getElementById("btnPgpSignEncrypt").addEventListener("click", pgpencrypt); document.getElementById("btnPgpDecryptVerifySign").addEventListener("click", pgpdecrypt); document.getElementById("btnCopyPubKey").addEventListener("click", copyToClipboard); document.getElementById("btnCopyPgpMsg").addEventListener("click", copyToClipboard); document.getElementById("btnClearPubKey2").addEventListener("click", clearTextarea); document.getElementById("btnClearPgpMsg2").addEventListener("click", clearTextarea); </script> </body> </html>