Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   Loading a PKCS#1 public key using M2Crypto (http://www.velocityreviews.com/forums/t956584-loading-a-pkcs-1-public-key-using-m2crypto.html)

Marc Aymerich 01-16-2013 07:58 PM

Loading a PKCS#1 public key using M2Crypto
 
Hi,
I've been trying very, very hard to load an RSA key using M2Crypto but without any success.

basically this is what I'm trying to do:
>>> from M2Crypto import BIO, RSA
>>>
>>> pubkey = """-----BEGIN RSA PUBLIC KEY-----

.... MIIBCgKCAQEApwotnfHT9RAmxnuaGEMdI3lYPYE4aaqSD9v4Kb Th1E7Le3GNJQb7
.... wCpmDe8+n8S5Kp/gBEpWiYuvsVA/T4KseoX7NMcacP+DJMwjmNd9U58USn2vLz0Z
.... TMtXpc/FUhW5PZdgCiuNzw6IFgGn9ZCCv85jjUIW3KD8fUNdrUfVSv4ol DoL9NkR
.... dTRg3Os/znC6l0gv/mqnLaqj2bJ/tx47kUmj6Oq13JuEq34T+DVmsUCFVundQnRp
.... c/vVEqQot7Rvj9UmSvTi4WKt/qxiAnyZf3gXOdrXvxfVTGzD5I/Xg+By+a4C2JwB
.... A5RGvZP3fyfhkCnnhFDpfws5lc20FA6ryQIDAQAB
.... -----END RSA PUBLIC KEY-----"""
>>>
>>> bio = BIO.MemoryBuffer(pubkey.encode('ascii'))
>>> RSA.load_pub_key_bio(bio)

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/M2Crypto/RSA.py", line 422, in load_pub_key_bio
rsa_error()
File "/usr/lib/python2.7/dist-packages/M2Crypto/RSA.py", line 302, in rsa_error
raise RSAError, m2.err_reason_error_string(m2.err_get_error())
M2Crypto.RSA.RSAError: no start line


Reading all whats in Internet about this problem it seems that my key is in PKCS#1 format but M2Crypto only reads X.501 RSA keys.

I know that python-crypto doesn't have any problem loading this key, but I'll prefer to stick with M2Crypto because I already have lots code using M2Crypto.

So my question is, is there any way to load this key using M2Crypto? Can I convert somehow the key to X.501?

I'll be very, very grateful if someone can come up with an interesting idea!
thanks a lot!!
Marc

Piet van Oostrum 01-17-2013 12:32 AM

Re: Loading a PKCS#1 public key using M2Crypto
 
Marc Aymerich <glicerinu@gmail.com> writes:

> Hi,
> I've been trying very, very hard to load an RSA key using M2Crypto but without any success.
>
> basically this is what I'm trying to do:
>>>> from M2Crypto import BIO, RSA
>>>>
>>>> pubkey = """-----BEGIN RSA PUBLIC KEY-----

> ... MIIBCgKCAQEApwotnfHT9RAmxnuaGEMdI3lYPYE4aaqSD9v4Kb Th1E7Le3GNJQb7
> ... wCpmDe8+n8S5Kp/gBEpWiYuvsVA/T4KseoX7NMcacP+DJMwjmNd9U58USn2vLz0Z
> ... TMtXpc/FUhW5PZdgCiuNzw6IFgGn9ZCCv85jjUIW3KD8fUNdrUfVSv4ol DoL9NkR
> ... dTRg3Os/znC6l0gv/mqnLaqj2bJ/tx47kUmj6Oq13JuEq34T+DVmsUCFVundQnRp
> ... c/vVEqQot7Rvj9UmSvTi4WKt/qxiAnyZf3gXOdrXvxfVTGzD5I/Xg+By+a4C2JwB
> ... A5RGvZP3fyfhkCnnhFDpfws5lc20FA6ryQIDAQAB
> ... -----END RSA PUBLIC KEY-----"""
>>>>
>>>> bio = BIO.MemoryBuffer(pubkey.encode('ascii'))
>>>> RSA.load_pub_key_bio(bio)

> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "/usr/lib/python2.7/dist-packages/M2Crypto/RSA.py", line 422, in load_pub_key_bio
> rsa_error()
> File "/usr/lib/python2.7/dist-packages/M2Crypto/RSA.py", line 302, in rsa_error
> raise RSAError, m2.err_reason_error_string(m2.err_get_error())
> M2Crypto.RSA.RSAError: no start line
>
>
> Reading all whats in Internet about this problem it seems that my key is in PKCS#1 format but M2Crypto only reads X.501 RSA keys.
>
> I know that python-crypto doesn't have any problem loading this key, but I'll prefer to stick with M2Crypto because I already have lots code using M2Crypto.
>
> So my question is, is there any way to load this key using M2Crypto? Can I convert somehow the key to X.501?
>

Converting to X.501 isn't difficult (assuming this is a 2048 bit key):
Get rid of the 'RSA' in header and trailer
Prepend X.501 header 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A' to the data
Reformat the lines to 64 characters.

from M2Crypto import BIO, RSA

pubkey="""-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEApwotnfHT9RAmxnuaGEMdI3lYPYE4aaqSD9v4Kb Th1E7Le3GNJQb7
wCpmDe8+n8S5Kp/gBEpWiYuvsVA/T4KseoX7NMcacP+DJMwjmNd9U58USn2vLz0Z
TMtXpc/FUhW5PZdgCiuNzw6IFgGn9ZCCv85jjUIW3KD8fUNdrUfVSv4ol DoL9NkR
dTRg3Os/znC6l0gv/mqnLaqj2bJ/tx47kUmj6Oq13JuEq34T+DVmsUCFVundQnRp
c/vVEqQot7Rvj9UmSvTi4WKt/qxiAnyZf3gXOdrXvxfVTGzD5I/Xg+By+a4C2JwB
A5RGvZP3fyfhkCnnhFDpfws5lc20FA6ryQIDAQAB
-----END RSA PUBLIC KEY-----
"""

pk = pubkey.split('\n')
pk = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A' + ''.join(pk[1:-2])
pk = [pk[i:i+64] for i in range(0, len(pk), 64)]
pk = '-----BEGIN PUBLIC KEY-----\n' + '\n'.join(pk) + '\n-----END PUBLIC KEY-----'

bio = BIO.MemoryBuffer(pk) # pk is ASCII, don't encode
key = RSA.load_pub_key_bio(bio)

--
Piet van Oostrum <piet@vanoostrum.org>
WWW: http://pietvanoostrum.com/
PGP key: [8DAE142BE17999C4]

Marc Aymerich 01-17-2013 09:16 AM

Re: Loading a PKCS#1 public key using M2Crypto
 
On Thursday, January 17, 2013 1:32:25 AM UTC+1, Piet van Oostrum wrote:
> Marc Aymerich <glicerinu@gmail.com> writes:
>
>
>
> > Hi,

>
> > I've been trying very, very hard to load an RSA key using M2Crypto but without any success.

>
> >

>
> > basically this is what I'm trying to do:

>
> >>>> from M2Crypto import BIO, RSA

>
> >>>>

>
> >>>> pubkey = """-----BEGIN RSA PUBLIC KEY-----

>
> > ... MIIBCgKCAQEApwotnfHT9RAmxnuaGEMdI3lYPYE4aaqSD9v4Kb Th1E7Le3GNJQb7

>
> > ... wCpmDe8+n8S5Kp/gBEpWiYuvsVA/T4KseoX7NMcacP+DJMwjmNd9U58USn2vLz0Z

>
> > ... TMtXpc/FUhW5PZdgCiuNzw6IFgGn9ZCCv85jjUIW3KD8fUNdrUfVSv4ol DoL9NkR

>
> > ... dTRg3Os/znC6l0gv/mqnLaqj2bJ/tx47kUmj6Oq13JuEq34T+DVmsUCFVundQnRp

>
> > ... c/vVEqQot7Rvj9UmSvTi4WKt/qxiAnyZf3gXOdrXvxfVTGzD5I/Xg+By+a4C2JwB

>
> > ... A5RGvZP3fyfhkCnnhFDpfws5lc20FA6ryQIDAQAB

>
> > ... -----END RSA PUBLIC KEY-----"""

>
> >>>>

>
> >>>> bio = BIO.MemoryBuffer(pubkey.encode('ascii'))

>
> >>>> RSA.load_pub_key_bio(bio)

>
> > Traceback (most recent call last):

>
> > File "<stdin>", line 1, in <module>

