PyCrypto: Encode chinese charaters with RSA asymmetric key

I am trying to use PyCrypto to encrypt/decrypt some strings, and I am having troubles with Chinese characters.

When I try to encrypt "ni-hao" (hello)...

pemFile = open("/home/borrajax/keys/myKey.pem", "r")
encryptor = RSA.importKey(pemFile, passphrase="f00")
return encryptor.encrypt("你好", 0)[0]

... I keep getting errors:

Module Crypto.PublicKey.pubkey:64 in encrypt         
>>  ciphertext=self._encrypt(plaintext, K)
Module Crypto.PublicKey.RSA:92 in _encrypt         
>>  return (self.key._encrypt(c),)
ValueError: Plaintext too large

I have tried many combinations,

encryptor.encrypt(u"你好"...
encryptor.encrypt(u"你好".encode("utf-8")...

without any luck.

I guess I could always try to use base64 before encoding, but I'd like to leave that as a "last resource"... I was hoping for a more "elegant" way of doing this.

Has anyone encountered the same problems? Any hint will be appreciated. Thank you in advance.

Answers


First, you should be encrypting only binary data, not Unicode text. That means str type (in Python 2.x) or bytes (in Python 3.x and most recent Python 2.x). You must encode text before encrypting it, and you must decode it after you decrypt.

Second, the byte string you are encrypting must be smaller than the RSA modulus (e.g. less than 256 bytes for RSA2048). If your data is longer, think of using an intermediate AES session key.

Third, if you use PyCrypto 2.5, there is no good reason for using the .encrypt/.decrypt methods of the RSA key object. It is better and more secure to use one of the PKCS#1 methods: OAEP or v1.5. With them, the plaintext must be even shorter.


I tested with PyCrypto v2.5 installed from pip on Ubuntu Linux 10.04 on python 2.6.5 in the interactive interpreter from the yakuake terminal.

I'm not able to reproduce the error you're seeing, especially the "Plaintext too large" bit. Some errors I have seen:

encryptor.encrypt(u"你好",0)[0]

TypeError: argument 1 must be long, not unicode

Seems like it doesn't like unicode objects - only wants str.

Both of these work on my setup, and both produce the same output, however the first solution is more correct:

encryptor.encrypt(u"你好".encode("utf-8"), 0)[0]
encryptor.encrypt("你好", 0)[0]

Are you trying this from the interactive interpreter, or from a file? If file, is the file UTF-8 encoded? If console, does it have proper UTF-8 support?


I checked related codes of PyCrypto, this error is only thrown when plain-text (after converted to long) is bigger than one of the key parameter. Assuming encoding of the script is correctly set, it may be because your RSA key is invalid or too short. I tried this snippet, it works with no problem:

rsa = RSA.generate(1024)

print(rsa.encrypt("你好", 0))

Need Your Help

How do I prevent using the incorrect type in PHP?

php oop type-safety

PHP, as we all know is very loosely typed. The language does not require you to specify any kind of type for function parameters or class variables. This can be a powerful feature.

Corona sdk chains example app

sdk lua corona

I am working on a Corona sdk lua app for Android devices that does something similar to the example corona chains app. I would like to make a pivot joint to join two of the chains together at the l...