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

160 天前
 busier
在纯前端实现的 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>
492 次点击
所在节点    程序员
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1050284

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX