كيف يعمل TOTP: الخوارزمية وراء رموز تطبيق المصادقة لديك
تنسخ رمزاً من ستة أرقام من تطبيق مصادقة بضع مرات أسبوعياً، وبطريقة ما يظهر الرمز نفسه على هاتفك ويطابق ما يتوقّعه الخادم، رغم أنهما لا يتبادلان أي حديث. فكيف يعمل TOTP إذاً؟ السرّ المشترك ذاته يُنتج رقماً جديداً كل 30 ثانية، والجواب خوارزمية صغيرة حتمية يُجريها الطرفان كلٌّ على حدة. لا رمز يعبر الشبكة، ولا خادم مركزي يوزّع الرقم.
TOTP (كلمة مرور لمرّة واحدة قائمة على الوقت — Time-based One-Time Password)، المعرّفة في RFC 6238، تحوّل سرّاً مشتركاً مضافاً إليه الوقت الحالي إلى رمز رقمي قصير، عبر إجراء HMAC على الوقت ثم اقتطاع النتيجة. والمصادقة الثنائية (2FA) تتوقّف على حساب الطرفين القيمة نفسها دون تبادلها، فالخوارزمية وحدها هي ما يقوم عليه التوثيق.
يستعرض هذا الدليل الخوارزمية من أولها إلى آخرها بأرقام ملموسة، ثم يغطّي النصف الذي يتجاوزه معظم الشروح: كيف يتحقّق الخادم من الرمز فعلاً، وما الذي توقفه 2FA وما لا توقفه. يمكنك حساب رمز حيّ في مولّد TOTP لدينا أثناء القراءة.
ما هو TOTP؟
TOTP (كلمة مرور لمرّة واحدة قائمة على الوقت)، المعرّفة في RFC 6238، خوارزمية تجمع سرّاً مشتركاً مع الوقت الحالي لإنتاج رمز قصير يتجدّد على فترات ثابتة. يحمل كلٌّ من تطبيق المصادقة والخادم السرّ نفسه، ويقرآن الساعة نفسها، ويُجريان الحساب نفسه، فيصلان إلى الرمز نفسه دون أن يرسلاه قطّ.
والنقطة الأخيرة هي الأهم. لا يُرسَل الرمز أثناء الإعداد، يُرسَل السرّ فقط، وبعد ذلك يشتقّ كل طرف الرموز بمفرده. فلا شيء على الشبكة يمكن اعتراضه سوى السرّ لحظة التسجيل، والأرقام الستة التي يكتبها المستخدم عند الدخول. والصورة بسيطة: ثلاثة مدخلات تُعطي مخرجاً واحداً:
| المدخل | الدور | القيمة النموذجية |
|---|---|---|
| السرّ المشترك | المفتاح طويل الأمد، يُتفَّق عليه مرة عند التسجيل | JBSWY3DPEHPK3PXP (Base32) |
| الخطوة الزمنية | العدّاد الذي يمضي قُدُماً | نافذة من 30 ثانية |
| المخرج | الرمز القصير المشتقّ من الاثنين | 324550 |
يُكتَب السرّ في كل الأحوال تقريباً بترميز Base32 (الحروف A–Z والأرقام 2–7)، لأن تلك الأبجدية لا تفرّق بين الأحرف الكبيرة والصغيرة، وتصمد عند طباعتها أو كتابتها أو حزمها في رمز QR. تسجّل السرّ بمسح معرّف otpauth://، الذي يمكنك عرضه على هيئة رمز QR للمصادقة، أو بكتابة سلسلة Base32 يدوياً.
TOTP وHOTP وSMS ومفاتيح المرور: مشهد المصادقة الثنائية 2FA
TOTP خيار واحد من بين عدّة خيارات، ولاختياره عن بيّنة يلزم النظر إلى البقية. وأبسط طريقة لربطها: TOTP هو HOTP نفسه، لكن مع استبدال العدّاد بعدد الخطوات الزمنية منذ مبدأ زمن يونكس (Unix epoch). وما عدا ذلك مفاضلة بين مقاومة التصيّد والراحة والبنية التحتية التي تحتاجها.
| الآلية | المحرّك | عمر الرمز | مقاوِمة للتصيّد؟ | تحتاج شبكة؟ | الاستخدام النموذجي |
|---|---|---|---|---|---|
| HOTP (RFC 4226) | عدّاد تصاعدي | حتى يُستخدَم | لا | لا | الرموز العتادية، الأنظمة القديمة |
| TOTP (RFC 6238) | الوقت الحالي | نحو 30 ثانية | لا | لا (بعد التسجيل) | تطبيقات المصادقة |
| SMS OTP | الخادم يرسل رمزاً | بضع دقائق | لا | نعم (شبكة خلوية) | احتياطي للمستهلكين |
| موافقة بالدفع (Push) | الخادم يطلب من جهاز | لكل طلب | جزئياً | نعم | 2FA قائمة على تطبيق |
| مفتاح مرور / FIDO2 | تحدٍّ بالمفتاح العام | لكل طلب | نعم (مرتبط بالأصل) | نعم | الحسابات الحديثة |
يعمل TOTP وHOTP دون اتصال بعد التسجيل، فيبقيان متاحين ويحفظان الخصوصية، لكن أياً منهما ليس مقاوماً للتصيّد بمفرده: فصفحة مزيّفة مقنعة يمكنها طلب الرمز ثم إعادة إرساله. تضيف SMS قناة شبكية تجلب معها سطح هجوم خاصاً بها. أما مفاتيح المرور فتسدّ ثغرة التصيّد بربط بيانات الاعتماد بأصل الموقع (origin)، ولهذا تتّجه الصناعة نحوها. ويقف TOTP في موضع وسط مريح: قوي ومنتشر ومجاني، ولهذا ظلّ شائعاً.
كيف تعمل خوارزمية TOTP خطوة بخطوة
إليك الخوارزمية كاملة في أربع خطوات. سنُجري كلاً منها بالسرّ الاختباري الوارد في الـRFC وهو JBSWY3DPEHPK3PXP، ووقت يونكس ثابت قدره 1700000000، بحيث يكون كل رقم قابلاً لإعادة الإنتاج.
- فُكّ ترميز سرّ Base32 إلى بايتات المفتاح الخام.
- احسب عدّاد الخطوة الزمنية من وقت يونكس الحالي.
- أجرِ HMAC على العدّاد بمفتاح السرّ.
- اقتطع البصمة إلى رمز من ستة أرقام.
الخطوة 1 — فكّ ترميز سرّ Base32 إلى بايتات
يحزم Base32 خمسة بِتّات في كل محرف. ويُعيد فاكّ الترميز تجميع المحارف إلى بايتات من ثمانية بِتّات. يُفكّ ترميز السرّ JBSWY3DPEHPK3PXP إلى البايتات العشرة الخام 48 65 6c 6c 6f 21 de ad be ef. هذه المصفوفة من البايتات، لا السلسلة القابلة للطباعة، هي مفتاح HMAC.
الخطوة 2 — احسب عدّاد الخطوة الزمنية
العدّاد هو عدد الخطوات الزمنية الكاملة المنقضية منذ نقطة بداية: T = floor((unixTime − T0) / period). والقيم الافتراضية في الـRFC هي T0 = 0 (مبدأ زمن يونكس) وperiod = 30. وبجعل unixTime = 1700000000، نحصل على T = floor(1700000000 / 30) = 56666666. ثم يُرمَّز هذا العدد الصحيح كقيمة من ثمانية بايتات بترتيب الأكثر أهمية أولاً (big-endian): 00 00 00 00 03 60 aa 2a. ولأن العدّاد لا يتغيّر إلا عند بدء نافذة جديدة من 30 ثانية، يظلّ كل رمز ثابتاً طوال نافذة واحدة ثم يقفز.
الخطوة 3 — أجرِ HMAC على العدّاد بالسرّ
تُجري الخوارزمية HMAC-SHA1 على العدّاد المؤلّف من ثمانية بايتات، مستخدمةً بايتات السرّ مفتاحاً. وHMAC دالّة مُمفتَحة أحادية الاتجاه: دون السرّ لا يمكنك عكس البصمة ولا تزوير بصمة صحيحة، وهذا ما يجعل الرمز غير قابل للتزوير. ولمدخلاتنا تكون البصمة هي البايتات العشرين 1d 70 6e 94 1a c7 6b 6d 4a 46 dd 6f af a4 5f e3 35 11 bf 86.
الخطوة 4 — اقتطاع ديناميكي إلى رمز من ستة أرقام (RFC 4226)
بصمة من عشرين بايتاً أطول من أن تُكتَب، فيستخرج الاقتطاع الديناميكي في RFC 4226 رقماً منها. خذ النصف الأدنى (low nibble) من البايت الأخير كإزاحة: البايت الأخير هو 0x86، ونصفه الأدنى 6، فتكون الإزاحة 6. اقرأ أربعة بايتات بدءاً من تلك الإزاحة (6b 6d 4a 46)، واطمس البِتّ الأعلى من البايت الأول لإبقاء الرقم موجباً، فينتج العدد الصحيح 1802324550. اختزله بأخذ باقي قسمته على 10^6 ثم املأ الفراغ بأصفار: 1802324550 % 1000000 = 324550. هذا هو الرمز الذي يعرضه تطبيقك لهذا السرّ في هذه اللحظة.
إليك الخوارزمية بلغة جافاسكربت باستخدام واجهة Web Crypto الأصلية في المتصفّح، دون أي اعتماديات. كل تعليق يربط كتلة بإحدى الخطوات الأربع أعلاه:
// TOTP وفق RFC 6238 — SHA-1، 6 أرقام، فترة 30 ثانية (القيم الافتراضية).
async function generateTotp(base32Secret, unixTime = Date.now() / 1000) {
// الخطوة 1: فكّ ترميز سرّ Base32 (A-Z, 2-7) إلى بايتات المفتاح الخام.
const alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
let bits = '';
for (const ch of base32Secret.replace(/=+$/, '').toUpperCase()) {
bits += alpha.indexOf(ch).toString(2).padStart(5, '0');
}
const keyBytes = new Uint8Array(
bits.match(/.{8}/g).map((b) => parseInt(b, 2)));
// الخطوة 2: العدّاد = عدد خطوات 30 ثانية منذ المبدأ (8 بايتات big-endian).
let counter = Math.floor(unixTime / 30);
const msg = new Uint8Array(8);
for (let i = 7; i >= 0; i--) {
msg[i] = counter & 0xff;
counter = Math.floor(counter / 256);
}
// الخطوة 3: HMAC-SHA1 للعدّاد بمفتاح السرّ.
const key = await crypto.subtle.importKey(
'raw', keyBytes, { name: 'HMAC', hash: 'SHA-1' }, false, ['sign']);
const hmac = new Uint8Array(await crypto.subtle.sign('HMAC', key, msg));
// الخطوة 4: اقتطاع ديناميكي (RFC 4226) -> رمز من 6 أرقام.
const offset = hmac[hmac.length - 1] & 0x0f;
const binary = ((hmac[offset] & 0x7f) << 24) | (hmac[offset + 1] << 16) |
(hmac[offset + 2] << 8) | hmac[offset + 3];
return (binary % 1_000_000).toString().padStart(6, '0');
}
const code = await generateTotp('JBSWY3DPEHPK3PXP', 1700000000);
console.log(code); // -> "324550"
والخوارزمية نفسها بلغة بايثون، باستخدام المكتبة القياسية فقط (hmac وstruct):
import base64, hmac, hashlib, struct, time
def totp(secret, for_time=None, period=30, digits=6, digest='sha1'):
if for_time is None:
for_time = time.time()
# الخطوة 1: فكّ ترميز Base32 للسرّ إلى بايتات المفتاح الخام.
key = base64.b32decode(secret.upper())
# الخطوة 2: العدّاد = عدد الخطوات الزمنية منذ المبدأ (8 بايتات big-endian).
counter = int(for_time // period)
msg = struct.pack(">Q", counter)
# الخطوة 3: HMAC للعدّاد بالسرّ.
h = hmac.new(key, msg, digest).digest()
# الخطوة 4: اقتطاع ديناميكي (RFC 4226) -> رمز من N أرقام.
offset = h[-1] & 0x0f
binary = ((h[offset] & 0x7f) << 24 |
(h[offset + 1] & 0xff) << 16 |
(h[offset + 2] & 0xff) << 8 |
(h[offset + 3] & 0xff))
return str(binary % (10 ** digits)).zfill(digits)
print(totp('JBSWY3DPEHPK3PXP', 1700000000)) # -> 324550
يطبع كلا التنفيذين 324550 لوقتنا الثابت، وكلاهما يعيد إنتاج المتجهات الاختبارية الرسمية لـRFC 6238 (مثلاً، متجه SHA-1 عند T = 59 يعطي 94287082). وإن استبدلت SHA-1 بـSHA-256 أو SHA-512، أو غيّرت عدد الأرقام، فعلى المُتحقِّق في الطرف الآخر أن يطابق الخيارات نفسها تماماً، وإلا فلن تتّفق الرموز أبداً.
التحقّق من رمز TOTP على الخادم
توليد الرمز نصف المنظومة. أما النصف الآخر فهو قرار الخادم بقبول الأرقام الستة التي كتبها المستخدم لتوّه أو رفضها، وتلك الخطوة تحمل كل المفاضلات الحسّاسة أمنياً.
لا يخزّن الخادم الرموز. يخزّن السرّ، وعند الدخول يعيد حساب الرمز المتوقّع من ذلك السرّ ومن الوقت الحالي، ثم يقارن. والمعضلة هي انحراف الساعة: نادراً ما يتّفق جهاز المستخدم والخادم على الثانية ذاتها بالضبط، فأي فحص مساواة صارم سيرفض الرموز قرب حدود النافذة. والحلّ نافذة تحقّق (validation window) صغيرة. اقبل الخطوة الحالية وخطوة واحدة على كل جانب، أي تحقّق من رموز العدّادات T−1 وT وT+1. النافذة الأوسع تحتمل انحرافاً أكبر لكنها توسّع سطح التخمين، لذا فالنافذة 1 (تسامح قدره ±30 ثانية) هي التوازن الشائع. ويمكنك ملاحظة تسامح ±الخطوة الواحدة هذا في تبويب التحقّق بأداة المولّد.
import { createHmac, timingSafeEqual } from 'crypto';
function verifyTotp(secret, code, { window = 1, period = 30, digits = 6 } = {}) {
const counter = Math.floor(Date.now() / 1000 / period);
const submitted = Buffer.from(code);
// افحص الخطوة الحالية و±window خطوات لانحراف الساعة.
for (let i = -window; i <= window; i++) {
const expected = Buffer.from(totpAt(secret, counter + i, digits));
// مقارنة بزمن ثابت كي لا يُسرّب التوقيت تطابقاً جزئياً.
if (expected.length === submitted.length &&
timingSafeEqual(expected, submitted)) {
return counter + i; // الخطوة المتطابقة — خزّنها لمنع إعادة التشغيل
}
}
return false;
}
تفصيلان آخران ينقلان هذا من «يعمل» إلى «آمن». أولاً، منع إعادة التشغيل (replay prevention): خزّن آخر عدّاد قبلته لكل مستخدم، وارفض أي رمز من خطوة عنده أو دونه، كي لا يُعاد استخدام رمز التُقِط مرة واحدة داخل النافذة نفسها. ولهذا تُعيد verifyTotp الخطوة المتطابقة بدلاً من true مجرّدة. ثانياً، تحديد المعدّل (rate limiting): رمز من ستة أرقام واحد من مليون قيمة، ونافذة ±1 تجعل ثلاثة منها صحيحة في أي لحظة، فبلا كبح يستطيع المهاجم تجريب الفضاء كله بالقوة الغاشمة. أقفل الحساب أو أضف تأخيراً تصاعدياً بعد حفنة من الإخفاقات. وأخيراً، السرّ مفتاح طويل الأمد، لذا شفّره في حالة السكون، وأبقِه خارج إدارة الإصدار، وعامله تماماً كما تعامل كلمة مرور. وولّد رموز استرداد قوية إلى جواره ليوم يضيع فيه جهاز.
ما الذي يحميك منه TOTP — وما لا يحميك
TOTP ترقية حقيقية عن كلمات المرور وحدها، لكنه لا يحلّ كل شيء، وصفحات التسويق تميل إلى تجميل الثغرات. وفي ما يلي تقسيم واضح لقدراته وحدوده.
| TOTP يوقف | TOTP لا يوقف |
|---|---|
| كلمات المرور المسرّبة أو المعاد استخدامها | التصيّد الفوري / الخصم في المنتصف |
| حشو بيانات الاعتماد | برمجية خبيثة تقرأ السرّ من جهاز |
| تخمين كلمة المرور عن بُعد بالقوة الغاشمة | مسارات استرداد حساب ضعيفة تتخطّى 2FA |
| اختراق قاعدة بيانات يكشف بصمات كلمات المرور فقط | (هذه تحتاج دفاعات أخرى) |
ما يكسبه المستخدم كبير. فلأن الدخول صار يتطلّب رمزاً لا يستطيع إنتاجه إلا السرّ، لم تعد كلمة المرور المسرّبة كافية، فيسقط حشو بيانات الاعتماد والتخمين عن بُعد بالقوة الغاشمة. وإن تسرّبت قاعدة بياناتك لكن أسرار TOTP مشفّرة في حالة السكون، فسيظلّ المهاجم عاجزاً عن سكّ الرموز.
أما ما يبقى مكشوفاً فحقيقي أيضاً. فوسيط تصيّد فوري (صفحة خصم في المنتصف) يمكنه أن يعرض على المستخدم نسخة طبق الأصل، ويلتقط الرمز الحيّ، ويعيد إرساله إلى الموقع الحقيقي داخل النافذة نفسها. ولا يقدر TOTP على معرفة أن الرمز كُتِب في المكان الخطأ. والبرمجية الخبيثة على الجهاز التي تسرّب السرّ تهزمه بالكامل، ومسار استرداد متهاون من نوع «نسيت رمز 2FA» قد يلتفّ عليه كلّياً. وهنا خلط شائع يحسن توضيحه: هجمات تبديل شريحة الاتصال (SIM-swap) تهزم رموز SMS لمرة واحدة، لا TOTP؛ فـTOTP لا قناة لرقم هاتف فيه، فلا شيء يستطيع المهاجم تحويله.
والخطوة التالية واضحة: مفاتيح المرور وFIDO2/WebAuthn مرتبطة بالأصل، فهي مقاوِمة للتصيّد بحكم التصميم، إذ ترفض بيانات الاعتماد المصادقة لنطاق خاطئ. عامِل TOTP كخطوة قوية متاحة في كل مكان فوق كلمات المرور، باعتباره محطة وسطى لا نهاية المطاف. وهو يندمج مع بقية منظومة المصادقة لديك: راجع أفضل ممارسات أمان JWT لطبقة رمز الجلسة التي تركب فوق دخول مُتحقَّق منه، وتجزئة كلمات المرور (bcrypt مقابل Argon2) لطبقة كلمة المرور في حالة السكون التي تُكمّلها 2FA.
أخطاء شائعة عند تنفيذ TOTP
معظم علل TOTP ليست في الخوارزمية، فهي مثبّتة في الـRFC، بل في ما يحيط بها من تفاصيل التنفيذ. وهذه أكثر الأخطاء التي يقع فيها المنفّذون.
- انحراف ساعة الخادم. إن لم يكن الخادم يشغّل NTP، انزلق مفهومه عن «الآن» بعيداً عن جهاز المستخدم وتوقّفت الرموز عن المطابقة للجميع. فعّل مزامنة الوقت عبر الشبكة على كل مضيف.
- أسرار بنصّ صريح أو مودَعة في الإصدار. سرّ في ملف إعداد مودَع في git باب خلفي دائم. خزّنه مشفّراً في مدير أسرار، لا في إدارة الإصدار أبداً.
- لا حماية من إعادة التشغيل. إن قبلت رمزاً دون تسجيل الخطوة التي طابقها، عمل الرمز نفسه ثانيةً داخل نافذته. ثبّت آخر خطوة مستخدمة لكل مستخدم وارفض إعادة الاستخدام.
- نافذة واسعة أو ضيّقة أكثر من اللازم. الواسعة تضاعف الرموز القابلة للتخمين وتُضعف الأمان؛ والضيّقة ترفض مستخدمين شرعيين عند انحراف طفيف. النافذة 1 هي التوازن المعتاد.
- عدم تطابق المعاملات. إن رمّز التسجيل SHA-256 وثمانية أرقام في معرّف otpauth:// بينما يفترض المُتحقِّق SHA-1 وستة أرقام، فلن يصحّ أي رمز أبداً. اقرأ الخوارزمية وعدد الأرقام والفترة من المعرّف واستخدمها في الطرفين.
- لا رموز احتياطية أو استرداد. عند ضياع الهاتف، السبيل الوحيد للعودة مسار استرداد. أصدِر رموز استرداد عند الإعداد، واجعلها بقوة يستحقّها الحساب — المنطق نفسه وراء إنتروبيا كلمة المرور ينطبق على أسرار الاسترداد أيضاً.
الأسئلة الشائعة
هل TOTP مضمون ضد التصيّد؟
لا. يوقف TOTP كلمات المرور المسرّبة والتخمين عن بُعد بالقوة الغاشمة، لكن وسيط تصيّد فوري يمكنه عرض دخول مزيّف، والتقاط الرمز الحيّ، وإعادة إرساله إلى الموقع الحقيقي داخل نافذة الثلاثين ثانية نفسها. مفاتيح المرور وFIDO2 هي الترقية المقاومة للتصيّد، لأنها تربط بيانات الاعتماد بأصل الموقع.
هل TOTP أأمن من المصادقة الثنائية عبر SMS؟
نعم. تسافر رموز SMS عبر الشبكة الخلوية ويمكن اعتراضها عبر تبديل الشريحة (SIM-swap) أو هجمات SS7، وهي تعتمد على أمان مشغّلك. أما TOTP فلا قناة لرقم هاتف فيه ولا يرسل الرمز مطلقاً، فلا شيء يُعترَض أثناء النقل. ويُتبادَل السرّ مرة واحدة، عند الإعداد.
ماذا يحدث إن فقدت هاتفي أو تطبيق المصادقة؟
تحتاج نسخة احتياطية مرتّبة سلفاً. الخيارات هي رموز استرداد محفوظة عند إعداد 2FA، أو جهاز ثانٍ مسجَّل بالسرّ نفسه، أو سرّ Base32 الأصلي مخزَّن في مكان آمن. وبلا واحد منها، يعني فقدان الجهاز أنك محبوس خارج الحساب.
كيف يتحقّق الخادم من رمز TOTP؟
يعيد حساب الرمز المتوقّع من السرّ المشترك ومن الوقت الحالي، ثم يفحص الرمز المُقدَّم مقابل الخطوة الزمنية الحالية وخطوة واحدة على كل جانب لاحتمال انحراف الساعة. كما يسجّل أي خطوة طابقت كي لا يُعاد تشغيل الرمز نفسه، ويحدّ معدّل المحاولات لمنع التخمين.
لماذا تتجدّد رموز TOTP كل 30 ثانية؟
ثلاثون ثانية هي الفترة الافتراضية في RFC 6238: طويلة بما يكفي لقراءة الرمز وكتابته بأريحية، وقصيرة بما يكفي لأن رمزاً التقطه مهاجم ينتهي مفعوله فوراً تقريباً. وتستخدم بعض الأنظمة فترة 60 ثانية، يسجّلها معرّف otpauth:// ليطابقها المُتحقِّق.
هل يستطيع جهازان مشاركة سرّ TOTP واحد؟
نعم. أي جهاز يحمل سرّ Base32 نفسه مع ساعة متزامنة يولّد رموزاً متطابقة، لأن الخوارزمية حتمية. وهكذا بالضبط تعمل النسخ الاحتياطية لتطبيقات المصادقة على أجهزة متعدّدة، وهذا أيضاً سبب وجوب بقاء السرّ خاصاً: من ينسخه يستطيع إنتاج كل رمز مقبل.
هل TOTP هو نفسه Google Authenticator؟
لا. TOTP هو الخوارزمية المفتوحة المعرّفة في RFC 6238. أما Google Authenticator وAuthy و1Password فتطبيقات تنفّذها. ولأن المعيار مشترك، يعمل أي تطبيق متوافق مع أي خدمة تستخدم TOTP — فلا ارتهان لمزوّد بعينه.
الخاتمة
الأفكار الأساسية قليلة وسهلة الحفظ:
- يحوّل TOTP سرّاً مشتركاً مضافاً إليه الوقت الحالي إلى رمز عبر HMAC والاقتطاع.
- يحسب الطرفان الرمز كلٌّ على حدة؛ ولا يُرسَل عبر الشبكة قطّ.
- تحقّق بنافذة ±خطوة واحدة مع حماية من إعادة التشغيل وتحديد معدّل.
- يوقف هجمات كلمات المرور لكن لا يوقف التصيّد الفوري — ومفاتيح المرور تسدّ تلك الثغرة.
- أبقِ ساعات الخادم متزامنة بـNTP، والسرّ مشفّراً وخاصاً.
لترى الخوارزمية وهي تنتج أرقاماً حقيقية وتجرّب نافذة التحقّق بنفسك، افتح مولّد TOTP / 2FA لحساب الرموز وإعدادها والتحقق منها كلياً داخل متصفّحك، دون أن يغادر السرّ جهازك.