Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I have a RSA public key exponent and modulus. How can I encrypt a string using Python?

Given a public key exponent and modulus like the following, how can I encrypt a string and send it to a server as text?

publicKey: 10001,
modulus: 'd0eeaf178015d0418170055351711be1e4ed1dbab956603ac04a6e7a0dca1179cf33f90294782e9db4dc24a2b1d1f2717c357f32373fb3d9fd7dce91c40b6602'

I am trying to replicate the functionality provided by the javascript rsa library http://www.ohdave.com/rsa/ in python. In javascript, it looks something like this:

setMaxDigits(67); //sets a max digits for bigInt
var key = new RSAKeyPair('10001', '10001', 'd0eeaf178015d0418170055351711be1e4ed1dbab956603ac04a6e7a0dca1179cf33f90294782e9db4dc24a2b1d1f2717c357f32373fb3d9fd7dce91c40b6602');
var encrypted = encryptedString(key, 'message');
console.log(encrypted); //prints '88d58fec172269e5186592dd20446c594dbeb82c01edad41f841666500c9a530e24a282c6527ec66f4c826719f12478c6535bdc2baef86e4ff26906a26398413'

I imagine there is a way to do this with the PyCrypto library but I couldn't find any examples that use the exponent and modulus.

Edit 1:

Using the solution below, it appears to be working. Since I'm using python 2.7 I modified it to look like this:

from Crypto.PublicKey.RSA import construct
from binascii import unhexlify
from codecs import encode

e = long(10001)
n = int(encode('d0eeaf17801.....5d041817005535171', 'hex'), 16)

key = construct((n, e))
a = key.encrypt('hello', None)
print(a)

('.X?\xdc\x81\xfb\x9b(\x0b\xa1\xc6\xf7\xc0\xa3\xd7}U{Q?\xa6VR\xbdJ\xe9\xc5\x1f\x
f9i+\xb2\xf7\xcc\x8c&_\x9bD\x00\x86}V[z&3\\]_\xde\xed\xdc~\xf2\xe1\xa9^\x96\xc3\
xd5R\xc2*\xcb\xd9\x1d\x88$\x98\xb0\x07\xfaG+>G#\xf7cG\xd8\xa6\xf3y_ 4\x17\x0b\x0
3z\x0cvk7\xf7\xebPyo-\xa1\x81\xf5\x81\xec\x17\x9e\xfe3j\x98\xf2\xd5\x80\x1d\xdd\
xaf\xa4\xc8I\xeeB\xdaP\x85\xa7',)

Now I want to convert this encrypted text to a string to send via a post request. But this doesn't seem to work:

a.decode('utf-8')
like image 246
twoLeftFeet Avatar asked Oct 17 '16 19:10

twoLeftFeet


1 Answers

With PyCrypto, you can use the Crypto.PublicKey.RSA.construct() function. You'll need to convert the modulus to an int. Here's an example (assuming big-endian):

from Crypto.PublicKey.RSA import construct

e = int('10001', 16)
n = int('d0eeaf...0b6602', 16)  #snipped for brevity
pubkey = construct((n, e))

Then you can do the usual things (like encrypt) with the key:

from Crypto.Cipher import PKCS1_OAEP

cipher = PKCS1_OAEP.new(pubkey)
ciphertext = cipher.encrypt(b'abcde')

Edit: Note that your public exponent, 10001, is mostly likely hexadecimal. This would correspond to the common public exponent 65537. I've updated the above to reflect that.

like image 74
glibdud Avatar answered Sep 22 '22 18:09

glibdud