0

I am facing a weird problem with WebCrypto Subtle. If I do the encryption and decryption in the same browser tab, it works perfectly. But, If I try to decrypt a ciphertext which was encrypted somewhere else, it just throws DOMException: The operation failed for an operation-specific reason

I am using this piece of code:

//encrypt
window.crypto.subtle.importKey(
                "jwk",
                key,
                {
                    name: "RSA-OAEP",
                    hash: "SHA-256",
                },
                true,
                ['encrypt']
            )
            .then(pkey => {
                const iv = window.crypto.getRandomValues(new Uint8Array(16))
                window.crypto.subtle.encrypt(
                    {
                      name: "RSA-OAEP",
                      hash: "SHA-256",
                      iv
                    },
                    pkey,
                    new TextEncoder().encode('hello world')
                ).then(encrypted => {
                    str = ab2str(encrypted) //special function to convert it to string
                })
            })


//decrypt
window.crypto.subtle.importKey(
                    "jwk",
                    privateKey,
                    {
                        name: "RSA-OAEP",
                        hash: "SHA-256"
                    },
                    true,
                    ['decrypt']
                )
                .then(prkey => {
                    window.crypto.subtle.decrypt(
                        { 
                           name: "RSA-OAEP", 
                           hash: "SHA-256", 
                           iv: new TextEncoder().encode(msg.data.iv) 
                        },
                        prkey,
                        str2ab(msg.data.message) //special function convert it to ArrayBuffer
                    )
                    .then(t => console.log(new TextDecoder().decode(t)))
                    .catch(console.log)
                })


//Helper functions
function ab2str(buf) {
        return String.fromCharCode.apply(null, new Uint16Array(buf));
}

function str2ab(str) {
        var buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char
        var bufView = new Uint16Array(buf);
        for (var i = 0, strLen = str.length; i < strLen; i++) {
          bufView[i] = str.charCodeAt(i);
        }
        return buf;
}

I have tried both with and without the Initialization vector. But nothing works. Could not find any information in google as well. Can someone please solve this issue?

Abrar
  • 69
  • 1
  • 7
  • How are ciphertext and IV encoded to get them from the encrypting side to the decrypting side, i.e. did you apply a reasonable binary-to-text encoding like Base64? Post sample data for `msg.data.iv` (`new TextEncoder().encode(msg.data.iv)` looks very suspect). Also, `ab2str()` and `str2ab()` are missing. – Topaco Feb 03 '23 at 12:50
  • @Topaco I have added those two functions to my question now. I am sending those data over plain http requests. After converting ciphertext arraybuffer to string, the encrypted message looks something like this: `앫徇㹢軵῵IJﲶ絗ꇤƾ燴擢ꈑ퇖᳚臖翢蠅偲붮棌扠닱ఏ⑾磡︴⮖ᨡ㟨렅�䒩冼ᙄ걳ᔸ겁⛞餎裮씹�猲⢫ꍁ읗ၜ餐횲ᔼꭨ鴳灴啜浪ؐח瑫ꉾ᳽䅊輺뛦ुɈ㙖༒쟂皒ᾞ᣾翾鏷䶨㤫�㙮ι"⼸捂⮥ྊ꘨ƪ宸詽眗ᚄ巤⯿훾称嚱飦➷墾鉬쐞ꡉ糶͹᱁ય롐쬫⽔혻萙堘벯챐튻즍詪忡ꢝ⨣텋ᱮ⨽轴�顿鰒ḙ헥࿚鄋軸䈓ᨭ潟ᩙ꺵캶닀逸�쒷꒠啩출ᕁ熀䖏ﱶ﷒꼣ḵ侫钅ꈫ쫉ڧ厢簊ﴨࡠ�팢Ԫ∧ᒔ矧飆춪濺࿯뫒糤̀ᩰួ泥閞ﯘ噄ω良䥠ꄴᝧႫ픣촧ᐫ㵘ⱳ㔣ؙ؁䉘眜ⵄ⣑☩픯⽹跌詛栙笰ꯝ灲೸␎덺ߊ쒿盡߃휪띷攺泫᠅嚌姝湔鋥ꔔ୻懲Ꭹ㿰說횁腮ڨ來星�` – Abrar Feb 03 '23 at 13:03
  • This looks like corrupted data. My recommendation: Base64 encode ciphertext and IV on the encrypting side and Base64 decode on the decrypting side. – Topaco Feb 03 '23 at 13:06
  • You can find Base64 <-> ArrayBuffer/TypedArray converters e.g. [here](https://stackoverflow.com/a/11562550/9014097) and [here](https://stackoverflow.com/a/41106346). – Topaco Feb 03 '23 at 13:13
  • @Topaco Thanks, I will try and let you know. But the interesting part is, it still works if I try to encrypt and decrypt inside the same tab. – Abrar Feb 03 '23 at 13:16
  • What does *inside the same tab* mean? That you run encryption and decryption together, as opposed to running them separately? Presumably in the latter case the data is corrupted during transport (copy/paste?) (which should not happen with a Base64 encoding). – Topaco Feb 03 '23 at 13:25
  • @Topaco It worked! Thanks a lot! If you post this as answer, I can mark it as correct answer so other people will get the solution too! – Abrar Feb 04 '23 at 08:12

0 Answers0