Olá% username%!

Na discussão das 
notícias do Passport 
, surgiram discussões acaloradas sobre a segurança das mais recentes embarcações dos autores do Telegram.
Vamos ver como ele criptografa seus dados pessoais e falar sobre o verdadeiro ponto a ponto.
Em poucas palavras, como o Passport funciona.
- Localmente, usando uma senha, você criptografa seus dados pessoais (nome, email, verificação de passaporte, outros documentos).
- Dados criptografados + meta-informações são carregados na nuvem do Telegram.
- Quando você precisa fazer login no serviço, o cliente baixa os dados da nuvem, descriptografa-os com uma senha, descriptografa-os para a chave pública do serviço que solicitou as informações e os envia.
Vamos considerar a primeira parte, que se refere à criptografia e armazenamento de dados pessoais.
End to End, de acordo com os desenvolvedores, reside no fato de que a nuvem do Telegram não pode decifrar seus dados pessoais, mas apenas vê "ruído aleatório".
Vamos analisar mais de perto o código do algoritmo de criptografia para dados pessoais do cliente de desktop localizado 
aqui e ver se o resultado do seu trabalho atende aos critérios de ponta a ponta.
Tudo começa com uma senha. Aqui é o lugar onde ele se transforma em uma chave de criptografia intermediária.
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.

 :
- ,
« », , , . , AES (2^256).
Telegram , HMAC.
:
- , (GPU)
- (AES-NI)
- .
- - SHA-512 (GPU)
- (AES-NI)
- 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 
, .