حل لغز بذور منحنيات NIST: 5 خرافات حول أصول ECDSA
بذور منحنيات NIST لـ ECDSA كانت مولّدة من lrand48(time) منذ البداية. خمس خرافات عن الأرقام الشفافة، والأبواب الخلفية، وتدقيق التشفير بنماذج اللغة.

طوال خمسة وعشرين عامًا، كانت بذور منحنيات ECDSA من NIST أقرب شيء في علم التشفير التطبيقي إلى قضية جنائية لم تُحل. خمس قيم عشوائية الظاهر بطول 160 بت، سلّمتها NSA إلى NIST دون أي تفسير، وهي تقف خلف التوقيعات في كل شيء من اتصالات TLS الخاصة بك إلى معاملات Bitcoin. هذا الأسبوع أُغلقت القضية، والجواب محرج تقريبًا: البذور كانت مخرجات مولّد lrand48() في مكتبة C، وقد زُرعت بطوابع زمنية Unix من عامي 1997 و1998. هذا كل شيء. لا تجزئة لعبارة سرية، ولا آلية غريبة، بل srand48(time(NULL))، النمط نفسه الذي تحذرك منه كل دورة أمنية بألا تستخدمه أبدًا.
جاء الاكتشاف من نموذج بحثي لدى Anthropic، وجّهه إلى المشكلة موظف فضولي. فتعرّف النموذج على البصمة الإحصائية لمولّد تطابقي خطي من التسعينيات في الثوابت المنشورة، ثم شغّل الحالة عكسيًا حتى وصل إلى تواريخ التقويم. لقد أمضيت سنوات كافية في تدقيق الأنظمة التشفيرية لأعرف أن هذا مهم، ليس لأن المنحنيات مكسورة (وهي ليست كذلك)، بل لأنه يهدم عدة أشياء آمنت بها صناعتنا بثقة. فلنأخذ الخرافات واحدة تلو الأخرى.
الخرافة 1: الثوابت غير المفسّرة تعني وجود باب خلفي مخفي
لم تكن الشكوك جنونية أبدًا. عندما نشرت NIST منحنيات FIPS 186-2 عام 2000، جاء كل منحنى مع بذرة تحدد تجزئتها معامل b للمنحنى. قالت NIST إن البذور تضمن أن المنحنيات «عشوائية قابلة للتحقق»، لكنها لم تقل، أو لم ترغب في القول، كيف وُلّدت البذور نفسها. كتب Koblitz وMenezes ورقة كاملة عن الجدل بعنوان ساخر هو «لغز ملفوف في أحجية». أفضل خيط لدى المجتمع كان Jerry Solinas من NSA، الذي تذكّر في عام 2015 أن المدخل كان تجزئة لعبارة مرحة، شيء مثل «امنح Bob وJerry زيادة في الراتب». وقد توفي عام 2023 دون أن يستعيد أحد التفاصيل.
والحقيقة المزعجة لأصحاب نظريات المؤامرة، وأنا منهم أحيانًا: غير المفسَّر يعني غالبًا غير الموثَّق، لا الخبيث. عملية التوليد الفعلية كانت مطوّرًا يشغّل برنامج C صغيرًا، يترك مولّد الأرقام الافتراضي يُزرع من ساعة الحائط، ويأخذ أول مرشح ينتج منحنى صالحًا. بذرة P-256 المنشورة كانت المرشح رقم 1,842 من تشغيل بدأ في الساعة 1:52 فجرًا بتاريخ 16 أغسطس 1997. هذا ليس أسلوب عمل وكالة تزرع فخًا رياضيًا في نظرية الأعداد. هذا مهندس في الواحدة فجرًا يشغّل حلقة حتى تطبع شيئًا صالحًا.
رأيت هذا النمط في مراجعات الحوادث أكثر من أن أحصيه. قيمة إعداد غامضة، وثابت سحري غير موثّق، وخطوة نشر لا يستطيع أحد تفسيرها. ثم يكشف تقرير ما بعد الحادثة أنها كانت اختصارًا معقولًا لمهندس مرهق في تلك اللحظة، ولم يُكتب أبدًا. الخطيئة الحقيقية لـ NSA هنا لم تكن زرع باب خلفي في المنحنيات. كانت شحن ثوابت تشفيرية إلى العالم كله دون ملف README.
الخرافة 2: طريقة التوليد تثبت أن الاختيار كان نزيهًا
الآن التصحيح المفرط. كثير من التعليقات هذا الأسبوع تعامل عبارة «إنها مجرد طوابع زمنية» كبراءة تامة. وهذا غير صحيح، والباحثون وراء العمل حريصون على قول ذلك. معرفة كيفية توليد المرشحين لا تخبرك بشيء عن كيفية اختيار المنحنيات النهائية، والاختيار جرى على مدى شهور، من مايو 1997 إلى أبريل 1998.
الأدلة تسير في الاتجاهين. في تشغيل P-256، أنتج المرشح 876 أيضًا منحنى أولي الرتبة بالحجم الصحيح، وبُني بالاتفاقيات الإعدادية نفسها، ومع ذلك تم تجاوزه. المنحنى المنشور هو المرشح 1,842. تشغيل P-224 تجاوز ثلاثة منحنيات قابلة للاستخدام، وتشغيلات ANSI X9.62 تجاوزت سبعة آخرين. لا نستطيع رؤية التاريخ الكامل للمرشحين المستبعدين، بل فقط ما هو متاح في التشغيلات المسجّلة. فإذا أراد أحد منحنى بخاصية نادرة محددة، فقد كان بإمكانه نظريًا البحث عبر الطوابع الزمنية حتى يجد واحدًا، ثم يلتزم الصمت التام عن الطابع الزمني. «فعلها ولم يقل شيئًا» كان دائمًا خيارًا ممكنًا.
قراءتي بعد سنوات من متابعة أبحاث المنحنيات الضعيفة: فرضية الباب الخلفي أُصيبت بجروح بالغة لكنها ليست ميتة رسميًا. عدد المرشحين المستبعدين قليل جدًا بحيث يعني الانتقاء الانتقائي أن المنحنيات الضعيفة شائعة وسهلة الإيجاد، وهذا ما تنفيه عقود من التحليل التشفيري العلني. لم ينشر أحد أبدًا مُميّزًا يفصل هذه المنحنيات عن المنحنيات العشوائية. لكن «لا توجد نقطة ضعف معروفة» و«لا توجد نقطة ضعف مثبتة استحالتها» عبارتان مختلفتان، والموقف الصادق هو الأولى. وهذا بالضبط فجوة المواصفة والتنفيذ تتجلى على مستوى المعايير: المواصفة قالت «عشوائية قابلة للتحقق»، والتنفيذ كان «ما قالته الساعة».
وُلّدت البذور بالطريقة التي يفعلها طالب دراسات عليا: مولّد أرقام جاهز وساعة النظام. الفضيحة لم تكن يومًا في الرياضيات. كانت في غياب التوثيق.
الخرافة 3: مولّدات الأرقام القديمة الضعيفة لا تضر إذا استُخدمت مرة واحدة
هذه هي الخرافة التي ينبغي أن تجعل كل مهندس كتب يومًا srand(time(NULL)) ينتصب في مقعده. ظل الغموض الذي دام خمسة وعشرين عامًا قائمًا بسبب خاصية تصميمية واحدة في lrand48(): إنه يسرّب بنيته الداخلية. المولّد يعيد فقط أعلى 31 بت من حالة بطول 48 بت، لذلك تحمل مخرجاته دائمًا بت أعلى صفريًا. عند كتابتها ككلمات 32 بت، تظهر أربع من بذور المنحنيات الثنائية العشر بأصفار في أعلى البتات عبر عشرين كلمة متتالية، وهو حدث احتماله نحو واحد من 58,000 تحت توزيع منتظم. كانت البصمة مرئية بالعين المجردة لكل من فكّر في النظر.
ومن هنا يصبح الهجوم رخيصًا بشكل محرج. لاستعادة حالات المنحنيات الثنائية، تأخذ أول كلمة مخرجات وتجرب القيم الممكنة لـ2^17 من البتات المنخفضة المخفية، وتتحقق مما إذا كانت الكلمات الأربع التالية تتبعها. هذا يستغرق بضعة أجزاء من الألف من الثانية. أما المنحنيات الأولية، فقد احتفظت البذور بعدد أقل من البتات لكل مخرج، لذا استلزم استعادة الحالة هجوم LCG المقتطع الكلاسيكي: تمثيله كمسألة شبكية (lattice) وتطبيق تقليص أساس LLL عليها. مادة كتب دراسية حرفيًا. وبمجرد أن تملك الحالة، يعمل LCG إلى الخلف بسهولة عمله إلى الأمام، فتعيده للخلف حتى يظهر شكل تهيئة srand48، أي أن البتات المنخفضة تساوي 0x330E، وتقرأ الطابع الزمني الذي زُرع به.
# The whole mystery, reproduced
from datetime import datetime, timezone
def unix(when):
return int(datetime.fromisoformat(when).replace(tzinfo=timezone.utc).timestamp())
def candidate(t, n, per, shift, width):
x, out = (t << 16) | 0x330E, "" # state set by srand48(t)
for i in range(per * n):
x = (0x5DEECE66D * x + 0xB) % 2**48 # one lrand48 step
if i >= per * (n - 1):
out += "%0*X" % (width, x >> shift)
return out
# P-256: run started 1997-08-16 01:52:34 UTC, candidate 1842
print(candidate(unix("1997-08-16 01:52:34"), 1842, 20, 40, 2))
# -> C49D360886E704936A6678E1139D26B7819F7E90 (the published NIST seed)
الدرس يتجاوز الهيئات المعيارية. أي قيمة «تبدو عشوائية» تُصدرها، كرموز الجلسات، ومعرّفات الطلبات، والأملاح، وأسماء الملفات، تحمل بصمة المولّد الذي أنشأها. إذا كان ذلك المولّد محركًا تطابقيًا خطيًا أو Mersenne Twister، فبضعة مخرجات تكفي لإعادة بناء الحالة الداخلية، وكل ما ولّدته قبلها وبعدها يصبح قابلًا للتنبؤ. استخدام واحد قبل 25 عامًا، في ملف صُمم ليبدو ضوضاء، انكشف بالكامل. وعندما أراجع شيفرة تستخدم مولّدات أرقام غير تشفيرية لأي شيء يستطيع المهاجم ملاحظته، فهذه هي قصة الحرب التي سأستشهد بها من الآن فصاعدًا.

