Open glober1234 opened 2 years ago
Yes, it's because JSEncrypt has bad compatibility with other libraries/OpenSSL, it's really hard (but possible) to make those work together.
I'd suggest moving to using subtle crypto API (native to JS, vanilla JS) instead of this laggy library.
I decided to migrate to using subtle crypto after the recent bug with their NPM package (#282 #209 #278 )
You could do something like:
const getRSAEncrypted = async (text : string) => {
if (!process.env.REACT_APP_PUBLIC_RSA_KEY) {
throw new Error('No public key provided in the .env');
}
const key =
await importPublicKey("Your public key in a string format, with all of the spaces replaced by \n".replace(
"\n",
`
`));
const encrypted = await encryptRSA(key, yourTextToEncrypt);
return window.btoa(ab2str(encrypted));
}
const fromBase64 = (base64String : string) => Uint8Array.from(atob(base64String), c => c.charCodeAt(0));
const getPkciDer = (pkciPem : string) => {
console.log(pkciPem);
pkciPem = pkciPem.replace(/[\r\n]+/gm, "");
const pkciPemHeader = "-----BEGIN PUBLIC KEY-----";
const pkciPemFooter = "-----END PUBLIC KEY-----";
console.log(pkciPem);
pkciPem = pkciPem.substring(pkciPemHeader.length, pkciPem.length - pkciPemFooter.length);
console.log(pkciPem.replace(/[\r\n]+/gm, "").replace(/[\r\n]+/gm, ""));
return fromBase64(pkciPem.replace(/[\r\n]+/gm, "").replace(/[\r\n]+/gm, ""));
}
const importPublicKey = async (pkciPem : string) => {
return await window.crypto.subtle.importKey(
"spki",
getPkciDer(pkciPem),
{
name: "RSA-OAEP",
hash: "SHA-1",
},
true,
["encrypt"]
);
}
const encryptRSA = async (key : CryptoKey, text : string) => {
const enc = new TextEncoder();
const encrypted = await window.crypto.subtle.encrypt(
{
name: "RSA-OAEP"
},
key,
enc.encode(text)
);
return encrypted;
}
const ab2str = (buf : ArrayBuffer) => {
//@ts-ignore
return String.fromCharCode.apply(null, new Uint8Array(buf));
}
This is a great working example of how you can encrypt RSA on frontend and then decrypt on backend. The encryption here implements a standard and doesn't add anything like JSEncrypt.
On the backend, I decrypt it like: this
openssl rsautl -decrypt -oaep -inkey private_key.pem -in cipheredtextthatyougotfromthersafunction.txt -out noncipheredtextdecryptedfromrsa.txt
I am creating RSA key pair in C# , and setting public key in hidden input field and storing private key in server session. On post i will encrypt in js and decrypt in C# on server side. But its not working its returning false on encrypt function. Does it only support PEM format keys? Is there any example which satisfies my goal.