mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-04-21 01:21:59 +03:00
Update RSA encryption to use the new RSA_PAD
This makes the server not return -404 when using newer RSA keys.
This commit is contained in:
parent
4078243dad
commit
d4288fd696
|
@ -1,10 +1,10 @@
|
|||
import os
|
||||
import struct
|
||||
from hashlib import sha1
|
||||
from hashlib import sha1, sha256
|
||||
|
||||
from rsa import PublicKey, encrypt
|
||||
from rsa import PublicKey
|
||||
|
||||
from ..tl.core import serialize_bytes_to
|
||||
from .aes import ige_encrypt
|
||||
|
||||
|
||||
def compute_fingerprint(key: PublicKey) -> int:
|
||||
|
@ -16,12 +16,49 @@ def compute_fingerprint(key: PublicKey) -> int:
|
|||
return fingerprint
|
||||
|
||||
|
||||
def encrypt_hashed(data: bytes, key: PublicKey, random_data: bytes) -> bytes:
|
||||
# Cannot use `rsa.encrypt` because it's not deterministic and requires its own padding.
|
||||
padding_length = 235 - len(data)
|
||||
assert padding_length >= 0 and len(random_data) >= padding_length
|
||||
to_encrypt = sha1(data).digest() + data + random_data[:padding_length]
|
||||
payload = int.from_bytes(to_encrypt)
|
||||
def encrypt_hashed(data: bytes, key: PublicKey, random_bytes: bytes) -> bytes:
|
||||
# https://core.telegram.org/mtproto/auth_key#41-rsa-paddata-server-public-key-mentioned-above-is-implemented-as-follows
|
||||
|
||||
# data_with_padding := data + random_padding_bytes; -- where random_padding_bytes are chosen so that the resulting length of data_with_padding is precisely 192 bytes, and data is the TL-serialized data to be encrypted as before. One has to check that data is not longer than 144 bytes.
|
||||
if len(data) > 144:
|
||||
raise ValueError("data must be 144 bytes at most")
|
||||
|
||||
data_with_padding = data + random_bytes[: 192 - len(data)]
|
||||
|
||||
# data_pad_reversed := BYTE_REVERSE(data_with_padding); -- is obtained from data_with_padding by reversing the byte order.
|
||||
data_pad_reversed = data_with_padding[::-1]
|
||||
|
||||
attempt = 0
|
||||
while 192 + 32 * attempt + 32 <= len(random_bytes):
|
||||
# a random 32-byte temp_key is generated.
|
||||
temp_key = random_bytes[192 + 32 * attempt : 192 + 32 * attempt + 32]
|
||||
|
||||
# data_with_hash := data_pad_reversed + SHA256(temp_key + data_with_padding); -- after this assignment, data_with_hash is exactly 224 bytes long.
|
||||
data_with_hash = (
|
||||
data_pad_reversed + sha256(temp_key + data_with_padding).digest()
|
||||
)
|
||||
|
||||
# aes_encrypted := AES256_IGE(data_with_hash, temp_key, 0); -- AES256-IGE encryption with zero IV.
|
||||
aes_encrypted = ige_encrypt(data_with_hash, temp_key, bytes(32))
|
||||
|
||||
# temp_key_xor := temp_key XOR SHA256(aes_encrypted); -- adjusted key, 32 bytes
|
||||
temp_key_xor = bytes(
|
||||
a ^ b for a, b in zip(temp_key, sha256(aes_encrypted).digest())
|
||||
)
|
||||
|
||||
# key_aes_encrypted := temp_key_xor + aes_encrypted; -- exactly 256 bytes (2048 bits) long
|
||||
key_aes_encrypted = temp_key_xor + aes_encrypted
|
||||
|
||||
# The value of key_aes_encrypted is compared with the RSA-modulus of server_pubkey as a big-endian 2048-bit (256-byte) unsigned integer. If key_aes_encrypted turns out to be greater than or equal to the RSA modulus, the previous steps starting from the generation of new random temp_key are repeated. Otherwise the final step is performed:
|
||||
if int.from_bytes(key_aes_encrypted) < key.n:
|
||||
break
|
||||
|
||||
attempt += 1
|
||||
else:
|
||||
raise RuntimeError("ran out of entropy")
|
||||
|
||||
# encrypted_data := RSA(key_aes_encrypted, server_pubkey); -- 256-byte big-endian integer is elevated to the requisite power from the RSA public key modulo the RSA modulus, and the result is stored as a big-endian integer consisting of exactly 256 bytes (with leading zero bytes if required).
|
||||
payload = int.from_bytes(key_aes_encrypted)
|
||||
encrypted = pow(payload, key.e, key.n)
|
||||
return encrypted.to_bytes(256)
|
||||
|
||||
|
@ -53,41 +90,3 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
|||
RSA_KEYS = {
|
||||
compute_fingerprint(key): key for key in (PRODUCTION_RSA_KEY, TESTMODE_RSA_KEY)
|
||||
}
|
||||
|
||||
RSA_KEYS.clear()
|
||||
for pub in (
|
||||
"""-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
|
||||
lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
|
||||
an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
|
||||
Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
|
||||
8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
|
||||
Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----""",
|
||||
"""-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBCgKCAQEAxq7aeLAqJR20tkQQMfRn+ocfrtMlJsQ2Uksfs7Xcoo77jAid0bRt
|
||||
ksiVmT2HEIJUlRxfABoPBV8wY9zRTUMaMA654pUX41mhyVN+XoerGxFvrs9dF1Ru
|
||||
vCHbI02dM2ppPvyytvvMoefRoL5BTcpAihFgm5xCaakgsJ/tH5oVl74CdhQw8J5L
|
||||
xI/K++KJBUyZ26Uba1632cOiq05JBUW0Z2vWIOk4BLysk7+U9z+SxynKiZR3/xdi
|
||||
XvFKk01R3BHV+GUKM2RYazpS/P8v7eyKhAbKxOdRcFpHLlVwfjyM1VlDQrEZxsMp
|
||||
NTLYXb6Sce1Uov0YtNx5wEowlREH1WOTlwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----""",
|
||||
"""-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBCgKCAQEAsQZnSWVZNfClk29RcDTJQ76n8zZaiTGuUsi8sUhW8AS4PSbPKDm+
|
||||
DyJgdHDWdIF3HBzl7DHeFrILuqTs0vfS7Pa2NW8nUBwiaYQmPtwEa4n7bTmBVGsB
|
||||
1700/tz8wQWOLUlL2nMv+BPlDhxq4kmJCyJfgrIrHlX8sGPcPA4Y6Rwo0MSqYn3s
|
||||
g1Pu5gOKlaT9HKmE6wn5Sut6IiBjWozrRQ6n5h2RXNtO7O2qCDqjgB2vBxhV7B+z
|
||||
hRbLbCmW0tYMDsvPpX5M8fsO05svN+lKtCAuz1leFns8piZpptpSCFn7bWxiA9/f
|
||||
x5x17D7pfah3Sy2pA+NDXyzSlGcKdaUmwQIDAQAB
|
||||
-----END RSA PUBLIC KEY-----""",
|
||||
"""-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBCgKCAQEAwqjFW0pi4reKGbkc9pK83Eunwj/k0G8ZTioMMPbZmW99GivMibwa
|
||||
xDM9RDWabEMyUtGoQC2ZcDeLWRK3W8jMP6dnEKAlvLkDLfC4fXYHzFO5KHEqF06i
|
||||
qAqBdmI1iBGdQv/OQCBcbXIWCGDY2AsiqLhlGQfPOI7/vvKc188rTriocgUtoTUc
|
||||
/n/sIUzkgwTqRyvWYynWARWzQg0I9olLBBC2q5RQJJlnYXZwyTL3y9tdb7zOHkks
|
||||
WV9IMQmZmyZh/N7sMbGWQpt4NMchGpPGeJ2e5gHBjDnlIf2p1yZOYeUYrdbwcS0t
|
||||
UiggS4UeE8TzIuXFQxw7fzEIlmhIaq3FnwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----""",
|
||||
):
|
||||
key = PublicKey.load_pkcs1(pub.encode("ascii"))
|
||||
RSA_KEYS[compute_fingerprint(key)] = key
|
||||
|
|
|
@ -19,11 +19,18 @@ def test_fingerprint_2() -> None:
|
|||
|
||||
def test_rsa_encryption() -> None:
|
||||
key = PublicKey(
|
||||
n=22081946531037833540524260580660774032207476521197121128740358761486364763467087828766873972338019078976854986531076484772771735399701424566177039926855356719497736439289455286277202113900509554266057302466528985253648318314129246825219640197356165626774276930672688973278712614800066037531599375044750753580126415613086372604312320014358994394131667022861767539879232149461579922316489532682165746762569651763794500923643656753278887871955676253526661694459370047843286685859688756429293184148202379356802488805862746046071921830921840273062124571073336369210703400985851431491295910187179045081526826572515473914151,
|
||||
n=25342889448840415564971689590713473206898847759084779052582026594546022463853940585885215951168491965708222649399180603818074200620463776135424884632162512403163793083921641631564740959529419359595852941166848940585952337613333022396096584117954892216031229237302943701877588456738335398602461675225081791820393153757504952636234951323237820036543581047826906120927972487366805292115792231423684261262330394324750785450942589751755390156647751460719351439969059949569615302809050721500330239005077889855323917509948255722081644689442127297605422579707142646660768825302832201908302295573257427896031830742328565032949,
|
||||
e=65537,
|
||||
)
|
||||
result = encrypt_hashed(b"Hello!", key, bytes(256))
|
||||
assert (
|
||||
result
|
||||
== b"up-L\x88\xd2\x9bj\xb945Q$\xdd(\xd9\xb6*GU\x88A\xc8\x03\x14P\xf7I\x9b\x1c\x9ck\xd3\x9d'\xc1X\x1cQ4NQ\xc1y#pd\xa7#\xae\x93\x9dZ\xc3P\x14\xfd\x8bO\xe2Ou\xe3\x11\\2\xa1ci\xee+7:a\xec\x94F\xb9+.=\xf0v\x18\xdb\n\x8a\xfd\xa9\x99\xb6p+2\xb5\x81\x9b\xd6\xeaIp\xfb4|\xa8J`\xd0\xc3\x8a\xb7\x0cf\xe5\xed\x01@D\x88\x89\xa3\xb8\x82\xee\xa53\xba\xd0^\xfa E\xed\xa7\x17\x12<AJ\xbf\xde\xd4>\x1e\xb4\x83\xa0Ixn\xf5\x03\x1b\x12\xd5\x1a?\xf7\xec\xb7\xd8\x04\xd4A5\x94_\x98\xf7ZJl\xf1\xa1\xdf7U\x9e0\xbb\xe9*Kyf\xc3O\x078\xe6\xd10Y\x85wm&\xdf\xab|\x0f\xdf\xd7\xec ,\xc7\x8cT\xcf\x82\xac#\x86\xc7\x9d\x0e\x19u\x80\xa4\xfa\x940\n#\x82\xf9\xe1\x16\xfe\x82\xdf\x9b\xd8r\xe5\xb9\xda{Bb#\xbf\x1a\xd8X\x890\xb5\x1e\x16]l\xdd\x02"
|
||||
result = encrypt_hashed(
|
||||
bytes.fromhex(
|
||||
"955ff5a9081a8e635f5743de9b00000004453dc27100000004622f1fcb000000f7a81627bbf511fa4afef71e94a0937474586c1add9198dda81a5df8393871c8293623c5fb968894af1be7dfe9c7be813f9307789242fd0cb0c16a5cb39a8d3e"
|
||||
),
|
||||
key,
|
||||
bytes.fromhex(
|
||||
"12270000635593b03fee033d0672f9afddf9124de9e77df6251806cba93482e4c9e6e06e7d44e4c4baae821aff91af44789689faaee9bdfc7b2df8c08709afe57396c4638ceaa0dc30114f82447e81d3b53edc423b32660c43a5b8ad057b64500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007dada0920c4973913229e0f881aec7b9db0c392d34f52fb0995ea493ecb4c09daaf68fe9554ec7a59c03e4035952b220b47a8d06aad71134110d8c44948901f8"
|
||||
),
|
||||
)
|
||||
assert result == bytes.fromhex(
|
||||
"c6d211349fc10cda6983276250b09f4be9b39f533b5d314b732b51a6dd72234dab4224209992c894e0e4c9f30249f1dbbd1630a27b98f2f92a53c00baabbd46f380bd35f417e5ec2edb43f7644b5c81af011d736eb369265e848b553ae5e6350dd5695efc72bde0e35f3c3fc827b91eb97cf1efdbff12269b9c33f81645adebc89ed167edc19d285237a754bf629aa358ed08498863b2aec8b7139001627bbe8bdef239474a5a43e664d278f39e72d694a206d7b838fd40868a71c4bfbffa38b7679faa502b7795cbe5ae1bd05ca7eb01ff5b05107265fd39bd5b4e19d392b735a3b0b5b21473062981bff86ff9084a7b594775e3127c05fd454e19f794a4ab4"
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue
Block a user