<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>التشفير on kenji.blog</title><link>http://kenji.blog/ar/categories/%D8%A7%D9%84%D8%AA%D8%B4%D9%81%D9%8A%D8%B1/</link><description>Recent content in التشفير on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ar</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 10:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ar/categories/%D8%A7%D9%84%D8%AA%D8%B4%D9%81%D9%8A%D8%B1/index.xml" rel="self" type="application/rss+xml"/><item><title>الأسس الرياضية لتشفير المنحنيات الإهليلجية (ECC) وتنفيذه بلغة C++</title><link>http://kenji.blog/ar/p/elliptic-curve-cryptography-math-cpp/</link><pubDate>Fri, 11 Sep 2026 10:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/elliptic-curve-cryptography-math-cpp/</guid><description>&lt;img src="http://kenji.blog/p/elliptic-curve-cryptography-math-cpp/img/eyecatch.jpg" alt="Featured image of post الأسس الرياضية لتشفير المنحنيات الإهليلجية (ECC) وتنفيذه بلغة C++" />&lt;h1 id="الأسس-الرياضية-لتشفير-المنحنيات-الإهليلجية-ecc-وتنفيذه-بلغة-c">الأسس الرياضية لتشفير المنحنيات الإهليلجية (ECC) وتنفيذه بلغة C++
&lt;/h1>&lt;p>في تقنيات التشفير الحديثة، يلعب &lt;strong>تشفير المنحنيات الإهليلجية (Elliptic Curve Cryptography: ECC)&lt;/strong> دورًا بالغ الأهمية. ليس من المبالغة القول إن أساس الثقة في مجتمعنا الرقمي الحديث يعتمد على ECC، بدءًا من اتصالات الإنترنت اليومية (HTTPS/TLS)، والجيوب الآمنة (Secure Enclaves) في الهواتف الذكية، ومصادقة الخوادم عبر SSH، والمصادقة بدون كلمات مرور مثل FIDO، وصولاً إلى الأصول المشفرة مثل بيتكوين وإيثريوم.&lt;/p>
&lt;p>في هذا المقال، سنشرح بشكل شامل وكثيف كيف يعمل تشفير المنحنيات الإهليلجية، بدءًا من النظرية الرياضية الجميلة والمعقدة التي تكمن وراءه (الهندسة الجبرية على الحقول المنتهية)، مرورًا بطريقة تنفيذه الفعلي باستخدام لغة C++، وصولاً إلى تقنيات البرمجة الآمنة لمنع هجمات القنوات الجانبية (مثل هجمات التوقيت).&lt;/p>
&lt;hr>
&lt;h2 id="1-لماذا-تشفير-المنحنيات-الإهليلجية-مقارنة-مع-rsa">1. لماذا تشفير المنحنيات الإهليلجية؟ (مقارنة مع RSA)
&lt;/h2>&lt;p>لطالما كان &lt;strong>تشفير RSA&lt;/strong> هو المرادف لتشفير المفتاح العام. يعتمد تشفير RSA في أمانه على &amp;ldquo;صعوبة تحليل الأعداد المركبة الضخمة إلى عواملها الأولية&amp;rdquo;. ومع ذلك، مع تحسن القوة الحسابية لأجهزة الكمبيوتر، أصبح من الضروري زيادة طول مفتاح RSA (عدد بتات المعامل) باستمرار للحفاظ على الأمان. حاليًا، يُوصى باستخدام مفاتيح بطول 2048 بت كحد أدنى، ولأمان أكبر يُفضل استخدام 3072 بت أو 4096 بت.&lt;/p>
&lt;p>في المقابل، يعتمد تشفير المنحنيات الإهليلجية (ECC) على صعوبة رياضية مختلفة وهي &lt;strong>&amp;ldquo;مشكلة اللوغاريتم المتقطع على المنحنيات الإهليلجية (ECDLP)&amp;rdquo;&lt;/strong>. حتى الآن، لم يتم اكتشاف خوارزمية فعالة (مثل خوارزميات الوقت شبه الأسّي) لحل ECDLP، وحتى أكثر طرق الهجوم الفعالة المعروفة تتطلب وقتًا أسّيًا.&lt;/p>
&lt;p>بسبب هذه الخاصية، يتمتع ECC بميزة حاسمة وهي &lt;strong>القدرة على تحقيق مستوى أمان مكافئ لـ RSA باستخدام مفاتيح أقصر بكثير&lt;/strong>.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:center">قوة الأمان (بت)&lt;/th>
&lt;th style="text-align:center">طول مفتاح RSA (بت)&lt;/th>
&lt;th style="text-align:center">طول مفتاح ECC (بت)&lt;/th>
&lt;th style="text-align:center">نسبة طول المفتاح&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:center">80&lt;/td>
&lt;td style="text-align:center">1024&lt;/td>
&lt;td style="text-align:center">160&lt;/td>
&lt;td style="text-align:center">1:6&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">112&lt;/td>
&lt;td style="text-align:center">2048&lt;/td>
&lt;td style="text-align:center">224&lt;/td>
&lt;td style="text-align:center">1:9&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">128&lt;/td>
&lt;td style="text-align:center">3072&lt;/td>
&lt;td style="text-align:center">256&lt;/td>
&lt;td style="text-align:center">1:12&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">192&lt;/td>
&lt;td style="text-align:center">7680&lt;/td>
&lt;td style="text-align:center">384&lt;/td>
&lt;td style="text-align:center">1:20&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">256&lt;/td>
&lt;td style="text-align:center">15360&lt;/td>
&lt;td style="text-align:center">512&lt;/td>
&lt;td style="text-align:center">1:30&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>كما يوضح الجدول أعلاه، للحصول على قوة أمان تبلغ 128 بت (القوة القياسية الحالية)، يتطلب RSA مفتاحًا بطول 3072 بت، بينما يكفي 256 بت فقط في حالة ECC. هذا يتيح تقليل العمليات الحسابية، وخفض استهلاك الذاكرة، وتوفير النطاق الترددي للشبكة، مما يمنحه تفوقًا ساحقًا خاصة في بيئات إنترنت الأشياء (IoT) والبطاقات الذكية ذات الموارد المحدودة.&lt;/p>
&lt;hr>
&lt;h2 id="2-التحضير-الرياضي-نظرية-الزمر-وعالم-الحقول-المنتهية">2. التحضير الرياضي: نظرية الزمر وعالم الحقول المنتهية
&lt;/h2>&lt;p>لفهم تشفير المنحنيات الإهليلجية حقًا، من الضروري استيعاب المفاهيم الأساسية في الجبر المجرد (نظرية الزمر ونظرية الحقول). نلخص هنا المعرفة الأساسية اللازمة لبناء ECC.&lt;/p>
&lt;h3 id="21-الزمرة-group-والزمرة-الأبيلية">2.1. الزمرة (Group) والزمرة الأبيلية
&lt;/h3>&lt;p>&lt;strong>الزمرة (Group)&lt;/strong> هي مجموعة $G$ مقترنة بعملية ثنائية (سنفترض هنا أنها الجمع $+$) يُرمز لها بـ $(G, +)$، والتي تحقق البديهيات الأربع التالية:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>الانغلاق (Closure)&lt;/strong>: لأي $a, b \in G$، يكون $a + b \in G$.&lt;/li>
&lt;li>&lt;strong>الدمج (Associativity)&lt;/strong>: لأي $a, b \in G$، يتحقق $(a + b) + c = a + (b + c)$.&lt;/li>
&lt;li>&lt;strong>وجود العنصر المحايد (Identity element)&lt;/strong>: يوجد عنصر $e \in G$ بحيث لأي $a \in G$ يكون $a + e = e + a = a$. في حالة زمرة الجمع، يُشار إلى هذا العنصر المحايد عادةً بـ $0$ أو $\mathcal{O}$.&lt;/li>
&lt;li>&lt;strong>وجود المعكوس (Inverse element)&lt;/strong>: لأي $a \in G$، يوجد عنصر $b \in G$ بحيث يكون $a + b = b + a = e$. يُشار إلى هذا الـ $b$ بـ $-a$.&lt;/li>
&lt;/ol>
&lt;p>بالإضافة إلى ذلك، إذا كانت الزمرة تحقق الشرط التالي (أي أن تغيير ترتيب العملية لا يغير النتيجة)، فإنها تُسمى &lt;strong>زمرة أبيلية (Abelian Group)&lt;/strong> أو زمرة إبدالية.&lt;/p>
&lt;ol start="5">
&lt;li>&lt;strong>الإبدال (Commutativity)&lt;/strong>: لأي $a, b \in G$، يتحقق $a + b = b + a$.&lt;/li>
&lt;/ol>
&lt;p>تشكل مجموعة النقاط على المنحنى الإهليلجي هذه &lt;strong>الزمرة الأبيلية&lt;/strong> من خلال تعريف قاعدة جمع محددة.&lt;/p>
&lt;h3 id="22-الحقل-المنتهي-finite-field">2.2. الحقل المنتهي (Finite Field)
&lt;/h3>&lt;p>في نظرية التشفير، لا نستخدم حقولاً مستمرة ذات عناصر لا نهائية مثل الأعداد الحقيقية أو المركبة، بل نستخدم &lt;strong>الحقول المنتهية (Finite Fields)&lt;/strong> أو حقول غالوا (Galois Fields) التي تحتوي على عدد محدود من العناصر.&lt;/p>
&lt;p>الحقل المنتهي الأساسي هو &lt;strong>الحقل الأولي $\mathbb{F}_p$&lt;/strong> باستخدام عدد أولي $p$. وهو عبارة عن مجموعة الأعداد الصحيحة $\{0, 1, 2, \dots, p-1\}$ مع تعريف العمليات الحسابية الأربع (الجمع، الطرح، الضرب، القسمة) باستخدام المعامل $p$ (الباقي من القسمة على $p$).&lt;/p>
&lt;ul>
&lt;li>&lt;strong>الجمع&lt;/strong>: $(a + b) \pmod p$&lt;/li>
&lt;li>&lt;strong>الطرح&lt;/strong>: $(a - b) \pmod p$&lt;/li>
&lt;li>&lt;strong>الضرب&lt;/strong>: $(a \times b) \pmod p$&lt;/li>
&lt;li>&lt;strong>القسمة&lt;/strong>: $a \times b^{-1} \pmod p$ (حيث $b^{-1}$ هو المعكوس الضربي لـ $b$ في المعامل $p$)&lt;/li>
&lt;/ul>
&lt;p>يعتبر حساب &lt;strong>المعكوس الضربي (Modular Multiplicative Inverse)&lt;/strong> بالغ الأهمية في تنفيذ التشفير. لإيجاد $b^{-1}$ الذي يحقق $b \times b^{-1} \equiv 1 \pmod p$، تُستخدم أساسًا الخوارزميتان التاليتان:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>خوارزمية إقليدس الممتدة (Extended Euclidean Algorithm)&lt;/strong>: سريعة، لكن في بعض التنفيذات يعتمد وقت المعالجة على قيم الإدخال، مما يشكل خطر التعرض لهجمات التوقيت.&lt;/li>
&lt;li>&lt;strong>مبرهنة فيرما الصغرى (Fermat&amp;rsquo;s Little Theorem)&lt;/strong>: عندما يكون $p$ عددًا أوليًا و $b \neq 0$، يتحقق $b^{p-1} \equiv 1 \pmod p$. بقسمة الطرفين على $b$، نحصل على $b^{p-2} \equiv b^{-1} \pmod p$. أي أن حساب القوة $p-2$ لـ $b$ يعطينا المعكوس. نظرًا لسهولة تنفيذ عمليات الرفع للأس في وقت ثابت (Constant-Time)، يُفضل استخدام هذه الطريقة في تنفيذ التشفير.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="3-معادلة-المنحنى-الإهليلجي-والهندسة">3. معادلة المنحنى الإهليلجي والهندسة
&lt;/h2>&lt;h3 id="31-شكل-فايرشتراس-القياسي">3.1. شكل فايرشتراس القياسي
&lt;/h3>&lt;p>&lt;strong>المنحنى الإهليلجي (Elliptic Curve)&lt;/strong> هو بشكل عام منحنى مستوٍ يُعرّف بالمعادلة التالية التي تُعرف بـ &lt;strong>شكل فايرشتراس القياسي (Weierstrass normal form)&lt;/strong>:&lt;/p>
$$ y^2 = x^3 + ax + b $$
&lt;p>حيث $a$ و $b$ ثوابت، ولضمان عدم احتواء المنحنى على نقاط شاذة (مثل التقاطعات الذاتية أو النقاط المدببة) أي ليكون منحنى أملس (smooth)، يُشترط ألا يكون &lt;strong>المميز (Discriminant) $\Delta$&lt;/strong> التالي مساويًا للصفر:&lt;/p>
$$ \Delta = -16(4a^3 + 27b^2) \neq 0 $$
&lt;p>نظرًا لأن المنحنيات ذات النقاط الشاذة تُضعف الأمان التشفيري، يتم دائمًا اختيار معاملات $a, b$ تحقق هذا الشرط.&lt;/p>
&lt;h3 id="32-نقطة-في-اللانهاية-point-at-infinity">3.2. نقطة في اللانهاية (Point at Infinity)
&lt;/h3>&lt;p>لجعل المنحنى الإهليلجي زمرة رياضية مكتملة، نُدخل نقطة افتراضية تُسمى &lt;strong>&amp;ldquo;نقطة في اللانهاية (Point at Infinity)&amp;rdquo;&lt;/strong> بالإضافة إلى النقاط على المستوى. يُرمز لها بـ $\mathcal{O}$.&lt;/p>
&lt;p>تُعرّف النقطة في اللانهاية $\mathcal{O}$ على أنها النقطة التي تتقاطع عندها جميع الخطوط الرأسية في اللانهاية. في نظرية الزمر، تعمل هذه النقطة $\mathcal{O}$ كـ &lt;strong>عنصر محايد في الجمع&lt;/strong> (صفر).&lt;/p>
&lt;p>أي أنه لأي نقطة $P$ على المنحنى، يتحقق ما يلي:
&lt;/p>
$$ P + \mathcal{O} = \mathcal{O} + P = P $$
&lt;p>كما أن المعكوس $-P$ للنقطة $P = (x, y)$ يُعرّف على أنه النقطة المتناظرة بالنسبة لمحور x وهي $(x, -y)$. وبالتالي:
&lt;/p>
$$ P + (-P) = \mathcal{O} $$
&lt;hr>
&lt;h2 id="4-عمليات-الزمرة-على-المنحنى-الإهليلجي-جمع-النقاط-والمضاعفة">4. عمليات الزمرة على المنحنى الإهليلجي (جمع النقاط والمضاعفة)
&lt;/h2>&lt;p>العملية الأساسية في تشفير المنحنيات الإهليلجية هي &lt;strong>&amp;ldquo;الجمع (Addition)&amp;rdquo;&lt;/strong> بين النقاط على المنحنى. وهذا يختلف عن الجمع العادي للأعداد الصحيحة، حيث يتم تعريفه بناءً على عمليات هندسية.&lt;/p>
&lt;h3 id="41-الجمع-الهندسي-tangent-and-chord-method">4.1. الجمع الهندسي (Tangent and Chord Method)
&lt;/h3>&lt;p>لإيجاد نقطة جديدة $R$ ($R = P + Q$) بجمع نقطتين مختلفتين $P$ و $Q$ على المنحنى، نتبع الخطوات التالية:&lt;/p>
&lt;ol>
&lt;li>نرسم خطًا مستقيمًا (وترًا) يمر بالنقطتين $P$ و $Q$.&lt;/li>
&lt;li>سيتقاطع هذا الخط دائمًا مع المنحنى الإهليلجي في نقطة ثالثة (سنسميها $-R$). (※بناءً على نظرية في الهندسة الجبرية)&lt;/li>
&lt;li>النقطة الناتجة عن عكس $-R$ بشكل متناظر حول محور x (بعكس إشارة الإحداثي y) هي النقطة المطلوبة $R$.&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph TD
Step1["رسم خط يمر بـ P(x1, y1) و Q(x2, y2)"] --> Step2["إيجاد نقطة التقاطع الثالثة -R مع المنحنى"]
Step2 --> Step3["عكس -R حول محور x للحصول على R(x3, y3)"]
Step3 -.-> Result["هذه هي R = P + Q"]&lt;/div>
&lt;h3 id="42-مضاعفة-النقطة-point-doubling">4.2. مضاعفة النقطة (Point Doubling)
&lt;/h3>&lt;p>عند جمع النقطة $P$ مع نفسها ($P + P = 2P$)، لا يمكننا رسم خط يمر بنقطتين. في هذه الحالة، نرسم &lt;strong>مماس المنحنى (Tangent) عند النقطة $P$&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>نرسم المماس للمنحنى عند النقطة $P$.&lt;/li>
&lt;li>يتقاطع هذا المماس مع المنحنى في نقطة أخرى $-R$.&lt;/li>
&lt;li>النقطة المعكوسة متناظرًا حول محور x لنقطة التقاطع هي النقطة المطلوبة $R = 2P$.&lt;/li>
&lt;/ol>
&lt;h3 id="43-المعادلات-الجبرية-للحساب">4.3. المعادلات الجبرية للحساب
&lt;/h3>&lt;p>يتم تحويل العمليات الهندسية إلى معادلات جبرية يمكن للكمبيوتر حسابها.
تتم جميع العمليات &lt;strong>فوق الحقل المنتهي $\mathbb{F}_p$ (بالمعامل $p$)&lt;/strong>.&lt;/p>
&lt;p>لنفترض أن النقطة $P = (x_1, y_1)$ والنقطة $Q = (x_2, y_2)$.
ونقطة النتيجة هي $R = P + Q = (x_3, y_3)$.&lt;/p>
&lt;p>ليكن ميل الخط $\lambda$ (لامدا).&lt;/p>
&lt;p>&lt;strong>【الحالة 1: عندما $P \neq Q$ (جمع النقاط)】&lt;/strong>
الميل $\lambda$ هو معدل التغير بين النقطتين.
&lt;/p>
$$ \lambda \equiv \frac{y_2 - y_1}{x_2 - x_1} \pmod p $$
$$ \lambda \equiv (y_2 - y_1) \cdot (x_2 - x_1)^{-1} \pmod p $$
&lt;p>باستخدام هذا $\lambda$، يمكن حساب $x_3, y_3$ كما يلي:
&lt;/p>
$$ x_3 \equiv \lambda^2 - x_1 - x_2 \pmod p $$
$$ y_3 \equiv \lambda(x_1 - x_3) - y_1 \pmod p $$
&lt;p>&lt;strong>【الحالة 2: عندما $P = Q$ (مضاعفة النقطة)】&lt;/strong>
الميل $\lambda$ سيكون ميل المماس المحسوب بواسطة الاشتقاق. (نشتق المعادلة $y^2 = x^3 + ax + b$ ضمنيًا)
&lt;/p>
$$ 2y \cdot y' = 3x^2 + a \implies y' = \frac{3x^2 + a}{2y} $$
&lt;p>
لذلك،
&lt;/p>
$$ \lambda \equiv (3x_1^2 + a) \cdot (2y_1)^{-1} \pmod p $$
&lt;p>صيغتا $x_3, y_3$ هما نفس صيغتي الجمع، ولكن بما أن $x_2 = x_1$ تصبحان كالتالي:
&lt;/p>
$$ x_3 \equiv \lambda^2 - 2x_1 \pmod p $$
$$ y_3 \equiv \lambda(x_1 - x_3) - y_1 \pmod p $$
&lt;blockquote>
&lt;p>[!IMPORTANT]
تتضمن هذه المعادلات &lt;strong>عمليات قسمة (حساب المعكوس النمطي)&lt;/strong> مثل $(x_2 - x_1)^{-1}$ و $(2y_1)^{-1}$. نظرًا لأن تكلفة حساب المعكوس النمطي عالية جدًا، تُستخدم في التنفيذ الفعلي عادةً أنظمة الإحداثيات الإسقاطية مثل &lt;strong>&amp;ldquo;إحداثيات جاكوبي (Jacobian Coordinates)&amp;rdquo;&lt;/strong> لتأخير عملية القسمة.&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="5-الضرب-القياسي-ومشكلة-اللوغاريتم-المتقطع-على-المنحنيات-الإهليلجية-ecdlp">5. الضرب القياسي ومشكلة اللوغاريتم المتقطع على المنحنيات الإهليلجية (ECDLP)
&lt;/h2>&lt;p>العملية التي تتطلب أكبر قدر من الحسابات وتُشكل جوهر الأمان في تشفير المنحنيات الإهليلجية هي &lt;strong>الضرب القياسي (Scalar Multiplication)&lt;/strong>.&lt;/p>
&lt;h3 id="51-ما-هو-الضرب-القياسي">5.1. ما هو الضرب القياسي
&lt;/h3>&lt;p>يُسمى جمع النقطة $P$ مع نفسها عدد $k$ من المرات بالضرب القياسي، ويُكتب $kP$.
&lt;/p>
$$ kP = \underbrace{P + P + \dots + P}_{k \text{ من المرات}} $$
&lt;p>حيث $k$ هو عدد صحيح كبير جدًا (مثلاً عدد صحيح من 256 بت).&lt;/p>
&lt;h3 id="52-مشكلة-اللوغاريتم-المتقطع-على-المنحنيات-الإهليلجية-ecdlp">5.2. مشكلة اللوغاريتم المتقطع على المنحنيات الإهليلجية (ECDLP)
&lt;/h3>&lt;p>يعتمد أمان تشفير المنحنيات الإهليلجية على صعوبة المشكلة التالية.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>مشكلة اللوغاريتم المتقطع على المنحنيات الإهليلجية (Elliptic Curve Discrete Logarithm Problem: ECDLP)&lt;/strong>
عند إعطاء النقطة المعروفة $P$ (النقطة الأساسية) والنقطة المحسوبة $Q$، أوجد المُعامل القياسي $k$ الذي يحقق $Q = kP$.&lt;/p>
&lt;/blockquote>
&lt;p>حساب $Q$ من $k$ و $P$ (الاتجاه الأمامي) أمر سهل (وقت متعدد الحدود) باستخدام الخوارزمية الموضحة أدناه، لكن العكس (الاتجاه المعكس) لاستنتاج $k$ من $P$ و $Q$ أمر مستحيل عمليًا، حيث لا توجد طريقة فعالة لحله سوى البحث الشامل (دالة وحيدة الاتجاه).
في بروتوكولات التشفير، يتوافق &lt;strong>$k$ مع &amp;ldquo;المفتاح الخاص&amp;rdquo; و $Q$ مع &amp;ldquo;المفتاح العام&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="53-خوارزمية-المضاعفة-والجمع-double-and-add">5.3. خوارزمية المضاعفة والجمع (Double-and-Add)
&lt;/h3>&lt;p>عندما يكون $k$ رقمًا ضخمًا (مثال: $2^{256}$)، فإن جمع $P$ بشكل مباشر $k$ مرة لن ينتهي حتى لو انتهى عمر الكون. لذلك، لإجراء الضرب القياسي بسرعة، تُستخدم &lt;strong>طريقة المضاعفة والجمع (الطريقة الثنائية)&lt;/strong>.&lt;/p>
&lt;p>هذه هي النسخة الخاصة بالمنحنيات الإهليلجية من &amp;ldquo;طريقة التربيع المتكرر&amp;rdquo; المُستخدمة لحساب قوى الأعداد الصحيحة بسرعة. يتم تمثيل المُعامل $k$ بالنظام الثنائي، وتتم معالجته بدءًا من البت الأكثر أهمية (MSB).&lt;/p>
&lt;ol>
&lt;li>تهيئة النقطة $R$ التي ستحتفظ بالنتيجة بـ $\mathcal{O}$.&lt;/li>
&lt;li>من البت الأكثر أهمية في $k$ إلى البت الأقل أهمية، كرر ما يلي:
&lt;ul>
&lt;li>ضاعف $R$ (مضاعفة النقطة: $R = 2R$)&lt;/li>
&lt;li>إذا كان البت الحالي &lt;code>1&lt;/code>، أضف $P$ إلى $R$ (جمع النقاط: $R = R + P$)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>بفضل هذه الخوارزمية، ينخفض التعقيد الحسابي بشكل كبير من $O(k)$ إلى $O(\log_2 k)$، مما يجعل الحساب ممكنًا في وقت واقعي (بأجزاء من الثانية).&lt;/p>
&lt;hr>
&lt;h2 id="6-تبادل-مفاتيح-ديفي-هيلمان-على-المنحنيات-الإهليلجية-ecdh">6. تبادل مفاتيح ديفي-هيلمان على المنحنيات الإهليلجية (ECDH)
&lt;/h2>&lt;p>نشرح هنا آلية بروتوكول &lt;strong>تبادل مفاتيح ECDH (Elliptic Curve Diffie-Hellman)&lt;/strong>، وهو التطبيق الأكثر تمثيلاً لـ ECC. ECDH هي آلية تتيح لأليس وبوب إنشاء ومشاركة مفتاح سري مشترك (مفتاح الجلسة) بأمان عبر قناة اتصال عرضة للتنصت (وهي جوهر عملية مصافحة TLS).&lt;/p>
&lt;p>&lt;strong>【المعلمات المسبقة (معلمات المجال)】&lt;/strong>
يتشارك الطرفان مسبقًا في المنحنى الإهليلجي المُستخدم $E$، العدد الأولي $p$، والنقطة الأساسية $G$. (على سبيل المثال، NIST P-256 أو secp256k1)&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Alice as "أليس (Alice)"
participant Bob as "بوب (Bob)"
Note over Alice,Bob: "المعلمات العامة: المنحنى E، النقطة الأساسية G، العدد الأولي p"
Alice->>Alice: "توليد المفتاح الخاص d_A (عدد صحيح عشوائي)"
Alice->>Alice: "حساب المفتاح العام Q_A = d_A * G"
Bob->>Bob: "توليد المفتاح الخاص d_B (عدد صحيح عشوائي)"
Bob->>Bob: "حساب المفتاح العام Q_B = d_B * G"
Alice->>Bob: "إرسال المفتاح العام Q_A (نص صريح)"
Bob->>Alice: "إرسال المفتاح العام Q_B (نص صريح)"
Alice->>Alice: "حساب السر المشترك S = d_A * Q_B"
Bob->>Bob: "حساب السر المشترك S = d_B * Q_A"
Note over Alice,Bob: "S = d_A * (d_B * G) = d_B * (d_A * G) = (d_A * d_B) * G"
Note over Alice,Bob: "النتيجة الحسابية S لكلا الطرفين متطابقة تمامًا!"&lt;/div>
&lt;p>يمكن للمتنصت (إيف) اعتراض $G$ و $Q_A$ و $Q_B$ أثناء انتقالها عبر قناة الاتصال، ولكن نظرًا لصعوبة ECDLP، لا يمكن استنتاج المفتاح الخاص لأليس $d_A$ من $Q_A = d_A \cdot G$. علاوة على ذلك، فإن ضرب $Q_A$ في $Q_B$ لا ينتج المفتاح المشترك $S$، لذلك لا يستطيع المتنصت حساب $S$.&lt;/p>
&lt;hr>
&lt;h2 id="7-فخاخ-التنفيذ-هجمات-القنوات-الجانبية-وطرق-الوقاية-منها">7. فخاخ التنفيذ: هجمات القنوات الجانبية وطرق الوقاية منها
&lt;/h2>&lt;p>حتى لو كانت خوارزمية التشفير مثالية نظريًا، فقد تنشأ نقاط ضعف أثناء عملية تحويلها إلى برنامج. هذا ما يُعرف بـ &lt;strong>&amp;ldquo;هجوم القناة الجانبية (Side-Channel Attack)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="71-هجوم-التوقيت-timing-attack">7.1. هجوم التوقيت (Timing Attack)
&lt;/h3>&lt;p>دعونا نراجع خوارزمية المضاعفة والجمع المذكورة أعلاه.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// الكود الزائف لـ Double-and-Add الضعيف
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="n">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Infinity&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">255&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PointDoubling&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// يتم تنفيذه دائمًا
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">bit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PointAddition&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// يتم تنفيذه فقط عندما يكون البت 1!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>هذا التنفيذ يحتوي على خلل قاتل. نظرًا لأن Point Addition يتم تنفيذه عندما يكون البت &lt;code>1&lt;/code>، فإن &lt;strong>وقت الحساب سيكون أطول قليلاً&lt;/strong> مما لو كان البت &lt;code>0&lt;/code>. كما يتغير سلوك التنبؤ بالتفرعات في المعالج (Branch Prediction) وذاكرة التخزين المؤقت (Cache).
من خلال مراقبة هذه الفروق الدقيقة في وقت الحساب (أو استهلاك الطاقة) إحصائيًا لآلاف المرات، يمكن للمهاجم &lt;strong>استعادة سلسلة بتات المفتاح الخاص $k$ بتًا بتًا بالكامل&lt;/strong>. هذا هو هجوم التوقيت.&lt;/p>
&lt;h3 id="72-تنفيذ-الوقت-الثابت-constant-time-سلم-مونتغمري-montgomery-ladder">7.2. تنفيذ الوقت الثابت (Constant-Time): سُلَّم مونتغمري (Montgomery Ladder)
&lt;/h3>&lt;p>لمنع هجمات التوقيت، من الضروري اعتماد خوارزمية تكون فيها &lt;strong>سلسلة الأوامر المنفذة ووقت الحساب ثابتين دائمًا (Constant-Time) بغض النظر عن قيمة بتات المفتاح الخاص&lt;/strong>.&lt;/p>
&lt;p>المثال الأبرز على ذلك هو &lt;strong>سُلَّم مونتغمري (Montgomery Ladder)&lt;/strong>.&lt;/p>
&lt;div class="mermaid">graph TD
Start["التهيئة: R0 = O, R1 = P"] --> LoopStart["لكل بت i (من البت الأعلى)"]
LoopStart --> Cond{"ما هي قيمة k_i ؟"}
Cond -->|0| Branch0["R1 = R0 + R1&lt;br>R0 = 2 * R0"]
Cond -->|1| Branch1["R0 = R0 + R1&lt;br>R1 = 2 * R1"]
Branch0 --> LoopEnd["إلى البت التالي"]
Branch1 --> LoopEnd
LoopEnd --> LoopStart
LoopStart -.->|"اكتملت جميع البتات"| End["النهاية: R0 هو النتيجة (kP)"]&lt;/div>
&lt;p>يكمن جمال Montgomery Ladder في أنه، سواء كان البت &lt;code>0&lt;/code> أو &lt;code>1&lt;/code>، يتم &lt;strong>&amp;ldquo;دائمًا تنفيذ عملية Point Addition واحدة وعملية Point Doubling واحدة&amp;rdquo;&lt;/strong>. هذا يقضي تمامًا على اعتماد وقت الحساب على البيانات.&lt;/p>
&lt;p>ومع ذلك، إذا كان هناك تفرع (Branch) نفسه (&lt;code>if (k_i == 0)&lt;/code>)، يظل هناك خطر تغير وقت التنفيذ بسبب تحسينات المترجم (Compiler Optimizations) أو التنبؤ بالتفرعات في وحدة المعالجة المركزية. لذلك، في تنفيذ الوقت الثابت الفعلي، يتم استبعاد الشروط (جملة &lt;code>if&lt;/code>)، ويُستخدم &lt;strong>التبديل الشرطي (Conditional Swap) باستخدام العمليات على مستوى البتات (Bitwise Operations)&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h2 id="8-تنفيذ-تشفير-المنحنيات-الإهليلجية-بلغة-c">8. تنفيذ تشفير المنحنيات الإهليلجية بلغة C++
&lt;/h2>&lt;p>من هنا، سنقوم بتطبيق النظرية في كود C++. على الرغم من أن مكتبات التشفير العملية (مثل OpenSSL أو libsodium) تستخدم تحسينات تجميع (Assembly) متقدمة وأنظمة إحداثيات جاكوبي، إلا أننا سنعرض هنا الهيكل الأساسي لـ &lt;strong>تنفيذ واضح بوقت ثابت (Constant-Time) باستخدام نظام الإحداثيات الأفينية (Affine Coordinates)&lt;/strong> لتعميق الفهم الرياضي.&lt;/p>
&lt;p>سنفترض استخدام &lt;code>boost::multiprecision::cpp_int&lt;/code> للعمليات على الأعداد الصحيحة الضخمة.&lt;/p>
&lt;h3 id="81-العمليات-النمطية-والمعكوس">8.1. العمليات النمطية والمعكوس
&lt;/h3>&lt;p>أولاً، سنعرّف دوال مساعدة للعمليات على الحقول المنتهية. سننفذ حساب المعكوس باستخدام مبرهنة فيرما الصغرى.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;stdexcept&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;boost/multiprecision/cpp_int.hpp&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">boost&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">multiprecision&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// مثال: العدد الأولي p ومعلمات secp256k1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">p&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// عملية المعامل للحصول على باقي موجب
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="nl">m&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// حساب قوة المعامل (x^y mod m)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">powerMod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">exp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">res&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">base&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">exp&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">exp&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">res&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">res&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">base&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">base&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">exp&lt;/span> &lt;span class="o">/=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">res&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// المعكوس النمطي باستخدام مبرهنة فيرما الصغرى
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// بافتراض أن m عدد أولي: n^(m-2) ≡ n^(-1) mod m
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">powerMod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="82-تمثيل-النقاط-وعمليات-الزمرة-الجمع-والمضاعفة">8.2. تمثيل النقاط وعمليات الزمرة (الجمع والمضاعفة)
&lt;/h3>&lt;p>سننفذ بنية &lt;code>Point&lt;/code> التي تدير النقطة في اللانهاية بواسطة علامة (Flag)، بالإضافة إلى معادلات الجمع.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="nc">Point&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">bool&lt;/span> &lt;span class="n">isInfinity&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// إنشاء نقطة في اللانهاية
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">isInfinity&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// إنشاء نقطة عادية
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">isInfinity&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">false&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// جمع النقاط على المنحنى الإهليلجي (R = P + Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="nf">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">isInfinity&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">isInfinity&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// P + (-P) = النقطة في اللانهاية
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">lambda&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// مضاعفة النقطة (عندما P = Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// lambda = (3x^2 + a) / 2y
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">den&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lambda&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">den&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// جمع النقاط (عندما P != Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// lambda = (y2 - y1) / (x2 - x1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">den&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lambda&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">den&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lambda&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">lambda&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">y3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lambda&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">x3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y3&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="83-تنفيذ-التبديل-الشرطي-بوقت-ثابت-constant-time-conditional-swap">8.3. تنفيذ التبديل الشرطي بوقت ثابت (Constant-Time Conditional Swap)
&lt;/h3>&lt;p>عند تبديل محتويات المتغيرات بناءً على قيمة بت المفتاح الخاص، سنقوم بالتبديل باستخدام العمليات على البتات (Mask) فقط بدون استخدام جمل &lt;code>if&lt;/code>. هذا يضمن أن يكون مسار التنفيذ ثابتًا تمامًا.&lt;/p>
&lt;blockquote>
&lt;p>[!TIP]
في التنفيذ الفعلي، لا تعد فئات الأعداد الصحيحة الكبيرة ذات التخصيص الديناميكي مثل &lt;code>cpp_int&lt;/code> مناسبة لمعالجة الوقت الثابت (Constant-Time). يرجع ذلك إلى تسريب معلومات التوقيت عبر تخصيص الذاكرة وتغييرات حجم المصفوفة. في المكتبات العملية، يتم تمثيل الأعداد بحجم ثابت (مثلاً مصفوفة من 4 عناصر من نوع uint64_t)، وتُنفذ عمليات التقنيع (Masking) على مستوى البتات. فيما يلي مثال مفاهيمي.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// التبديل الشرطي بوقت ثابت (بافتراض استخدام أعداد صحيحة ثابتة الطول)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// إذا كان البت 1 بَدِّل بين P1 و P2، وإذا كان 0 لا تبدل
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">void&lt;/span> &lt;span class="nf">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">bit&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// البت إما 0 أو 1. القناع (Mask) يكون كله 1 (0xFF..) إذا كان البت 1، وكله 0 إذا كان البت 0.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// (نفترض هنا للتوضيح أن كل كلمة في فئة BigInt ثابتة الطول هي w)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="cm">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> uint64_t mask = 0 - (uint64_t)bit;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> for (int i = 0; i &amp;lt; NUM_WORDS; i++) {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> uint64_t dummy = mask &amp;amp; (P1.x.words[i] ^ P2.x.words[i]);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> P1.x.words[i] ^= dummy;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> P2.x.words[i] ^= dummy;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> // يتم معالجة الإحداثي y وعلامة isInfinity بنفس الطريقة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ※ من الصعب تنفيذ تبديل وقت ثابت مثالي باستخدام boost::multiprecision،
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// لكننا نقتصر هنا على محاكاته باستخدام التفرع لفهم المنطق.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">bit&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">P1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">P2&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="84-الضرب-القياسي-باستخدام-سلم-مونتغمري-montgomery-ladder">8.4. الضرب القياسي باستخدام سُلَّم مونتغمري (Montgomery Ladder)
&lt;/h3>&lt;p>سنجمع بين &lt;code>pointAdd&lt;/code> و &lt;code>cswap&lt;/code> المذكورتين أعلاه لتنفيذ ضرب قياسي آمن.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// الضرب القياسي k * P (باستخدام طريقة سُلَّم مونتغمري)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="nf">scalarMultiply&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Point&lt;/span> &lt;span class="n">R0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// نقطة في اللانهاية
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span> &lt;span class="n">R1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// الحصول على طول بتات k (في secp256k1 هو 256 بت)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">numBits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">numBits&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// الحصول على قيمة البت i (0 أو 1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">bit&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">static_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint8_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bit_test&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// إذا كان bit == 1، يتم التبديل بين R0 و R1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">bit&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// تنفيذ نفس العمليات دائمًا (Point Addition و Point Doubling)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">R1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">R0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// إذا كان bit == 1، يتم التبديل مرة أخرى لإعادة الحالة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">bit&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">R0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>بفضل منطق التنفيذ هذا، سواء كان كل بت من المُعامل $k$ هو &lt;code>0&lt;/code> أو &lt;code>1&lt;/code>، فإن العمليات المُنفذة داخل كل تكرار للحلقة (&lt;code>cswap&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>cswap&lt;/code>) ستكون لها نفس المسار تمامًا، مما يوفر حماية قوية ضد تسريب المعلومات السرية من خلال فروق التوقيت أو أنماط الوصول إلى الذاكرة المخبئية (Cache).&lt;/p>
&lt;hr>
&lt;h2 id="9-الخاتمة">9. الخاتمة
&lt;/h2>&lt;p>قد يبدو تشفير المنحنيات الإهليلجية (ECC) للوهلة الأولى غريبًا متسائلاً &amp;ldquo;لماذا تشكل عملية هندسية مثل رسم خط وعكس نقطة التقاطع نظام تشفير؟&amp;rdquo;. لكنه نتاج دمج مذهل بين الرياضيات وعلم التشفير، حيث يمكن بناء دالة وحيدة الاتجاه ممتازة (مشكلة اللوغاريتم المتقطع) من خلال التعيين إلى عالم منفصل وهو الحقول المنتهية.&lt;/p>
&lt;p>في هذا المقال، شرحنا النقاط الهامة التالية:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>التفوق على RSA&lt;/strong>: يوفر أمانًا قويًا بمفاتيح قصيرة جدًا، مما يجعله مثاليًا لعصر الأجهزة المحمولة وإنترنت الأشياء (IoT) الحديث.&lt;/li>
&lt;li>&lt;strong>أساسيات نظرية الزمر والحقول المنتهية&lt;/strong>: البنية الرياضية التي تشكل أساس ECC.&lt;/li>
&lt;li>&lt;strong>صيغ الجمع والمضاعفة&lt;/strong>: طريقة تنفيذ عمليات الزمرة الجبرية باستخدام معادلة فايرشتراس.&lt;/li>
&lt;li>&lt;strong>تهديدات هجمات القنوات الجانبية&lt;/strong>: كيف أن التفرعات الشرطية المعتمدة على بتات المفتاح الخاص تخلق ثغرات قاتلة.&lt;/li>
&lt;li>&lt;strong>تنفيذ الوقت الثابت (Constant-Time)&lt;/strong>: تقنيات برمجة C++ لمنع الهجمات عن طريق توحيد السلوك على مستوى العتاد باستخدام Montgomery Ladder و Conditional Swap.&lt;/li>
&lt;/ol>
&lt;p>في الواقع، يُعتبر بناء مكتبة تشفير مخصصة للعمل في بيئة إنتاجية أمرًا غير مستحسن بسبب المخاطر الأمنية العالية جدًا (قاعدة &amp;ldquo;لا تصنع تشفيرك الخاص&amp;rdquo; أو &amp;ldquo;Don&amp;rsquo;t roll your own crypto&amp;rdquo;). ومع ذلك، فإن الفهم العميق للخوارزمية والخلفية الرياضية التي تعمل بداخلها، سيكون بمثابة سلاح قوي لا يقدر بثمن للمهندسين الذين يصممون ويديرون أنظمة أكثر أمانًا وعالية الأداء.&lt;/p>
&lt;p>في المقال القادم، نود التعمق أكثر في آلية &lt;strong>ECDSA (خوارزمية التوقيع الرقمي للمنحنيات الإهليلجية)&lt;/strong> التي تستخدم هذه المنحنيات، وكذلك &lt;strong>توقيع شنور (Schnorr Signature)&lt;/strong> المُستخدم في بيتكوين.&lt;/p></description></item></channel></rss>