Warum Telegrammpass - kein Ende zu Ende

Hallo% Benutzername%!



In der Diskussion über Passport- Nachrichten kam es von den Autoren von Telegram zu heftigen Diskussionen über die Sicherheit des neuesten Fahrzeugs.

Lassen Sie uns sehen, wie es Ihre persönlichen Daten verschlüsselt, und über das wahre End-to-End sprechen.

Kurz gesagt, wie Passport funktioniert.

  • Vor Ort verschlüsseln Sie Ihre persönlichen Daten (Name, E-Mail, Pass-Scan, andere Dokumente) mit einem Passwort.
  • Verschlüsselte Daten + Metainformationen werden in die Telegrammwolke hochgeladen.
  • Wenn Sie sich beim Dienst anmelden müssen, lädt der Client die Daten aus der Cloud herunter, entschlüsselt sie mit einem Kennwort, entschlüsselt sie in den öffentlichen Schlüssel des Dienstes, der die Informationen angefordert hat, und sendet sie.

Wir werden den ersten Teil betrachten, der sich auf die Verschlüsselung und Speicherung personenbezogener Daten bezieht.

End to End liegt laut den Entwicklern in der Tatsache, dass die Telegramm-Cloud Ihre persönlichen Daten angeblich nicht entschlüsseln kann, sondern nur „zufälliges Rauschen“ sieht.

Schauen wir uns den Code des Verschlüsselungsalgorithmus für persönliche Daten vom Desktop-Client hier genauer an und prüfen Sie, ob das Ergebnis seiner Arbeit die End-to-End-Kriterien erfüllt.

Alles beginnt mit einem Passwort. Hier wird es zu einem Zwischenverschlüsselungsschlüssel.

bytes::vector CountPasswordHashForSecret(
		bytes::const_span salt,
		bytes::const_span password) {
	return openssl::Sha512(bytes::concatenate(
		salt,
		password,
		salt));
}

, SHA-512. . !

2018 . GPU SHA-512 . 10 GPU 8- 94 ( , , ) 5 .

, GPU, Telegram .

. , :

bytes::vector GenerateSecretBytes() {
	auto result = bytes::vector(kSecretSize);
	memset_rand(result.data(), result.size());
	const auto full = ranges::accumulate(
		result,
		0ULL,
		[](uint64 sum, gsl::byte value) { return sum + uchar(value); });
	const auto mod = (full % 255ULL);
	const auto add = 255ULL + 239 - mod;
	auto first = (static_cast<uchar>(result[0]) + add) % 255ULL;
	result[0] = static_cast<gsl::byte>(first);
	return result;
}

, .

«», HMAC AEAD , , , 239, :

bool CheckBytesMod255(bytes::const_span bytes) {
	const auto full = ranges::accumulate(
		bytes,
		0ULL,
		[](uint64 sum, gsl::byte value) { return sum + uchar(value); });
	const auto mod = (full % 255ULL);
	return (mod == 239);
}

-, . , , HMAC, .

. , . , :

EncryptedData EncryptData(
		bytes::const_span bytes,
		bytes::const_span dataSecret) {
	constexpr auto kFromPadding = kMinPadding + kAlignTo - 1;
	constexpr auto kPaddingDelta = kMaxPadding - kFromPadding;
	const auto randomPadding = kFromPadding
		+ (rand_value<uint32>() % kPaddingDelta);
	const auto padding = randomPadding
		- ((bytes.size() + randomPadding) % kAlignTo);
	Assert(padding >= kMinPadding && padding <= kMaxPadding);

	auto unencrypted = bytes::vector(padding + bytes.size());
	Assert(unencrypted.size() % kAlignTo == 0);

	unencrypted[0] = static_cast<gsl::byte>(padding);
	memset_rand(unencrypted.data() + 1, padding - 1);
	bytes::copy(
		gsl::make_span(unencrypted).subspan(padding),
		bytes);


32 255 .
dataHash. , .

	const auto dataHash = openssl::Sha256(unencrypted);
	const auto bytesForEncryptionKey = bytes::concatenate(
		dataSecret,
		dataHash);

	auto params = PrepareAesParams(bytesForEncryptionKey);
	return {
		{ dataSecret.begin(), dataSecret.end() },
		{ dataHash.begin(), dataHash.end() },
		Encrypt(unencrypted, std::move(params))
	};
}

. SHA-512 , dataHash.


:

  1. ,

« », , , . , AES (2^256).

Telegram , HMAC.

:

  1. , (GPU)
  2. (AES-NI)
  3. .
  4. - SHA-512 (GPU)
  5. (AES-NI)
  6. SHA-256, , :

if (padding < kMinPadding
		|| padding > kMaxPadding
		|| padding > decrypted.size()) {

, , . . GPU, AES-NI. , , . , ?

, , Don't roll your own crypto , End-to-End, .

, , , .

End-to-End


E2E , . , .

, , , , . Signal, (WhatsApp, etc). , , , .

, . .

Telegram , . , , .

P.S. E2E, VirgilSecurity , .

Source: https://habr.com/ru/post/de418535/


All Articles