2

I want to encrypt a message using RSA with a provided PEM public key in Javascript, using SubtleCrypto window.crypto.subtle and then decode it with Python (PyCryptodome) in the back-end. However, I get a ValueError: Incorrect decryption.. I'm not sure if the data is being correctly handled though. Here is my code:

JavaScript:

var publicKey;
var pemPublicKey = `public.pem key with stripped header and footer and newlines (just the base64 data)`;

function base64ToArrayBuffer(b64) {
    var byteString = window.atob(b64);
    var byteArray = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) { byteArray[i] = byteString.charCodeAt(i); }
    return byteArray;
}

function arrayBufferToBase64(buffer) {
    var binary = '';
    var bytes = new Uint8Array(buffer);
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) { binary += String.fromCharCode(bytes[i]); }
    return window.btoa(binary);
}

window.crypto.subtle.importKey(
    "spki",
    base64ToArrayBuffer(pemPublicKey),
    { name: "RSA-OAEP", hash: { name: "SHA-256" } },
    false,
    ["encrypt"])
    .then(function (key) {
        publicKey = key
    })

console.log(publicKey)

var enc = new TextEncoder()
var encmessage = enc.encode("test14")

var encryptedData;
window.crypto.subtle.encrypt({
    name: "RSA-OAEP"
}, publicKey, encmessage).then(function (encrypted) { encryptedData = encrypted })

var encodedData = arrayBufferToBase64(encryptedData);
console.log(encodedData)

What the code above does is convert the public PEM key, generate a CryptoKey object out of it (using crypto.subtle.importKey) and then encrypts a simple message "test14".

Python backend:

import base64
from Cryptodome.PublicKey import RSA
from Cryptodome.Cipher import AES, PKCS1_OAEP

with open('private.pem', 'r') as f: keypair = RSA.import_key(f.read())
decryptor = PKCS1_OAEP.new(keypair)
decrypted = decryptor.decrypt(base64.b64decode(encrypted))  # encrypted is the data that is returned by JavaScript code
print(decrypted)

1 Answer 1

2

Directly from the documentation of Crypto.Cipher.PKCS1_OAEP.new(key, hashAlgo=None, mgfunc=None, label='', randfunc=None):

...

  • hashAlgo (hash object) - The hash function to use. This can be a module under Crypto.Hash or an existing hash object created from any of such modules. If not specified, Crypto.Hash.SHA1 is used.

...

Sign up to request clarification or add additional context in comments.

3 Comments

For some reason I thought SHA-256 was the default. Changing to SHA-1 in Javascript code fixed it, thanks!
SHA-1 is the (slightly unfortunate) default in the PKCS#1 v2.x standards. It's secure for this type of function but SHA-256 would have been the better choice.
And my general advice is never to use the default value always define it, especially in Cryptographic implementation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.