// RSA 加密
async function encryptData(publicKeyStr, data) {
const publicKey = await importPublicKey(publicKeyStr);
const encoder = new TextEncoder();
const encrypted = await window.crypto.subtle.encrypt(
{
name: "RSA-OAEP"
},
publicKey,
encoder.encode(data)
);
return arrayBufferToBase64(encrypted);
}
// RSA 解密
async function decryptData(privateKeyStr, encryptedData) {
const privateKey = await importPrivateKey(privateKeyStr);
const encryptedBuffer = base64ToArrayBuffer(encryptedData);
const decrypted = await window.crypto.subtle.decrypt(
{
name: "RSA-OAEP"
},
privateKey,
encryptedBuffer
);
const decoder = new TextDecoder();
return decoder.decode(decrypted);
}
// 导入公钥根据公钥字符串
async function importPublicKey(pemString) {
const keyData = pemToArrayBuffer(pemString);
const publicKey = await window.crypto.subtle.importKey(
"spki",
keyData,
{
name: "RSA-OAEP",
hash: "SHA-256"
},
true, // extractable
["encrypt"]
);
return publicKey;
}
// 导入私钥根据私钥字符串
async function importPrivateKey(pemString) {
const keyData = pemToArrayBuffer(pemString);
const privateKey = await window.crypto.subtle.importKey(
"pkcs8",
keyData,
{
name: "RSA-OAEP",
hash: "SHA-256"
},
true, // extractable
["decrypt"]
);
return privateKey;
}
// PEM 转 ArrayBuffer(清理 PEM 头尾并解码 Base64)
function pemToArrayBuffer(pem) {
const PEM_REGEX = /-----BEGIN [A-Z0-9 ]+KEY-----([^-]+)-----END [A-Z0-9 ]+KEY-----/g;
const base64Der = pem.replace(PEM_REGEX, '$1').replace(/\s/g, '');
const binaryString = atob(base64Der);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
// 格式化 PEM 字符串为每行指定长度
function formatPEM(str, chunkSize = 64) {
return str.match(new RegExp('.{1,' + chunkSize + '}', 'g')).join('\n');
}
// 将 ArrayBuffer 转换为 Base64 字符串
function arrayBufferToBase64(buffer) {
let binary = '';
const bytes = new Uint8Array(buffer);
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
// 将 Base64 字符串转换为 ArrayBuffer
function base64ToArrayBuffer(base64) {
const binaryString = window.atob(base64);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
console.log("😊😊😊 RSA Begin");
const keyPair = await generateRsaKeyPair();
console.log("GenerateRsaKey:", keyPair);
const publicKeyStr = await exportPublicKey(keyPair.publicKey);
const privateKeyStr = await exportPrivateKey(keyPair.privateKey);
console.log("PrivateKeyStr:", privateKeyStr);
console.log("PublicKeyStr:", publicKeyStr);
const testData = "Hello, World!";
console.log("Test Data:", testData);
const encryptStr = await encryptData(publicKeyStr, testData);
console.log("EncryptStr:", encryptStr);
const decryptStr = await decryptData(privateKeyStr, encryptStr);
console.log("DecryptStr:", decryptStr);
console.log("😊😊😊 RSA End");
注意
Node.js 不支持 window.crypto,因为 window 对象是浏览器环境特有的,代表了浏览器中的全局对象,而 Node.js 运行在一个独立的环境中,没有浏览器相关的全局对象如 window。
如果你希望在 Node.js 中使用类似于浏览器环境中 window.crypto 提供的功能(例如加密操作),你可以利用 Node.js 自带的 crypto 模块来实现。或者使用其他的三方组件库,如"webcrypto"等