V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
busier
V2EX  ›  程序员

人手一个工具站:前端 PGP 加解密 (单 html+单 js)

  •  
  •   busier · 160 天前 · 490 次点击
    这是一个创建于 160 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在纯前端实现的 PGP 加解密( firefox 115.12 测试通过)

    代码中引用的 openpgp.min.js 是 openpgpjs 在这里发布的项目: https://unpkg.com/openpgp/dist/

    直接下载此 js 文件: https://unpkg.com/[email protected]/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: '[email protected]' }], // 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: '[email protected]' }], // 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>
    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5376 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 05:53 · PVG 13:53 · LAX 21:53 · JFK 00:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.