I have a "modulus" as a long string of numbers that is obtained from doing the following:
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
modulus = private_key.private_numbers().public_numbers.n
which gives me this (modulus = )
26430269838726291280672963883929276522234428127706081469034773908296247736139996682259102127358592459713530791841365862493123186868249887704862202193368911366855128282431762151411775448913702006864890463842779084995140786092249248736282702798861993161873918065709700856741944572285079076367907667914080902844624750622976126824522682693806275617591268441477045328753440100516039389493242021813789624216965389245973390154276959750292100226026141811533048330927545995241735560114821851311606450209870516259015344299837790769762906871134121821490748608899823911354842159754168574881499683924223044838326144226160998129721
I want to get this into the usual base64 interpretation of:
0V45nHfQFYZwdC7aES-0zkkhct3PM-fpxp9Lo6QZWmeaXSwS8gQVfJeJhmLp1097qlO3d-n0kblVouvH42LdlWgkzYq-lqP2Ny2M4z3a0VXCdIk1TAxM0Qse-QP6otsIoLKcT2p0JdIEOVeCC9BOLIEcGnWenqHsrm29i-21-zngbREUEQwM7UT55_vgywmJn9fB_NJFz-g7lLyhxwP8gMKSWwhMnQ4oAsRAfefEDr2a_0IPRqQE0r4L2WzgknW6aHex-KZ7LWCgLdLzH5iFUEdfvqJ6MhzlcJtpZQkFhwBVnfKVelCZcDex3TI374dbcvvO-3tVH7Ik4WEukrSgOQ
From a routine I found on the internet, this can be done executing openssl to read a private key PEM encoded file, extract the modulus in hex, and then convert it.
proc = subprocess.Popen(["openssl", "rsa", "-in", "./account.key", "-noout", "-text"], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate(None)
pub_pattern = r"modulus:[\s]+?00:([a-f0-9\:\s]+?)\npublicExponent: ([0-9]+)"
pub_hex, _ = re.search(pub_pattern, out.decode('utf8'), re.MULTILINE|re.DOTALL).groups()
modulus = base64.urlsafe_b64encode(binascii.unhexlify(re.sub(r"(\s|:)", "", pub_hex).encode("utf-8"))).decode('utf8').replace("=", "")
print(pub_hex)
print(modulus)
which gives you:
d1:5e:39:9c:77:d0:15:86:70:74:2e:da:11:2f:
b4:ce:49:21:72:dd:cf:33:e7:e9:c6:9f:4b:a3:a4:
19:5a:67:9a:5d:2c:12:f2:04:15:7c:97:89:86:62:
e9:d7:4f:7b:aa:53:b7:77:e9:f4:91:b9:55:a2:eb:
c7:e3:62:dd:95:68:24:cd:8a:be:96:a3:f6:37:2d:
8c:e3:3d:da:d1:55:c2:74:89:35:4c:0c:4c:d1:0b:
1e:f9:03:fa:a2:db:08:a0:b2:9c:4f:6a:74:25:d2:
04:39:57:82:0b:d0:4e:2c:81:1c:1a:75:9e:9e:a1:
ec:ae:6d:bd:8b:ed:b5:fb:39:e0:6d:11:14:11:0c:
0c:ed:44:f9:e7:fb:e0:cb:09:89:9f:d7:c1:fc:d2:
45:cf:e8:3b:94:bc:a1:c7:03:fc:80:c2:92:5b:08:
4c:9d:0e:28:02:c4:40:7d:e7:c4:0e:bd:9a:ff:42:
0f:46:a4:04:d2:be:0b:d9:6c:e0:92:75:ba:68:77:
b1:f8:a6:7b:2d:60:a0:2d:d2:f3:1f:98:85:50:47:
5f:be:a2:7a:32:1c:e5:70:9b:69:65:09:05:87:00:
55:9d:f2:95:7a:50:99:70:37:b1:dd:32:37:ef:87:
5b:72:fb:ce:fb:7b:55:1f:b2:24:e1:61:2e:92:b4:
a0:39
0V45nHfQFYZwdC7aES-0zkkhct3PM-fpxp9Lo6QZWmeaXSwS8gQVfJeJhmLp1097qlO3d-n0kblVouvH42LdlWgkzYq-lqP2Ny2M4z3a0VXCdIk1TAxM0Qse-QP6otsIoLKcT2p0JdIEOVeCC9BOLIEcGnWenqHsrm29i-21-zngbREUEQwM7UT55_vgywmJn9fB_NJFz-g7lLyhxwP8gMKSWwhMnQ4oAsRAfefEDr2a_0IPRqQE0r4L2WzgknW6aHex-KZ7LWCgLdLzH5iFUEdfvqJ6MhzlcJtpZQkFhwBVnfKVelCZcDex3TI374dbcvvO-3tVH7Ik4WEukrSgOQ
I would like to do this using all python modules, not relying on executing openssl.
Since you already have the modulus as a decimal number, you only have to convert it to a hexadecimal number (with int.to_bytes()
) and then Base64url encode it (with base64.urlsafe_b64encode()
). The Base64 padding can be removed with rstrip()
, e.g.:
import base64
n = 26430269838726291280672963883929276522234428127706081469034773908296247736139996682259102127358592459713530791841365862493123186868249887704862202193368911366855128282431762151411775448913702006864890463842779084995140786092249248736282702798861993161873918065709700856741944572285079076367907667914080902844624750622976126824522682693806275617591268441477045328753440100516039389493242021813789624216965389245973390154276959750292100226026141811533048330927545995241735560114821851311606450209870516259015344299837790769762906871134121821490748608899823911354842159754168574881499683924223044838326144226160998129721
n_bytes = n.to_bytes(2048//8, 'big')
n_b64 = base64.urlsafe_b64encode(n_bytes)
print(n_b64.rstrip(b"=").decode()) # 0V45nHfQFYZwdC7aES-0zkkhct3PM-fpxp9Lo6QZWmeaXSwS8gQVfJeJhmLp1097qlO3d-n0kblVouvH42LdlWgkzYq-lqP2Ny2M4z3a0VXCdIk1TAxM0Qse-QP6otsIoLKcT2p0JdIEOVeCC9BOLIEcGnWenqHsrm29i-21-zngbREUEQwM7UT55_vgywmJn9fB_NJFz-g7lLyhxwP8gMKSWwhMnQ4oAsRAfefEDr2a_0IPRqQE0r4L2WzgknW6aHex-KZ7LWCgLdLzH5iFUEdfvqJ6MhzlcJtpZQkFhwBVnfKVelCZcDex3TI374dbcvvO-3tVH7Ik4WEukrSgOQ