pythonhexrsaasn.1

Obtain RSA exponent and modulus from public key with Python


I know how to obtain RSA modulus and exponent from public key using openssl, but now i tried it to do with Python. I've seen this and followed steps.

Suppose this is the public key:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdZGziIrJOlRomzh7M9qzo4ibw
QmwORcVDI0dsfUICLUVRdUN+MJ8ELd55NKsfYy4dZodWX7AmdN02zm1Gk5V5i2Vw
GVWE205u7DhtRe85W1oR9WTsMact5wuqU6okJd2GKrEGotgd9iuAJm90N6TDeDZ4
KHEvVEE1yTyvrxQgkwIDAQAB
-----END PUBLIC KEY-----

First, public key is decoded from base64:

import base64
bytearray = base64.b64decode("""MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdZGziIrJOlRomzh7M9qzo4ibw
QmwORcVDI0dsfUICLUVRdUN+MJ8ELd55NKsfYy4dZodWX7AmdN02zm1Gk5V5i2Vw
GVWE205u7DhtRe85W1oR9WTsMact5wuqU6okJd2GKrEGotgd9iuAJm90N6TDeDZ4
KHEvVEE1yTyvrxQgkwIDAQAB""")
print(bytearray)

output:

0\x81\x9f0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x81\x8d\x000\x81\x89\x02\x81\x81\x00\x9ddl\xe2"\xb2N\x95\x1a&\xce\x1e\xcc\xf6\xac\xe8\xe2&\xf0Bl\x0eE\xc5C#Gl}B\x02-EQuC~0\x9f\x04-\xdey4\xab\x1fc.\x1df\x87V_\xb0&t\xdd6\xcemF\x93\x95y\x8bep\x19U\x84\xdbNn\xec8mE\xef9[Z\x11\xf5d\xec1\xa7-\xe7\x0b\xaaS\xaa$%\xdd\x86*\xb1\x06\xa2\xd8\x1d\xf6+\x80&ot7\xa4\xc3x6x(q/TA5\xc9<\xaf\xaf\x14 \x93\x02\x03\x01\x00\x01

Then, byte array is converted to base 16 (hexadecimal) string:

bytearray.encode('hex')

output:

30819f300d06092a864886f70d010101050003818d00308189028181009d646ce222b24e951a26ce1eccf6ace8e226f0426c0e45c54323476c7d42022d455175437e309f042dde7934ab1f632e1d6687565fb02674dd36ce6d469395798b6570195584db4e6eec386d45ef395b5a11f564ec31a72de70baa53aa2425dd862ab106a2d81df62b80266f7437a4c378367828712f544135c93cafaf1420930203010001

and for the design, let's add ":" between every two character in the string:

':'.join([ i+j for i,j in zip(bytearray[::2],bytearray[1::2])])

output:

30:81:9f:30:0d:06:09:2a:86:48:86:f7:0d:01:01:01:05:00:03:81:8d:00:30:81:89:02:81:81:00:9d:64:6c:e2:22:b2:4e:95:1a:26:ce:1e:cc:f6:ac:e8:e2:26:f0:42:6c:0e:45:c5:43:23:47:6c:7d:42:02:2d:45:51:75:43:7e:30:9f:04:2d:de:79:34:ab:1f:63:2e:1d:66:87:56:5f:b0:26:74:dd:36:ce:6d:46:93:95:79:8b:65:70:19:55:84:db:4e:6e:ec:38:6d:45:ef:39:5b:5a:11:f5:64:ec:31:a7:2d:e7:0b:aa:53:aa:24:25:dd:86:2a:b1:06:a2:d8:1d:f6:2b:80:26:6f:74:37:a4:c3:78:36:78:28:71:2f:54:41:35:c9:3c:af:af:14:20:93:02:03:01:00:01

But, unfortunately, i couldn't understand the last step. I know that output includes both exponent and modulus, but there are other characters to filter out (since they can't be converted back to base 10). I also known that hex representation above is based on ASN.1 syntax, so there should be some specific offset in hex representation where these two values will appear.

What needs to be done to obtain modulus and exponent from this result?

Thanks!


Solution

  • The public key is in the ASN.1 SubjectPublicKeyInfo format, also known in the Java world as an X509EncodedKeySpec. Many crypt packages can import such an object directly.

    For example, using PyCrypto and Cryptography.io, the following snippet

    from Crypto.PublicKey import RSA
    key_encoded='''-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdZGziIrJOlRomzh7M9qzo4ibw
    QmwORcVDI0dsfUICLUVRdUN+MJ8ELd55NKsfYy4dZodWX7AmdN02zm1Gk5V5i2Vw
    GVWE205u7DhtRe85W1oR9WTsMact5wuqU6okJd2GKrEGotgd9iuAJm90N6TDeDZ4
    KHEvVEE1yTyvrxQgkwIDAQAB
    -----END PUBLIC KEY-----'''
    
    
    pubkey = RSA.importKey(key_encoded)
    print(pubkey.n)
    print(pubkey.e)
    
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives import serialization
    
    pubkey2 = serialization.load_pem_public_key(
        key_encoded.encode('ascii'),
        backend=default_backend()
    )
    
    print(pubkey2.public_numbers().n)
    print(pubkey2.public_numbers().e)
    

    produces

    110524622184298189406696366981362867320131527048683492811128204661745388510505145389459518039217549444918405620726988722254633562452576638635488354260221598432448974859895979017211032905988949400704082939941050902513120244660937339078367607684436944094809985731012813959774525636937965082155868293686780764307
    65537
    110524622184298189406696366981362867320131527048683492811128204661745388510505145389459518039217549444918405620726988722254633562452576638635488354260221598432448974859895979017211032905988949400704082939941050902513120244660937339078367607684436944094809985731012813959774525636937965082155868293686780764307
    65537