Dit artikel over MTProto ‘ s End-to-End encryptie is bedoeld voor gevorderde gebruikers.Als je meer wilt weten over geheime Chats van een minder intimiderende bron, zie dan onze Algemene veelgestelde vragen.
merk op dat vanaf Versie 4.6 grote Telegram clients MTProto 2.0 gebruiken.MTProto V. 1. 0 is verouderd en wordt momenteel afgebouwd.
geheime Chats zijn een-op-een chats waarin berichten worden versleuteld met een sleutel die alleen door de deelnemers van de chat wordt vastgehouden. Merk op dat het schema voor deze end-to-end versleutelde geheime Chats verschilt van wat wordt gebruikt voor cloud chats:
een notitie op MTProto 2.0
Dit artikel beschrijft de end-to-end encryptie laag in het MTProto protocol versie 2.0.De belangrijkste verschillen met Versie 1.0 (hier ter referentie beschreven) zijn als volgt:
- SHA-256 wordt gebruikt in plaats van SHA-1;
- Padding bytes zijn betrokken bij de berekening van msg_key;
- msg_key hangt niet alleen af van het te versleutelen bericht, maar ook van een deel van de geheime chatsleutel;
- 12..1024 padding bytes worden gebruikt in plaats van 0..15 vulling bytes in v. 1. 0.
zie ook: MTProto 2.0: Cloud Chats, Server-client encryptie
Sleutelgeneratie
sleutels worden gegenereerd met behulp van het Diffie-Hellman protocol.
laten we het volgende scenario overwegen: gebruiker A wil end-to-end versleutelde communicatie met gebruiker B initiëren.
een verzoek verzenden
gebruiker A voert berichten uit.getDhConfig om de Diffie-Hellman parameters te verkrijgen: een priemgetal p, en een high order element g.
het uitvoeren van deze methode voor elke nieuwe sleutel generatie procedure is van vitaal belang. Het is zinvol om de waarden van de parameters samen met de versie in cache om te voorkomen dat alle waarden elke keer ontvangen. Als de versie die op de client is opgeslagen nog steeds up-to-date is, zal de server de constructorberichten retourneren.dhconfignot gewijzigd.
Client wordt verwacht om te controleren of p is een veilige 2048-bits prime (dit betekent dat zowel de p-en (p-1)/2 priem zijn, en dat 2^2047 < p < 2^2048), en dat g genereert een cyclische subgroepen van eerste orde (p-1)/2, dat wil zeggen is een kwadratische residu mod p. Sinds g is altijd gelijk aan 2, 3, 4, 5, 6 of 7, dit is gemakkelijk te doen met behulp van kwadratische reciprociteit wet, waardoor een eenvoudige voorwaarde op p mod 4g — namelijk, p mod 8 = 7 g = 2; p mod 3 = 2 g = 3; geen extra voorwaarde voor g = 4; p mod 5 = 1 of 4 voor g = 5; p mod 24 = 19 of 23 voor g = 6; en P mod 7 = 3, 5 of 6 voor g = 7. Nadat g en p zijn gecontroleerd door de client, is het zinvol om het resultaat in de cache te plaatsen, om te voorkomen dat lange berekeningen in de toekomst worden herhaald. Deze cache kan worden gedeeld met een die wordt gebruikt voor het genereren van Autorisatiesleutels.
als de client een inadequate Random number generator heeft, is het zinvol om de random_length parameter (random_length> 0) door te geven, zodat de server zijn eigen willekeurige volgorde van de juiste lengte genereert.Belangrijk: het gebruik van de willekeurige volgorde van de server in zijn ruwe vorm kan onveilig zijn. Het moet worden gecombineerd met een clientreeks, bijvoorbeeld door een willekeurig clientnummer van dezelfde lengte te genereren (client_random) en final_random := random XOR client_random
te gebruiken.
Client a berekent een 2048 – bit nummer a (met behulp van voldoende entropie of de server ‘ s random; zie hierboven) en voert berichten uit.requestencryptie na het doorgeven van g_a := pow(g, a) mod dh_prime
.
gebruiker B ontvangt de update updateencryptie voor alle geassocieerde autorisatiesleutels (alle geautoriseerde apparaten) met de chat constructor encryptedChatRequested. De gebruiker moet worden getoond basisinformatie over Gebruiker A en moet worden gevraagd om het verzoek te accepteren of af te wijzen.
beide clients moeten controleren of g, g_a en g_b groter zijn dan één en kleiner dan p-1. We raden aan om te controleren of g_a en g_b ook tussen 2^{2048-64} en p – 2^{2048-64} liggen.
een verzoek accepteren
nadat gebruiker B de creatie van een geheime chat met A in de client interface bevestigt, ontvangt Client B ook up-to-date configuratieparameters voor de Diffie-Hellman methode. Daarna genereert het een willekeurig 2048-bit nummer, b, met behulp van regels die vergelijkbaar zijn met die voor a.
nadat g_a is ontvangen van de update met encryptedChatRequested, kan het onmiddellijk de laatste gedeelde sleutel genereren: key = (pow(g_a, b) mod dh_prime)
. Als key length < 256 bytes, voeg dan een aantal voorloopnul bytes toe als padding — zodat de sleutel precies 256 bytes lang is. De vingerafdruk, key_fingerprint, is gelijk aan de 64 laatste bits van SHA1 (key).
Opmerking 1: in dit specifieke geval wordt SHA1 hier zelfs gebruikt voor MTProto 2.0 secret chats.
noot 2: deze vingerafdruk wordt gebruikt als een sanity check voor de sleutel uitwisseling procedure om bugs te detecteren bij het ontwikkelen van client software-het is niet verbonden met de sleutel visualisatie gebruikt op de clients als middel van externe authenticatie in geheime chats. Belangrijke visualisaties op de clients worden gegenereerd met behulp van de eerste 128 bits van SHA1(intial key) gevolgd door de eerste 160 bits van SHA256(key gebruikt toen secret chat werd bijgewerkt naar layer 46).
Client B voert berichten uit.acceptencryptie na het doorgeven g_b := pow(g, b) mod dh_prime
en key_fingerprint.
voor alle geautoriseerde apparaten van Client B, behalve de huidige, worden updateencryptieupdates verzonden met de versleutelde versleuteling van de constructor. Daarna, het enige apparaat dat in staat om toegang te krijgen tot de geheime chat zal zijn Apparaat B, die de oproep naar berichten gemaakt.acceptencryptie.
gebruiker A zal een updateencryptie-update ontvangen met de versleutelde chat van de constructor, voor de autorisatiesleutel die de chat heeft geïnitieerd.
met g_b van de update kan Client A ook de gedeelde sleutel key = (pow(g_b, a) mod dh_prime)
berekenen. Als key length < 256 bytes, voeg dan een aantal voorloopnul bytes toe als padding — zodat de sleutel precies 256 bytes lang is. Als de vingerafdruk voor de ontvangen sleutel identiek is aan die welke is doorgegeven aan encryptedChat, kunnen inkomende berichten worden verzonden en verwerkt. Anders, berichten.discardencryptie moet worden uitgevoerd en de gebruiker verwittigd.
Perfect Forward Secrecy
om communicatie uit het verleden veilig te houden, zullen officiële Telegram-clients opnieuw Keyen starten zodra een sleutel is gebruikt om meer dan 100 berichten te ontcijferen en te versleutelen, of langer dan een week in gebruik is geweest, op voorwaarde dat de sleutel is gebruikt om ten minste één bericht te versleutelen. Oude sleutels worden dan veilig weggegooid en kunnen niet worden gereconstrueerd, zelfs niet met toegang tot de nieuwe sleutels die momenteel in gebruik zijn.
Het re-keying protocol wordt verder beschreven in dit artikel: Perfect Forward Secrecy in Secret Chats.
houd er rekening mee dat uw client Forward Secrecy moet ondersteunen in geheime Chats om compatibel te zijn met officiële Telegram-clients.
verzenden en ontvangen van berichten in een geheime Chat
serialisatie en versleuteling van uitgaande berichten
een TL-object van het type DecryptedMessage wordt aangemaakt en bevat het bericht in platte tekst. Voor achterwaartse compatibiliteit moet het object worden verpakt in de constructor decryptedMessageLayer met een indicatie van de ondersteunde laag (beginnend met 46).
Het tl-Schema voor de inhoud van end-to-end versleutelde berichten is hier beschikbaar”
de resulterende constructie wordt geserialiseerd als een array van bytes met behulp van generieke tl-regels. De resulterende array wordt voorafgegaan door 4 bytes die de array lengte bevatten zonder deze 4 bytes te tellen.
de byte array is opgevuld met 12 tot 1024 random padding bytes om de lengte deelbaar te maken door 16 bytes. (In de oudere MTProto 1.0 encryptie werden slechts 0 tot 15 padding bytes gebruikt.)
Message key, msg_key, wordt berekend als de 128 middelste bits van SHA256 van de gegevens die in de vorige stap zijn verkregen, met 32 bytes van de gedeelde sleutel. (Voor de oudere MTProto 1.0 encryptie, msg_key werd anders berekend, als de 128 lagere bits van SHA1 van de gegevens verkregen in de vorige stappen, met uitzondering van de padding bytes.)
voor MTProto 2.0 worden de AES-sleutel aes_key en initialisatievector aes_iv als volgt berekend ( sleutel is de gedeelde sleutel die wordt verkregen tijdens het genereren van sleutels):
- MSG_KEY_LARGE = SHA256 (substr (key, 88+x, 32) + plaintext + random_padding);
- msg_key = substr (msg_key_large, 8, 16);
- sha256_a = SHA256 (msg_key + substr (toets, x, 36));
- sha256_b = SHA256 (substr (sleutel, 40+x, 36) + msg_key);
- aes_key = substr (sha256_a, 0, 8) + substr (sha256_b, 8, 16) + substr (sha256_a, 24, 8);
- aes_iv = substr (sha256_b, 0, 8) + substr (sha256_a, 8, 16) + substr (sha256_b, 24, 8);
Voor MTProto 2.0, x=0 voor de berichten van de afzender van het geheim chat, x=8 voor de berichten in de tegenovergestelde richting.
voor de verouderde MTProto 1.0, msg_key, aes_key, en aes_iv werden anders berekend (zie dit document voor referentie).
gegevens worden versleuteld met een 256-bit sleutel, aes_key en een 256-bit initialisatievector, aes-iv, met behulp van AES-256 encryptie met infinite garble extension (IGE). Encryptiesleutel vingerafdruk key_fingerprint en de message key msg_key worden toegevoegd aan de bovenkant van de resulterende byte array.
versleutelde gegevens zijn ingebed in een bericht.sendencrypted API call en doorgegeven aan Telegram server voor levering aan de andere partij van de geheime Chat.
upgraden naar MTProto 2.0 van MTProto 1.0
zodra beide partijen in een geheime chat tenminste Layer 73 gebruiken, moeten ze alleen MTProto 2.0 gebruiken voor alle uitgaande berichten. Sommige van de eerste ontvangen berichten kunnen gebruik maken van MTProto 1.0, als een voldoende hoge startlaag niet is onderhandeld tijdens de creatie van de geheime chat. Nadat het eerste bericht dat met MTProto 2.0 is versleuteld (of het eerste bericht met laag 73 of hoger) is ontvangen, moeten alle berichten met hogere volgnummers ook met MTProto 2.0 worden versleuteld.
zolang de huidige laag lager is dan 73, moet elke partij proberen om ontvangen berichten te decoderen met MTProto 1.0, en als dit niet succesvol is (msg_key komt niet overeen), probeer MTProto 2.0. Zodra het eerste MTProto 2.0-versleutelde bericht arriveert (of de laag is opgewaardeerd naar 73), is het niet nodig om MTProto 1.0-decryptie uit te proberen voor een van de volgende berichten (tenzij de client nog steeds wacht op een aantal hiaten die worden gedicht).
decoderen van een binnenkomend bericht
de bovenstaande stappen worden in omgekeerde volgorde uitgevoerd. Wanneer een versleuteld bericht wordt ontvangen, moet je controleren of msg_key in feite gelijk is aan de 128 middelste bits van de SHA256 hash van het gedecodeerde bericht, vooraf gezet door 32 bytes genomen van de gedeelde sleutel.Als de berichtenlaag groter is dan die welke door de client wordt ondersteund, moet de gebruiker worden geïnformeerd dat de clientversie verouderd is en worden gevraagd om bij te werken.
volgnummers
het is noodzakelijk alle berichten in hun oorspronkelijke volgorde te interpreteren om te beschermen tegen mogelijke manipulaties. Secret chats ondersteunen een speciaal mechanisme voor het verwerken van seq_no tellers onafhankelijk van de server.
de juiste behandeling van deze tellers wordt verder beschreven in dit artikel: Sequence numbers in Secret Chats.
houd er rekening mee dat uw client sequentienummers moet ondersteunen in geheime Chats om compatibel te zijn met officiële Telegram-clients.
versleutelde bestanden verzenden
alle bestanden die naar geheime chats worden verzonden, worden versleuteld met eenmalige sleutels die op geen enkele manier gerelateerd zijn aan de gedeelde sleutel van de chat. Voordat een versleuteld bestand wordt verzonden, wordt aangenomen dat het adres van het versleutelde bestand aan de buitenkant van een versleuteld bericht wordt bevestigd met behulp van de bestandsparameter van de berichten.sendencryptedfile methode en dat de sleutel voor directe decryptie zal worden verzonden in de body van het bericht (de sleutel parameter in de constructors decryptedMessageMediaPhoto, decryptedMessageMediaVideo en decryptedMessageMediaFile.
voordat een bestand naar een geheime chat wordt verzonden, worden 2 willekeurige 256-bit getallen berekend die zullen dienen als de AES-sleutel en initialisatievector die worden gebruikt om het bestand te versleutelen. AES-256 encryptie met infinite garble extensie (IGE) wordt gebruikt op dezelfde manier.
de key fingerprint wordt als volgt berekend:
- digest = md5(key + iv)
- fingerprint = substr(digest, 0, 4) XOR substr(digest, 4, 4)
de versleutelde inhoud van een bestand wordt op dezelfde manier opgeslagen als die van een bestand in cloudchats: stuk voor stuk met behulp van oproepen om te uploaden.saveFilePart.Een volgende oproep naar berichten.sendEncryptedFile zal een identifier toewijzen aan het opgeslagen bestand en het adres samen met het bericht verzenden. De ontvanger ontvangt een update met encryptedMessage, en de bestandsparameter bevat bestandsinformatie.
inkomende en uitgaande versleutelde bestanden kunnen worden doorgestuurd naar andere geheime chats met behulp van de constructor inputEncryptedFile om te voorkomen dat dezelfde inhoud twee keer op de server wordt opgeslagen.
werken met een Update Box
geheime chats worden geassocieerd met specifieke apparaten (of liever met autorisatiesleutels), niet met gebruikers. Een conventioneel berichtenvenster, dat pts gebruikt om de status van de client te beschrijven, is niet geschikt, omdat het is ontworpen voor langdurige berichtopslag en berichttoegang vanaf verschillende apparaten.
een extra tijdelijke berichtenwachtrij wordt geïntroduceerd als een oplossing voor dit probleem. Wanneer een update met betrekking tot een bericht van een geheime chat wordt verzonden, wordt een nieuwe waarde van qts verzonden, die helpt het verschil te reconstrueren als er een lange onderbreking is geweest in de verbinding of in geval van verlies van een update.
naarmate het aantal gebeurtenissen toeneemt, neemt de waarde van qts met 1 toe bij elke nieuwe gebeurtenis. De initiële waarde mag niet (en zal niet) gelijk zijn aan 0.
het feit dat gebeurtenissen uit de tijdelijke wachtrij door de client zijn ontvangen en opgeslagen, wordt expliciet bevestigd door een aanroep naar de berichten.receivedQueue methode of impliciet door een oproep tot updates.getDifference (de waarde van qts doorgegeven, niet de uiteindelijke status). Alle berichten die door de client worden bevestigd als geleverd, evenals alle berichten ouder dan 7 dagen, kunnen (en zullen) van de server worden verwijderd.
na de-autorisatie zal de gebeurteniswachtrij van het overeenkomstige apparaat met geweld worden gewist en zal de waarde van qts irrelevant worden.
bijwerken naar nieuwe lagen
uw client moet altijd de maximale laag opslaan waarvan bekend is dat deze door de client wordt ondersteund aan de andere kant van een geheime chat. Wanneer de geheime chat voor het eerst wordt gemaakt, moet deze waarde worden geïnitialiseerd naar 46. Deze remote layer waarde moet altijd worden bijgewerkt onmiddellijk na het ontvangen van een pakket met informatie van een bovenste laag, d.w.z.:
- elk geheim chatbericht met layer_no in zijn
decryptedMessageLayer
met laag>=46, of - een decryptedMessageActionNotifyLayer service-bericht, verpakt alsof het de decryptedMessageService-constructor van de verouderde laag 8 (constructor
decryptedMessageService#aa48327d
).
de externe client informeren over uw lokale laag
om de externe client op de hoogte te stellen van uw lokale laag, moet uw client een bericht sturen met hetdecryptedMessageActionNotifyLayer
type. Deze kennisgeving moet worden verpakt in een constructeur van een geschikte laag.
Er zijn twee gevallen waarin uw client de externe client op de hoogte moet stellen van zijn lokale laag:
- zodra een nieuwe geheime chat is aangemaakt, onmiddellijk nadat de geheime sleutel met succes is uitgewisseld.
- onmiddellijk nadat de lokale client is bijgewerkt om een nieuwe geheime chatlaag te ondersteunen. In dit geval moeten meldingen worden verzonden naar alle bestaande geheime chats. Merk op dat dit alleen nodig is bij het updaten naar nieuwe lagen die veranderingen bevatten in de geheime chats implementatie (bijv. u hoeft dit niet te doen wanneer uw client wordt bijgewerkt van laag 46 naar laag 47).