الخرافة 4: أرقام «لا شيء في كمّي» لم تكن الحماية الحقيقية أبدًا
فكرة «لا شيء في كمّي»، أي اشتقاق الثوابت من شيء بريء بوضوح مثل أرقام π، وُجدت لتقييد هامش حرية المصمم. إذا استطعت أن أُظهر لك أن ثابتي ينبثق من إجراء عام وصارم، فلم يكن لدي مجال لتهريب باب خلفي. فشلت بذور NIST في هذا الاختبار إجرائيًا، لأن الإجراء كان سريًا، فكان التقييد غير معروف. لكن ما تكشفه هذه الحلقة حقًا هو أن اختبار الكمّ أضعف مما تظاهرنا به حتى حين ينجح.
تأمل ما يمنحك إياه «عشوائي قابل للتحقق من طابع زمني» فعلًا. الطابع الزمني يحمل نحو 31 بت من الإنتروبيا لنافذة معقولة. أي شخص، بما فيه المؤلف الأصلي، يستطيع أن يمرّ على ملايين الطوابع الزمنية، فيولّد ملايين المنحنيات المرشحة، وينشر فقط الذي يريده، مع بذرته البريئة الظاهر. إذا وُجدت منحنيات بنقطة ضعف سرية بمعدل واحد من المليون، فالبحث بالطوابع الزمنية يجد واحدًا في بعد ظهر. البذرة تثبت من أين جاء الرقم، لكنها تقول القليل جدًا عن سبب اختيار ذلك الرقم بالتحديد. وينطبق الأمر نفسه على مخططات تجزئة عبارة سرية، ولهذا لم تكن الإشاعة حول عبارة Solinas المرحة مطمئنة تمامًا أيضًا.
الممارسة الحديثة الأقوى هي بناء المنحنيات الصارم: اختيار أصغر معامل يحقق قائمة عامة من معايير الأمان، مع تثبيت قواعد الانتقاء قبل بدء البحث. هذه هي الفلسفة وراء Curve25519، ولهذا أعادت حجج Dan Bernstein حول الصرامة تشكيل طريقة تقييم المجتمع للمنحنيات. الحماية الفعلية من الثوابت الخبيثة لم تكن يومًا قصة اشتقاق لطيفة. إنها تقليل مساحة البحث، ونشر المعايير مسبقًا، ووجود عيون مستقلة كافية على الرياضيات بحيث لا تبقى خاصية مخفية مخفية. تدقيق الثوابت يعني تدقيق العملية التي صفّتها، ولهذا تستحق الأسئلة المفتوحة هنا (المرشحون المستبعدون، ونقاط الأساس غير المفسّرة لـ P-256 وأمثالها، وبذرة B-163 التي لم تُحدد هويتها بعد) أن تبقى مفتوحة في السجل، لا أن تُمحى من الذاكرة تحت وطأة الاحتفال.
الخرافة 5: نماذج اللغة تكتفي بالاجترار، ولا تستطيع إجراء تحليل تشفيري أصيل
هذه الخرافة هي الأكثر إيلامًا، لأنني صدّقت نسخة منها. بقيت المشكلة المفتوحة دون حل لربع قرن رغم مكافأة عامة قدرها 36,864 دولارًا واهتمام جاد من هواة مهرة. حاول عدة باحثين في Anthropic ملاحقتها بأنفسهم، متتبعين خيط «تجزئة عبارة مضحكة»، وعادوا خالي الوفاض. ثم جرّب نموذج بحث داخلي، سُئل دون أن يُعطى الإشاعة، زاوية مختلفة في أقل من نصف ساعة: بدلًا من تخمين مدخل التجزئة، سأل أي برمجية كانت ستولّد البذور، وافترض مولّد أرقام PRNG من مكتبة C في التسعينيات، وكتب ماسحًا ينزلق عبر كل بذرة ويختبر 34 تركيبة من المولّد وشريحة المخرجات، ولاحظ نمط البت الأعلى الصفري، وشغّل هجوم الشبكة على المخرجات المقتطعة، وتتبّع الحالات حتى وصل إلى تواريخ التقويم.
انظر إلى طبيعة هذا الأسلوب. ليس استرجاعًا، فلا توجد وثيقة تدريب تحوي الجواب، لأن الجواب لم يكن موجودًا في أي مكان. إنه توليد فرضيات مع استخدام أدوات والتحقق، وهذا هو الشكل الفعلي للعمل التحليلي التشفيري. بل إن النموذج راجع سلامة نفسه في منتصف التشغيل: هل هذه بيئة اختبار محاكاة؟ هل كان شيء بهذا الوضوح سيبقى غير مكتشف لـ25 عامًا؟ هل تطابق 160 بت من بذرة 32 بت يستبعد الصدفة؟ هذه الشكوك الذاتية هي ما أريده من محلل بشري، وبصراحة بعض المحللين البشريين يتخطونها. كنا نختبر الخرافات حول ما تفعله هذه النماذج فعلًا على هذا الموقع منذ مدة، وهذه نقطة بيانات واضحة: صارت نماذج اللغة قادرة على تنفيذ استدلال جنائي متعدد الخطوات على آثار من العالم الحقيقي، لا على اختبارات معيارية فحسب.
الرد المنصف من الممارسين يتعلق بالمصدر. النموذج لم يخترع استعادة حالة LCG ولا LLL، بل يستند إلى عقود من التحليل التشفيري المنشور لباحثين معروفين وغير معروفين، ولا يستطيع أن يخبرك بأسماء من شكّلت نهجه. وهذا يزعجني أقل مما يزعج غيري. الماسح وكود التحقق وسكربت إعادة الإنتاج كلها عامة، والبشر في الفريق وجّهوا السؤال وتحققوا من النتيجة. فلنعترف بتقسيم العمل بأمانة: الآلة قدّمت بحثًا لا يكلّ عن الفرضيات، والبشر قدّموا الحكم والمساءلة. ومنح مكافأة 36,864 دولارًا إلى Internet Security Research Group كان طريقة أنيقة لإنهاء الأمر.

