Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I load a password-protected private key from a .pem file with M2Crypto?

I have a password-protected private key in a .pem file; I want to use it to sign requests to a remote server. I'm able to load the key and enter the passphrase after being prompted for it:

python
>>> import M2Crypto
>>> pk = M2Crypto.RSA.load_key('private.pem')
Enter passphrase:
>>>

However, I need this for a server process which is restarted every morning, and thus the passphrase must be passed automatically somehow. The load_key method supports a callback argument for this purpose, so I tried several variants of:

>>> def gimmepw():
...     return 'mysecret'
...
>>> pk = M2Crypto.RSA.load_key('private.pem', gimmepw)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/usr/local/Plone/Python-2.4/.../M2Crypto/RSA.py", line 351, in load_key
    return load_key_bio(bio, callback)
  File "/usr/local/Plone/Python-2.4/.../M2Crypto/RSA.py", line 372, in load_key_bio
    rsa_error()
  File "/usr/local/Plone/Python-2.4/.../M2Crypto/RSA.py", line 302, in rsa_error
    raise RSAError, m2.err_reason_error_string(m2.err_get_error())
M2Crypto.RSA.RSAError: bad password read
>>>

(replace "..." by "lib/python2.4/site-packages")

What am I doing wrong?

like image 874
Tobias Avatar asked May 16 '12 08:05

Tobias


2 Answers

This is due to the lack of parameter support in your callback function. As it will be called with at least one parameter, a TypeError exception will occurred (which is catched by M2Crypto).

>>> def gimmepw(*args):
...     print 'args:', repr(args)
...     return 'test'
... 
>>> M2Crypto.RSA.load_key('key.pem', gimmepw)
args: (0,)
<M2Crypto.RSA.RSA instance at 0xb6e8050c>

You should try:

def gimmepw(*args):
    return 'mysecret'
like image 95
math Avatar answered Oct 14 '22 15:10

math


One caveat: As of Python 2.7, the return value of your callback method must return a str type.

For example, a unicode type will error out in the same way.

>>> def gimmepw(*args):
...     return u'test'
... 
>>> M2Crypto.RSA.load_key('key.pem', gimmepw)
Traceback (most recent call last):
  File "test_intuit_data.py", line 76, in <module>
    intuit_rsa_key = RSA.load_key(file='key.pem', callback=gimmepw)
  File "lib/python2.7/site-packages/M2Crypto/RSA.py", line 351, in load_key
    return load_key_bio(bio, callback)
  File "lib/python2.7/site-packages/M2Crypto/RSA.py", line 372, in load_key_bio
    rsa_error()
  File "lib/python2.7/site-packages/M2Crypto/RSA.py", line 302, in rsa_error
    raise RSAError, m2.err_reason_error_string(m2.err_get_error())
M2Crypto.RSA.RSAError: bad password read

If you are using any input other than a str type, be sure to cast to a str appropriately:

>>> def gimmepw(*args):
...     return str(u'test')
... 
>>> M2Crypto.RSA.load_key('key.pem', gimmepw)
<M2Crypto.RSA.RSA instance at 0xb6e8050c>
like image 37
Luciano Avatar answered Oct 14 '22 16:10

Luciano