>
> > File "/usr/lib/python2.7/dist-packages/M2Crypto/RSA.py", line 422, in load_pub_key_bio

>
> > rsa_error()

>
> > File "/usr/lib/python2.7/dist-packages/M2Crypto/RSA.py", line 302, in rsa_error

>
> > raise RSAError, m2.err_reason_error_string(m2.err_get_error())

>
> > M2Crypto.RSA.RSAError: no start line

>
> >

>
> >

>
> > Reading all whats in Internet about this problem it seems that my key is in PKCS#1 format but M2Crypto only reads X.501 RSA keys.

>
> >

>
> > I know that python-crypto doesn't have any problem loading this key, but I'll prefer to stick with M2Crypto because I already have lots code using M2Crypto.

>
> >

>
> > So my question is, is there any way to load this key using M2Crypto? Can I convert somehow the key to X.501?

>
> >

>
> Converting to X.501 isn't difficult (assuming this is a 2048 bit key):
>
> Get rid of the 'RSA' in header and trailer
>
> Prepend X.501 header 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A' to the data
>
> Reformat the lines to 64 characters.
>
>
>
> from M2Crypto import BIO, RSA
>
>
>
> pubkey="""-----BEGIN RSA PUBLIC KEY-----
>
> MIIBCgKCAQEApwotnfHT9RAmxnuaGEMdI3lYPYE4aaqSD9v4Kb Th1E7Le3GNJQb7
>
> wCpmDe8+n8S5Kp/gBEpWiYuvsVA/T4KseoX7NMcacP+DJMwjmNd9U58USn2vLz0Z
>
> TMtXpc/FUhW5PZdgCiuNzw6IFgGn9ZCCv85jjUIW3KD8fUNdrUfVSv4ol DoL9NkR
>
> dTRg3Os/znC6l0gv/mqnLaqj2bJ/tx47kUmj6Oq13JuEq34T+DVmsUCFVundQnRp
>
> c/vVEqQot7Rvj9UmSvTi4WKt/qxiAnyZf3gXOdrXvxfVTGzD5I/Xg+By+a4C2JwB
>
> A5RGvZP3fyfhkCnnhFDpfws5lc20FA6ryQIDAQAB
>
> -----END RSA PUBLIC KEY-----
>
> """
>
>
>
> pk = pubkey.split('\n')
>
> pk = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A' + ''.join(pk[1:-2])
>
> pk = [pk[i:i+64] for i in range(0, len(pk), 64)]
>
> pk = '-----BEGIN PUBLIC KEY-----\n' + '\n'.join(pk) + '\n-----END PUBLIC KEY-----'
>
>
>
> bio = BIO.MemoryBuffer(pk) # pk is ASCII, don't encode
>
> key = RSA.load_pub_key_bio(bio)
>
>



Piet, that was really awesome, it seems so easy to do now :)
Thank you very, very much! really.

Piet van Oostrum 01-17-2013 04:39 PM

Re: Loading a PKCS#1 public key using M2Crypto
 
Piet van Oostrum <piet@vanoostrum.org> wrote:

> Converting to X.501 isn't difficult (assuming this is a 2048 bit key):
> Get rid of the 'RSA' in header and trailer
> Prepend X.501 header 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A' to the data
> Reformat the lines to 64 characters.


This solution is a bit restricted as it only works if the key is 2048
bits and uses an exponent of 65537 (which is the default). Otherwise it
fails.

Here is a robust solution that works for all PKCS#1 keys. Instead of
using a fixed X.501 header it calculates the header. We could do a
complete ASN.1 encoding, but most of the parts are fixed. The only
variable parts are two length fields. So I just plug these into the
fixed stuff. This saves using one of the ASN.1 libraries. We do have to
work in binary (DER format) instead of base64, however.

from M2Crypto import BIO, RSA
import base64

def der_length(length):
"""DER encoding of a length"""
if length < 128:
return chr(length)
prefix = 0x80
result = ''
while length > 0:
result = chr(length & 0xff) + result
length >>= 8
prefix += 1
return chr(prefix) + result

