Red*_*Red 2 javascript encryption rsa cryptojs subtlecrypto
所以我试图实现一些方法来加密然后解密一些数据。我对此没有任何经验,并且我尝试按照网上的一些帖子了解如何进行此操作。
\n当我将加密的“hello”传递给解密函数时,我得到:
\nlet a = importPublicKeyAndEncrypt('hello')\n\nCryptoKey\xc2\xa0{type: "public", extractable: true, algorithm: {\xe2\x80\xa6}, usages: Array(1)} W29iamVjdCBBcnJheUJ1ZmZlcl0=\n\nimportPrivateKeyAndDecrypt(a)\nPromise\xc2\xa0{<pending>}\n\nDOMException: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.\nat importPrivateKeyAndDecrypt (<anonymous>:26:60)\nRun Code Online (Sandbox Code Playgroud)\n当我使用我在 PKCS#8 看到的一篇帖子中的加密消息时,解密功能可以正常工作,但当我生成自己的密钥时,解密功能就不能正常工作。
\n这是代码\n我做错了什么?
\n// PEM encoded X.509 key\nconst publicKey = `\n-----BEGIN PUBLIC KEY-----\n <removed for space>\n-----END PUBLIC KEY-----`;\n\n// PEM encoded PKCS#8 key\nconst privateKey = `\n-----BEGIN PRIVATE KEY-----\n <removed for space>\n-----END PRIVATE KEY-----`;\n\nasync function importPublicKeyAndEncrypt(str) {\n try {\n const pub = await importPublicKey(publicKey);\n console.log(pub);\n const encrypted = await encryptRSA(pub, new TextEncoder().encode(str));\n const encryptedBase64 = window.btoa(ab2str(encrypted));\n console.log(encryptedBase64.replace(/(.{64})/g, '$1\\n'));\n } catch (error) {\n console.log(error);\n }\n}\n\nasync function importPrivateKeyAndDecrypt(str) {\n try {\n const priv = await importPrivateKey(privateKey);\n const decrypted = await decryptRSA(priv, str2ab(window.atob(str)));\n console.log(decrypted);\n } catch (error) {\n console.log(error);\n }\n}\n\nasync function importPublicKey(spkiPem) {\n return await window.crypto.subtle.importKey(\n 'spki',\n getSpkiDer(spkiPem),\n {\n name: 'RSA-OAEP',\n hash: 'SHA-256',\n },\n true,\n ['encrypt']\n );\n}\n\nasync function importPrivateKey(pkcs8Pem) {\n return await window.crypto.subtle.importKey(\n 'pkcs8',\n getPkcs8DerDecode(pkcs8Pem),\n {\n name: 'RSA-OAEP',\n hash: 'SHA-256',\n },\n true,\n ['decrypt']\n );\n}\n\nasync function encryptRSA(key, plaintext) {\n let encrypted = await window.crypto.subtle.encrypt(\n {\n name: 'RSA-OAEP',\n },\n key,\n plaintext\n );\n return encrypted;\n}\n\nasync function decryptRSA(key, ciphertext) {\n let decrypted = await window.crypto.subtle.decrypt(\n {\n name: 'RSA-OAEP',\n },\n key,\n ciphertext\n );\n return new TextDecoder().decode(decrypted);\n}\n\nfunction getSpkiDer(spkiPem) {\n const pemHeader = '-----BEGIN PUBLIC KEY-----';\n const pemFooter = '-----END PUBLIC KEY-----';\n var pemContents = spkiPem.substring(\n pemHeader.length,\n spkiPem.length - pemFooter.length\n );\n var binaryDerString = window.atob(pemContents);\n return str2ab(binaryDerString);\n}\n\nfunction getPkcs8DerDecode(pkcs8Pem) {\n const pemHeader = '-----BEGIN PRIVATE KEY-----';\n const pemFooter = '-----END PRIVATE KEY-----';\n var pemContents = pkcs8Pem.substring(\n pemHeader.length,\n pkcs8Pem.length - pemFooter.length\n );\n var binaryDerString = window.atob(pemContents);\n return str2ab(binaryDerString);\n}\n\nfunction str2ab(str) {\n const buf = new ArrayBuffer(str.length);\n const bufView = new Uint8Array(buf);\n for (let i = 0, strLen = str.length; i < strLen; i++) {\n bufView[i] = str.charCodeAt(i);\n }\n return buf;\n}\n\nfunction ab2str(buf) {\n return String.fromCharCode.apply(null, new Uint8Array(buf));\n}\nRun Code Online (Sandbox Code Playgroud)\n
只有两个小缺陷。
首先,return缺少 inimportPublicKeyAndEncrypt()和 in语句importPrivateKeyAndDecrypt()(尽管后者对于当前代码片段来说不是必需的)。
另外,需要等待importPublicKeyAndEncrypt()before的promiseimportPrivateKeyAndDecrypt()才能被调用。
通过这些修复,代码可以工作:
// PEM encoded X.509 key
const publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAunF5aDa6HCfLMMI/MZLT
5hDk304CU+ypFMFiBjowQdUMQKYHZ+fklB7GpLxCatxYJ/hZ7rjfHH3Klq20/Y1E
bYDRopyTSfkrTzPzwsX4Ur/l25CtdQldhHCTMgwf/Ev/buBNobfzdZE+Dhdv5lQw
KtjI43lDKvAi5kEet2TFwfJcJrBiRJeEcLfVgWTXGRQn7gngWKykUu5rS83eAU1x
H9FLojQfyia89/EykiOO7/3UWwd+MATZ9HLjSx2/Lf3g2jr81eifEmYDlri/OZp4
OhZu+0Bo1LXloCTe+vmIQ2YCX7EatUOuyQMt2Vwx4uV+d/A3DP6PtMGBKpF8St4i
GwIDAQAB
-----END PUBLIC KEY-----`;
// PEM encoded PKCS#8 key
const privateKey = `-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6cXloNrocJ8sw
wj8xktPmEOTfTgJT7KkUwWIGOjBB1QxApgdn5+SUHsakvEJq3Fgn+FnuuN8cfcqW
rbT9jURtgNGinJNJ+StPM/PCxfhSv+XbkK11CV2EcJMyDB/8S/9u4E2ht/N1kT4O
F2/mVDAq2MjjeUMq8CLmQR63ZMXB8lwmsGJEl4Rwt9WBZNcZFCfuCeBYrKRS7mtL
zd4BTXEf0UuiNB/KJrz38TKSI47v/dRbB34wBNn0cuNLHb8t/eDaOvzV6J8SZgOW
uL85mng6Fm77QGjUteWgJN76+YhDZgJfsRq1Q67JAy3ZXDHi5X538DcM/o+0wYEq
kXxK3iIbAgMBAAECggEASlJj0ExIomKmmBhG8q8SM1s2sWG6gdQMjs6MEeluRT/1
c2v79cq2Dum5y/+UBl8x8TUKPKSLpCLs+GXkiVKgHXrFlqoN+OYQArG2EUWzuODw
czdYPhhupBXwR3oX4g41k/BsYfQfZBVzBFEJdWrIDLyAUFWNlfdGIj2BTiAoySfy
qmamvmW8bsvc8coiGlZ28UC85/Xqx9wOzjeGoRkCH7PcTMlc9F7SxSthwX/k1VBX
mNOHa+HzGOgO/W3k1LDqJbq2wKjZTW3iVEg2VodjxgBLMm0MueSGoI6IuaZSPMyF
EM3gGvC2+cDBI2SL/amhiTUa/VDlTVw/IKbSuar9uQKBgQDd76M0Po5Lqh8ZhQ3o
bhFqkfO5EBXy7HUL15cw51kVtwF6Gf/J2HNHjwsg9Nb0eJETTS6bbuVd9bn884Jo
RS986nVTFNZ4dnjEgKjjQ8GjfzdkpbUxsRLWiIxuOQSpIUZGdMi2ctTTtspvMsDs
jRRYdYIQCe/SDsdHGT3vcUCybwKBgQDXDz6iVnY84Fh5iDDVrQOR4lYoxCL/ikCD
JjC6y1mjR0eVFdBPQ4j1dDSPU9lahBLby0VyagQCDp/kxQOl0z2zBLRI4I8jUtz9
/9KW6ze7U7dQJ7OTfumd5I97OyQOG9XZwKUkRgfyb/PAMBSUSLgosi38f+OC3IN3
qlvHFzvxFQKBgQCITpUDEmSczih5qQGIvolN1cRF5j5Ey7t7gXbnXz+Umah7kJpM
IvdyfMVOAXJABgi8PQwiBLM0ySXo2LpARjXLV8ilNUggBktYDNktc8DrJMgltaya
j3HNd2IglD5rjfc2cKWRgOd7/GlKcHaTEnbreYhfR2sWrWLxJOyoMfuVWwKBgFal
CbMV6qU0LfEo8aPlBN8ttVDPVNpntP4h0NgxPXgPK8Pg+gA1UWSy4MouGg/hzkdH
aj9ifyLlCX598a5JoT4S0x/ZeVHd/LNI8mtjcRzD6cMde7gdFbpLb5NSjIAyrsIA
X4hxvpnqiOYRePkVIz0iLGziiaMbfMwlkrxvm/LRAoGBALPRbtSbE2pPgvOHKHTG
Pr7gKbmsWVbOcQA8rG801T38W/UPe1XtynMEjzzQ29OaVeQwvUN9+DxFXJ6Yvwj6
ih4Wdq109i7Oo1fDnMczOQN9DKch2eNAHrNSOMyLDCBm++wbyHAsS2T0VO8+gzLA
BviZm5AFCQWfke4LZo5mOS10
-----END PRIVATE KEY-----`;
async function importPublicKeyAndEncrypt(str) {
try {
const pub = await importPublicKey(publicKey);
//console.log(pub);
const encrypted = await encryptRSA(pub, new TextEncoder().encode(str));
const encryptedBase64 = window.btoa(ab2str(encrypted));
//console.log(encryptedBase64.replace(/(.{64})/g, '$1\n'));
return encryptedBase64;
} catch (error) {
console.log(error);
}
}
async function importPrivateKeyAndDecrypt(str) {
try {
const priv = await importPrivateKey(privateKey);
const decrypted = await decryptRSA(priv, str2ab(window.atob(str)));
//console.log(decrypted);
return decrypted;
} catch (error) {
console.log(error);
}
}
async function importPublicKey(spkiPem) {
return await window.crypto.subtle.importKey(
'spki',
getSpkiDer(spkiPem),
{
name: 'RSA-OAEP',
hash: 'SHA-256',
},
true,
['encrypt']
);
}
async function importPrivateKey(pkcs8Pem) {
return await window.crypto.subtle.importKey(
'pkcs8',
getPkcs8DerDecode(pkcs8Pem),
{
name: 'RSA-OAEP',
hash: 'SHA-256',
},
true,
['decrypt']
);
}
async function encryptRSA(key, plaintext) {
let encrypted = await window.crypto.subtle.encrypt(
{
name: 'RSA-OAEP',
},
key,
plaintext
);
return encrypted;
}
async function decryptRSA(key, ciphertext) {
let decrypted = await window.crypto.subtle.decrypt(
{
name: 'RSA-OAEP',
},
key,
ciphertext
);
return new TextDecoder().decode(decrypted);
}
function getSpkiDer(spkiPem) {
const pemHeader = '-----BEGIN PUBLIC KEY-----';
const pemFooter = '-----END PUBLIC KEY-----';
var pemContents = spkiPem.substring(
pemHeader.length,
spkiPem.length - pemFooter.length
);
var binaryDerString = window.atob(pemContents);
return str2ab(binaryDerString);
}
function getPkcs8DerDecode(pkcs8Pem) {
const pemHeader = '-----BEGIN PRIVATE KEY-----';
const pemFooter = '-----END PRIVATE KEY-----';
var pemContents = pkcs8Pem.substring(
pemHeader.length,
pkcs8Pem.length - pemFooter.length
);
var binaryDerString = window.atob(pemContents);
return str2ab(binaryDerString);
}
function str2ab(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
}
(async () => {
let ciphertext = await importPublicKeyAndEncrypt('hello');
console.log("Ciphertext:\n", ciphertext.replace(/(.{48})/g, '$1\n'));
let decryptedData = await importPrivateKeyAndDecrypt(ciphertext);
console.log("Decrypted data:", decryptedData);
})();Run Code Online (Sandbox Code Playgroud)