ماذا يغيّر هذا في تدقيقات الأمان
إذن، أين يضعنا هذا كمهندسين عاملين؟ بضعة تحولات ملموسة في طريقة اقترابي من التدقيقات من الآن. أولًا، عامل كل ثابت سحري في بروتوكول أو قاعدة شيفرة كأثر جنائي، لا كحقيقة من حقائق الطبيعة. اسأل أي مولّد كان يمكن أن ينتجه، وتحقق من البصمات البنيوية، مثل الانحياز في البتات العليا، والكلمات المتتالية المترابطة وفق LCG، واستعادات الحالة المعقولة زمنيًا، قبل أن تقبل جواب «إنه عشوائي». الأدوات الخاصة بهذا صارت متاحة بسهولة الآن.
ثانيًا، إذا نشرت ثوابت، فانشر المولّد: الشيفرة المصدرية، والمدخلات الدقيقة، والبيئة الدقيقة. «عشوائي قابل للتحقق» دون وصفة قابلة لإعادة الإنتاج يشتري لك خمسة وعشرين عامًا من الشك ومكافأة على إرثك. ثالثًا، استمر في استخدام P-256، فالاكتشاف يرفع الثقة بالمنحنيات بدل أن يخفضها، ونموذج التهديد الحقيقي للمنحنيات الإهليلجية هو أجهزة الحوسبة الكمومية، لا ساعة محطة عمل من عام 1997. لكن اقرأ الأسئلة المفتوحة بأمانة: نقاط الأساس غير المفسّرة والمرشحون المستبعدون أطراف سائبة، ونضج العمل الأمني يعني إبقاءها ضمن الحسابات.
الخلاصة الأعمق تتعلق بالذاكرة المؤسسية. تذكّر Jerry Solinas مزحة عن الرواتب تبيّن أنها خاطئة. وكانت الأرشيفات، بحسب قوله، على الأغلب موجودة على قرص صلب قرب تابوت العهد. السبب الوحيد الذي يجعلنا نعرف الحقيقة اليوم هو أن المخرجات نفسها احتفظت ببنية كافية لتعترف. أنظمتك تكتب اعترافاتها الخاصة الآن، في كل معرّف ورمز وثابت تشحنه. تأكد أنها ستعترف بشيء تفخر به.