pubkey="""-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEApwotnfHT9RAmxnuaGEMdI3lYPYE4aaqSD9v4Kb Th1E7Le3GNJQb7
wCpmDe8+n8S5Kp/gBEpWiYuvsVA/T4KseoX7NMcacP+DJMwjmNd9U58USn2vLz0Z
TMtXpc/FUhW5PZdgCiuNzw6IFgGn9ZCCv85jjUIW3KD8fUNdrUfVSv4ol DoL9NkR
dTRg3Os/znC6l0gv/mqnLaqj2bJ/tx47kUmj6Oq13JuEq34T+DVmsUCFVundQnRp
c/vVEqQot7Rvj9UmSvTi4WKt/qxiAnyZf3gXOdrXvxfVTGzD5I/Xg+By+a4C2JwB
A5RGvZP3fyfhkCnnhFDpfws5lc20FA6ryQIDAQAB
-----END RSA PUBLIC KEY-----
"""

pk = pubkey.split('\n')
pk = '\0' + base64.decodestring("".join(pk[1:-2]))
pk = '\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\ x01\x05\x00\x03' + \
der_length(len(pk)) + pk
pk = '\x30' + der_length(len(pk)) + pk
pk = '-----BEGIN PUBLIC KEY-----\n' + base64.encodestring(pk) + '-----END PUBLIC KEY-----'

bio = BIO.MemoryBuffer(pk)
key = RSA.load_pub_key_bio(bio)

--
Piet van Oostrum <piet@vanoostrum.org>
WWW: http://pietvanoostrum.com/
PGP key: [8DAE142BE17999C4]

Marc Aymerich 01-17-2013 05:13 PM

Re: Loading a PKCS#1 public key using M2Crypto
 
On Thursday, January 17, 2013 5:39:57 PM UTC+1, Piet van Oostrum wrote:

> > Converting to X.501 isn't difficult (assuming this is a 2048 bit key):

>
> > Get rid of the 'RSA' in header and trailer

>
> > Prepend X.501 header 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A' to the data

>
> > Reformat the lines to 64 characters.

>
>
>
> This solution is a bit restricted as it only works if the key is 2048
>
> bits and uses an exponent of 65537 (which is the default). Otherwise it
>
> fails.
>
>
>
> Here is a robust solution that works for all PKCS#1 keys. Instead of
>
> using a fixed X.501 header it calculates the header. We could do a
>
> complete ASN.1 encoding, but most of the parts are fixed. The only
>
> variable parts are two length fields. So I just plug these into the
>
> fixed stuff. This saves using one of the ASN.1 libraries. We do have to
>
> work in binary (DER format) instead of base64, however.
>


Thank you very much Piet,
I'm just starting to grasp these cryptography related concepts and your code is helping me a lot to understand how to handle these keys in a low level..

I'm updating my code incorporating your new contribution!

Just to let you know, during my previous research I had found a python-Crypto related solution that also uses DER and ASN.1 [1], but it uses a different approach (I guess). I suspect that this approach is also possible with M2Crypto because it has a method for constructing RSA keys [2].

[1] http://stackoverflow.com/a/10574723
[2] http://www.heikkitoivonen.net/m2cryp...ml#new_pub_key


Thanks again!
Marc

PS: Sorry for my email format, I'm using google groups and it seems to ignore any mailing best practice.

Piet van Oostrum 01-17-2013 11:10 PM

Re: Loading a PKCS#1 public key using M2Crypto
 
Marc Aymerich <glicerinu@gmail.com> writes:

> Thank you very much Piet,
> I'm just starting to grasp these cryptography related concepts and your code is helping me a lot to understand how to handle these keys in a low level.
>
> I'm updating my code incorporating your new contribution!
>
> Just to let you know, during my previous research I had found a python-Crypto related solution that also uses DER and ASN.1 [1], but it uses a different approach (I guess). I suspect that this approach is also possible with M2Crypto because it has a method for constructing RSA keys [2].
>
> [1] http://stackoverflow.com/a/10574723
> [2] http://www.heikkitoivonen.net/m2cryp...ml#new_pub_key
>

new_pub_key could be used but then you would have to do an ASN.1 parse
of the DER format of your key to get the n and e values. AFAICT M2Crypto
doesn't have methods to do this, so you would need to use one of the
python ASN.1 libraries (or write that part yourself).
--
Piet van Oostrum <piet@vanoostrum.org>
WWW: http://pietvanoostrum.com/
PGP key: [8DAE142BE17999C4]


All times are GMT. The time now is 12:26 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.