مرحبًا٪ username٪!

في مناقشة
أخبار Passport
، نشأت مناقشات ساخنة حول أمن أحدث مركبة من مؤلفي Telegram.
دعونا نرى كيف تقوم بتشفير بياناتك الشخصية ونتحدث عن النهاية الحقيقية.
باختصار ، كيف يعمل Passport.
- محليًا ، باستخدام كلمة مرور ، تقوم بتشفير بياناتك الشخصية (الاسم ، البريد الإلكتروني ، مسح جواز السفر ، المستندات الأخرى).
- يتم تحميل البيانات المشفرة + المعلومات الوصفية إلى سحابة Telegram.
- عندما تحتاج إلى تسجيل الدخول إلى الخدمة ، يقوم العميل بتنزيل البيانات من السحابة ، وفك تشفيرها بكلمة مرور ، وفك تشفيرها إلى المفتاح العام للخدمة التي تطلب المعلومات ، وإرسالها.
سننظر في الجزء الأول ، الذي يتعلق بتشفير وتخزين البيانات الشخصية.
وفقًا للمطورين ، فإن End to End تكمن في حقيقة أنه من المفترض أن سحابة Telegram لا يمكنها فك تشفير بياناتك الشخصية ، ولكنها ترى فقط "ضوضاء عشوائية".
دعنا نلقي نظرة فاحصة على كود خوارزمية التشفير للبيانات الشخصية من عميل سطح المكتب الموجود
هنا ومعرفة ما إذا كانت نتيجة عملها تستوفي معايير النهاية إلى النهاية.
كل شيء يبدأ بكلمة مرور. هنا هو المكان الذي يتحول فيه إلى مفتاح تشفير متوسط.
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
, .