在纯前端实现的 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>