pythonpython-2.7rsapycryptojsencrypt

JSEncrypt to PyCrypto RSA encryption not possible


I'm trying to encrypt a string in Javascript using RSA (public key) And I want to decrypt that string in Python (2.7) with my private key.

The Libraries I am using are JSEncrypt and PyCrypto The Problem here is, that PyCrypto has problems to decrypt the encrypted string

This part encrypts the string:

var encrypted = new JSEncrypt();
encrypted.setPublicKey(key); // key == '-----BEGIN PUBLIC'.....
encrypted = encrypted.encrypt('test');

The produced encrypted String looks like this: HJuyZtuUbR4EvjZp0pirbEw0OX8KD7UDNyvSMx3plfzYPjV7r8RBOkouCkvPBG2XOF6E5lPr0ukWClF0u5HB8M6qF8b9xTMnM/j5e41iaPa/oIZyL0JC4h+FZ7cv/P6ygmaSafQ1xc96JltTbuW3u/YYdwmv/01CnFyaIEWW3gk=

This part should decrypt it:

private_rsa_key = open('rsa_1024_priv.pem', 'r').read()
rsa_key = RSA.importKey(private_rsa_key)
decrypted = rsa_key.decrypt(b64decode(encrypted_string))

The result now should be 'test', but indeed it is: enter image description here

The correct string is always being placed at the end, but i need to get rid of the part before it.

For testing purposes I tried encrypting the String in Python, using this code:

public_rsa_key = open('rsa_1024_pub.pem', 'r').read()
rsa_key = RSA.importKey(public_rsa_key)
encrypted = rsa_key.encrypt('test', 'x')

which perfectly turns out 'test' when decrypting, but looks quite different encrypted:

('\x0bY\x1ckk\x7f\xd6\xda$\x05g\xa0\x0bxI\x0cO9\x8b?>M#X\xd2_[\xb7\xf1\xd0f\xb4\x92C\x01z\xa4\x02q\xb9\xb1\x80\x82\xe8\xe4\\E\x85\xa7r\xff\x1aIL,\xd8\xce\xaf\xef\xb4)\x84\x92]\xabA\xc9+\xd6\xef}\x08\xce\xe8\x97\xf8}\x84(\xb3\x9c\xfe7g\xe0\x869\x8b\xe8\xf8\xdf\x85}\xb0\x87\x1a2\xab\xda\xca\xfd\x81\xc0\x98\x12y\x92\x13\xd6\xa5a\xf3\x9aU\xb5\xa4d\xb8\xfc\xa3\xd1\xe2<\x07\xda\xc3\x9e\xc2',)

I am wondering why this encrypted text is now a tuple, with hex inside. As in my opinion the encrypted string from JS looks correct. How could I get PyCrypto to correctly decrypt the string?

Thanks in advance


Solution

  • The python code you posted only does the low level decryption, the encrypted data returned by the jsencrypt also contains pkcs1 padding.

    Instead of using the raw RSA key to encrypt/decrypt in your python code, you need to use the appropriate cipher, in this case PKCS1_v1_5:

    ...
    from Crypto.Cipher import PKCS1_v1_5
    private_rsa_key = open('rsa_1024_priv.pem', 'r').read()
    rsa_key = RSA.importKey(private_rsa_key)
    cipher = PKCS1_v1_5.new(rsa_key)
    decrypted = cipher.decrypt(encrypted, "ERROR")
    

    The same applies when encrypting with the public key.