אלגוריתם רו של פולרד ללוגריתם הבדיד

בתורת המספרים ובקריפטוגרפיה, אלגוריתם רו של פולרד ללוגריתם הבדיד (באנגלית: Pollard’s rho algorithm for discrete logarithms) הוא אלגוריתם הסתברותי לחישוב לוגריתם בדיד בחבורה ציקלית סופית מסדר ראשוני עם זמן ריצה דומה לשיטת כוח גס גנרית הנקראת אלגוריתם צעד-קטן צעד-גדול אך עם צריכת זיכרון שולית ביחס אליה. האלגוריתם פותר את בעיית הלוגריתם הבדיד בהסתברות גבוהה, בסיבוכיות בסדר גודל של <math>O(\sqrt{n})</math> כאשר <math>n</math> הוא סדר החבורה. לצורך אלגוריתם פולרד ההנחה היא שסדר החבורה הוא מספר ראשוני, שאם לא כן, אפשר בשילוב עם אלגוריתם פוליג-הלמן לפתור את בעיית הלוגריתם הבדיד בזמן ריצה שהוא בסדר גודל <math>O(\sqrt{p})</math> כאשר <math>p</math> הוא הגורם הראשוני הגדול ביותר של <math>n</math>.

==היסטוריה==
צורת האות היוונית "רו" של מיפוי אקראי
אלגוריתם רו הומצא על ידי המתמטיקאי הבריטי ג'ון פולרד והתפרסם במאמר "שיטת מונטה קרלו לחישוב אינדקסים" בכתב העת המדעי "Mathematics of Computation" ביולי 1978. בדומה לאלגוריתם רו של פולרד לפירוק לגורמים הוא נקרא בשם זה בשל העובדה שבמיפוי אקראי (או הילוך מקרי) בקבוצה סופית, נוצר מעין "מעגל" אליו מחובר "שובל" קצר וצורתו דומה במקצת לאות היוונית <math>\rho</math> (כמתואר בתרשים משמאל), כלומר בהינתן פונקציה אקראית לאחר מספר מוגבל של ערכים מגיעים לנקודה בה הערכים מתחילים לחזור על עצמם במעגל אין סופי. הרעיון של פולרד ניתן להרחבה לכל סוג של חבורה ציקלית, כמו חבורה אבלית מעל עקום אליפטי הידועה בפופולריות שלה בהצפנה המודרנית ולמעשה לא ידוע על אלגוריתם שמציג סיבוכיות טובה יותר לפתרון בעיית הלוגריתם הבדיד בעקום אליפטי. בחבורה ציקלית מעל מספר ראשוני קיים אלגוריתם תחשיב אינדקסים עם זמן ריצה תת-מעריכי והוא נחשב ליעיל ביותר הידוע כיום למספרים גדולים אך אינו בר ביצוע בעקום אליפטי.

ב-1980 פיתח ריצ'רד ברנט גרסה משופרת יותר של אלגוריתם רו של פולרד לפירוק לגורמים שניתן ליישום גם לפתרון בעיית הלוגריתם הבדיד ומציע שיפור בפקטור של רבע ביעילותו לעומת הגרסה של פולרד. מאוחר יותר פולרד וברנט פיתחו ושיפרו את האלגוריתם אף יותר.

==בעיית הלוגריתם הבדיד==

ביטחון מערכות הצפנה מודרניות רבות מסתמך על ההשערה שקשה לפתור את בעיית הלוגריתם הבדיד (דיסקרטי) בחבורות מסוימות. בהסתמך על בעיה זו ניתן להכין פונקציה חד-כיוונית שהיא הבסיס להצפנה אסימטרית. הדוגמאות אולי החשובות ביותר הן פרוטוקול דיפי-הלמן וחתימה דיגיטלית DSA הפופולריים שמסתמכים על השערה זו, למרות שלא קיימת הוכחה מתמטית.

בעיית הלוגריתם הבדיד המסומנת בקיצור DLP היא כדלקמן:
:{| width="500"
|-
|
:נתונה חבורה ציקלית סופית מסדר <math>n</math> המסומנת <math>G</math> ונתון יוצר <math>\alpha</math> של החבורה ויהי <math>\beta\in G</math> אלמנט כלשהו. מצא את הלוגריתם הבדיד של <math>\beta</math> בבסיס <math>\alpha</math> בקיצור <math>\log_{\alpha} \beta</math> שהוא אלמנט יחיד <math>x</math> בטווח <math>0\le x\le n-1</math> המקיים: <math>\beta=\alpha^x</math>.
|}

בעיית דיפי-הלמן בקיצור DHP, היא בעיה דומה שהועלתה לראשונה על ידי ויטפילד דיפי ומרטין הלמן במאמר המפורסם שלהם שבו הציגו לראשונה את הצפנת מפתח ציבורי ופרוטוקול שיתוף מפתח המבוסס על הבעיה הבאה: נתון המספר הראשוני <math>p</math> ויוצר <math>\alpha</math> של החבורה <math>\mathbb{Z}_p^*</math> וכן נתונים <math>\alpha^x</math> ו-<math>\alpha^y</math> (מודולו <math>p</math>). מצא את <math>\alpha^{xy}</math> מודולו <math>p</math>. בעיה זו נחשבת גם היא לבעיה קשה אם כי לא הוכח האם היא קשה לפחות כבעיית הלוגריתם הבדיד. מאידך, כל דרך לפתרון בעיית הלוגריתם הדיקסרטי יכולה לשמש לפתרון בעיית דיפי-הלמן.

לדוגמה אם נתון המספר הראשוני <math>p=97</math> החבורה <math>\mathbb{Z}_{97}^*</math> היא חבורה ציקלית מסדר <math>n=96</math>. יוצר אפשרי אחד של חבורה זו יכול להיות <math>\alpha=5</math>. (קל לראות שאם מעלים את 5 בחזקת כל המספרים מ-1 עד 96 (מודולו 97) מתקבלים כל האלמנטים של החבורה בלי יוצא מן הכלל לא בהכרח לפי סדר עולה). אם נבחר <math>x=32</math> בחשבון פשוט מתקבל <math>5^{32}\equiv 35\text{ (mod }97)</math> לכן <math>\log_5 35=32</math> בחבורה <math>\mathbb{Z}_{97}^*</math>. וכן, אם <math>y=17</math> אז <math>5^{17}\equiv 83\text{ (mod }97)</math>. אם נתונים האלמנטים <math>5^{32}\equiv 35</math> ו-<math>5^{17}\equiv 83</math> (מודולו 97) בעיית דיפי-הלמן היא לגלות את <math>5^{32\cdot 17}\equiv 61\text{ (mod }97)</math> (כשהאלמנטים <math>x</math> ו-<math>y</math> אינם ידועים).

הבעיה נקראת לוגריתם בדיד כיוון שהיא עוסקת בקבוצה סופית מודולו שלם כלשהו הנקרא מודולוס. ראוי לציין שאף-על-פי שקל לחשב לוגריתמים באופן כללי, אין הדבר נכון לגבי לוגריתם בדיד מכיוון שהתנהגות התוצאה נראית אקראית על פניה ולא ניתן לבצע קירוב. הסיבה שהבסיס הוא יוצר היא כדי שהחבורה תהיה ציקלית כך שכל אלמנט בחבורה ניתן לייצוג כחזקה של היוצר. הדרישה שהחבורה תהיה ציקלית אינה הכרחית, הגדרה כללית יותר של הבעיה, הנקראת בקיצור GDLP, היא מציאת אלמנט <math>x</math> המקיים <math>\alpha^x=\beta</math>, בהנחה שקיים, עבור האלמנטים <math>\alpha,\beta\in G</math> (כאשר <math>\alpha</math> אינו בהכרח יוצר). החבורה החיבורית הנוצרת על ידי עקום אליפטי כאשר הפעולה היא חיבור נקודות בעקום היא דוגמה לחבורה שבה בעיית הלוגריתם הבדיד קשה. אחת הדרכים לפתור את הבעיה היא בעצם חישוב איזומורפיזם בין חבורות. אפילו אם שתי חבורות איזומורפיות זו לזו, אלגוריתם יעיל לפתרון בעיית הלוגריתם הבדיד בחבורה אחת, אינו בהכרח יעיל בחבורה השנייה. למשל כל חבורה כפלית ציקלית מסדר <math>n</math> איזומורפית לחבורה החיבורית הציקלית <math>\mathbb{Z}_n</math>. על כל פנים, בעוד שקיים אלגוריתם יעיל לחישוב לוגריתמים בחבורה החיבורית מעל המספרים השלמים מודולו מספר ראשוני, כלומר מציאת שלם המקיים <math>ax\equiv b\text{ (mod }n)</math>, לא ניתן ליישמו לפתרון הלוגריתם הבדיד בחבורה הכפלית.

הדרך הישירה והפשוטה ביותר לפתרון בעיית הלוגריתם הבדיד היא שיטת כוח גס, סריקת כל החזקות של <math>\alpha</math> בזה אחר זה מ-1 עד <math>n</math> עד שמתקבל <math>\beta</math> וסיבוכיותה היא מסדר גודל <math>O(n)</math>. היא אינה יעילה מהיבט קריפטוגרפי כיוון שאם <math>n</math> גדול (נניח באורך <math>n\ge 2^{128}</math> סיביות) התקפה כזו אינה פרקטית. שיטה מעט יותר טובה נקראת "צעד-קטן צעד-גדול" והיא מבוססת על העובדה שאם <math>\beta=\alpha^x</math> אפשר לכתוב את <math>x</math> בצורה: <math>x=im+j</math> (לפי כלל החילוק המודולרי) כאשר <math>j<m</math> ו-<math>m=\left\lceil\sqrt{n}\right\rceil</math>. לכן <math>\alpha^x=\alpha^{im}\alpha^j</math> לאחר העברת אגפים מתקבל <math>\beta(\alpha^{-m})^i=\alpha^j</math>. מהאמור עולה שאם מכינים טבלה המכילה את הזוגות (<math>j,\alpha^j</math>) עבור כל המספרים מ-1 עד <math>m</math>, הממויינת לפי האלמנט השני, מובטח שיימצא אלמנט אחד (אם קיים פתרון) השווה ל-<math>\beta(\alpha^{-m})^i</math>. היות שהטבלה היא בסדר גודל של השורש הריבועי של סדר החבורה וחיפוש בטבלה ממויינת אינו קשה, יוצא שסיבוכיות השיטה היא <math>O(\sqrt{n})</math> אך היא דורשת סיבוכיות מקום בסדר גודל של <math>O(\sqrt{n})</math> ועל כן אם <math>n</math> גדול מאוד (נניח <math>n\ge 2^{128}</math>) היא אינה פרקטית.

==תיאור כללי==
אלגוריתם רו של פולרד מנסה לייצר "סדרה פסידו-אקראית" של אלמנטים מהחבורה בהתבסס על רעיון מונטה קרלו וחיפוש אחר התנגשויות, כלומר שני אלמנטים זהים בסדרה. אם נמצאה התנגשות הדבר מוביל לפתרון בעיית הלוגריתם הבדיד בהסתברות גבוהה. שני רעיונות מרכזיים של פולרד הם פונקציה איטרטיבית אקראית קלה לחישוב, איתה מכינים את הסדרה הפסאודו-אקראית ואלגוריתם מציאת מחזוריות שמנסה למצוא בה התנגשות בזמן הקצר ביותר ללא שימוש בטבלאות. לצורך הפשטות נניח שנתונה חבורה ציקלית <math>G</math> מסדר <math>n</math> ראשוני.

תחילה מחלקים את <math>G</math> לשלוש קבוצות בגודל זהה בקירוב <math>S_1,S_2,S_3</math>, בחלוקה לוגית בהתבסס על כלל מנחה קל לבדיקה. אפשר למשל לחלק לפי משקלו של כל אלמנט באופן הבא הקבוצה <math>S_1</math> תכיל את כל האלמנטים: <math>\textstyle 0<x_i<\frac{1}{3}n</math>, הקבוצה <math>S_2</math> את האלמנטים <math>\textstyle\frac{1}{3}n<x_i<\frac{2}{3}n</math> והשלישית <math>\textstyle\frac{2}{3}n<x_i<n</math>. דרך אחרת יותר יעילה היא לחלק לפי הערך של <math>t</math> הסיביות הכי פחות משמעותיות של כל <math>x_i</math> כאשר <math>t</math> תלוי במספר החלוקות (במקרה זה מספיק לבחון את שתי הסיביות האחרונות). מספר החלוקות שרירותי וניתן לשינוי, אך יש צורך לשים לב לכמה היבטים חשובים בנוגע לחלוקה למשל <math>1\notin S_2</math>.

מחשבים סדרה פסידו-אקראית של אלמנטים מהחבורה לפי הכלל הבא. בוחרים אלמנט התחלתי <math>x_0=1</math> ועבור כל <math>i\ge 0</math> מחשבים:
:<math>x_{i+1}=f(x_i)\overset{\underset{\mathrm{def}}{}}{=}\begin{cases}
\beta\cdot x_i, & \mbox{ if }x_i\in S_1 \\
x_i^2, & \mbox{ if }x_i\in S_2 \\
\alpha\cdot x_i, & \mbox{ if }x_i\in S_3
\end{cases}</math>

בנוסף מתוך הסדרה האמורה מכינים שתי רשימות של שלמים <math>a_0,a_1,a_2,...</math> וכן <math>b_0,b_1,b_2,...</math> כאשר <math>a_0=0</math> ו-<math>b_0=0</math> ועבור כל <math>i\ge 0</math> מחשבים את
:<math>a_{i+1}=\begin{cases}
a_i, & \mbox{ if }x_i\in S_1 \\
2a_i\text{ mod }n, & \mbox{ if }x_i\in S_2 \\
a_i+1\text{ mod }n, & \mbox{ if }x_i\in S_3
\end{cases}</math>
וכן
:<math>b_{i+1}=\begin{cases}
b_i+1\text{ mod }n, & \mbox{ if }x_i\in S_1 \\
2b_i\text{ mod }n, & \mbox{ if }x_i\in S_2 \\
b_i, & \mbox{ if }x_i\in S_3
\end{cases}</math>

הערכים של <math>a_i</math> ו-<math>b_i</math> מחושבים כך שעבור כל <math>i</math> מתקיים <math>x_i=\alpha^{a_i}\cdot\beta^{b_i}</math>. אם <math>x_i=x_j</math> כאשר <math>i\ne j</math> זה אומר שנמצאה "התנגשות". כדי למצוא התנגשות ביעילות האלגוריתם מנצל טכניקה המיוחסת לרוברט פלויד (לפי דונלד קנות') שנקראת מציאת מחזוריות או "שיטת הצב והארנב" שהיא שיטה יעילה לאיתור מחזוריות של פונקציה איטרטיבית אקראית על עצמה מהצורה <math>f:X\rightarrow X</math>. מנסים באופן רקורסיבי לאתר את הנקודה בה הסדרה מתחילה לחזור על עצמה. מבצעים בכל איטרציה שתי הליכות, הליכה איטית והליכה מהירה. בהליכה איטית מחשבים מתוך הערכים מהאיטרציה הקודמת את השלשה החדשה (<math>x_i,a_i,b_i</math>) ובהליכה מהירה את <math>(x_{2i},a_{2i},b_{2i})</math> ומשווים בין <math>x_i</math> ל-<math>x_{2i}</math>, אם הם שווים אותרה מחזוריות הפונקציה וזה אומר שמנקודה זו ואילך המסלול יחזור על עצמו במעגל אין סופי. סיבוכיות הטכניקה הזו זהה לשיטה הישירה המסתמכת על חיפוש בטבלאות ומבזבזת זיכרון רב. אם נמצאה התאמה המשמעות היא ש-<math>\alpha^{a_i}\beta^{b_i}=\alpha^{a_{2i}}\beta^{b_{2i}}</math> ולכן <math>\beta^{b_i-b_{2i}}=\alpha^{a_{2i}-a_i}</math>. אם לוקחים לוגריתם בבסיס <math>\alpha</math> של שני האגפים במשוואה האחרונה מתקבל
:<math>(b_i-b_{2i})\cdot\log_{\alpha}\beta\equiv(a_{2i}-a_i)\text{ (mod }n)</math>.
בהנחה ש-<math>b_i\not\equiv b_{2i}\text{ (mod }n)</math>, שבכל מקרה עלול לקרות בהסתברות מאוד זניחה. מתוך המשוואה האחרונה אפשר לחלץ את <math>\log_{\alpha}\beta</math> על ידי הכפלה בהופכי הכפלי של <math>(b_i-b_{2i})</math>.

==פירוט מהלכי האלגוריתם==
אלגוריתם רו של פולרד

קלט: החבורה <math>G</math> מסדר <math>n</math>, יוצר <math>\alpha</math> והאלמנט <math>\beta</math>.

פלט: הלוגריתם הבדיד <math>x=\log_{\alpha}\beta</math>.

# מציבים <math>x_0=1, a_0=0, b_0=0</math>.
# מבצעים לולאה עם <math>i=1,2,3,...</math>
## מחשבים את הערכים של <math>x_i,a_i,b_i</math> מתוך הערכים הקודמים <math>x_{i-1},a_{i-1},b_{i-1}</math> וכן <math>x_{2i-2},a_{2i-2},b_{2i-2} </math> לפי הנוסחאות המתוארות לעיל.
## אם <math>x_i=x_{2i}</math> מבצעים:
### מציבים <math>r=b_i-b_{2i}\text{ mod }n</math>
### אם <math>r=0</math> אלגוריתם מסתיים בכישלון אחרת מחזירים את <math>x=r^{-1}(a_{2i}-a_i)\text{ mod }n</math>.

במקרה הנדיר שהאלגוריתם מסתיים בכישלון מגרילים <math>a_0,b_0</math> אחרים ומתחילים מההתחלה כאשר <math>x_0=\alpha^{a_0}\beta^{b_0}</math>.

===דוגמה במספרים קטנים===
נתונה תת-חבורה <math>G</math> של החבורה <math>\mathbb{Z}_{383}^*</math> מסדר <math>n=191</math> עם היוצר <math>\alpha=2</math> ונתון <math>\beta=228</math>.
חלוקת האלמנטים של <math>G</math> לשלוש קבוצות מתבצעת לפי הכלל הבא: מחשבים את <math>x\text{ mod }3</math>, אם השארית 1 הוא שייך ל-<math>S_1</math>, אם השארית היא 0 הוא שייך ל-<math>S_2</math> ואילו אם השארית היא 2 הוא שייך ל-<math>S_3</math>. הטבלה הבאה מסכמת את מהלכי האלגוריתם והערכים של <math>x_i,a_i,b_i</math> וכן <math>x_{2i},a_{2i},b_{2i}</math> לאחר כל איטרציה. באיטרציה ה-14 נמצאה התנגשות כי <math>x_{14}=x_{28}=144</math>. לכן מחשבים את <math>r=38-104=125\text{ (mod }191)</math> וההופכי שלו <math>125^{-1}\equiv 136\text{ (mod }191)</math> ולכן <math>136\cdot(10-12)\equiv 110\text{ (mod }191)</math> והפתרון הוא <math>\log_2 228=110</math> מודולו 191.

<center>
{| class="wikitable" dir="ltr"
|-
| <math>i</math> || <math>x_i</math> || <math>a_i</math> || <math>b_i</math> || <math>x_{2i}</math> || <math>a_{2i}</math> || <math>b_{2i}</math>
|-
| 1 || 228 || 0 || 1 || 279 || 0 || 2
|-
| 2 || 279 || 0 || 2 || 184 || 1 || 4
|-
| 3 || 92 || 0 || 4 || 14 || 1 || 6
|-
| 4 || 184 || 1 || 4 || 256 || 2 || 7
|-
| 5 || 205 || 1 || 5 || 304 || 3 || 8
|-
| 6 || 14 || 1 || 6 || 121 || 6 || 18
|-
| 7 || 28 || 2 || 6 || 144 || 12 || 38
|-
| 8 || 256 || 2 || 7 || 235 || 48 || 152
|-
| 9 || 152 || 2 || 8 || 72 || 48 || 154
|-
| 10 || 304 || 3 || 8 || 14 || 96 || 118
|-
| 11 || 372 || 3 || 9 || 256 || 97 || 119
|-
| 12 || 121 || 6 || 18 || 304 || 98 || 120
|-
| 13 || 12 || 6 || 19 || 121 || 5 || 51
|-
| 14 || 144 || 12 || 38 || 144 || 10 || 104
|}
</center>

==אלגוריתם רו של פולרד בעקום אליפטי==
עקום אליפטי הוא כלי מתמטי פופולרי המצוי בשימוש נרחב בהצפנה מודרנית בשל העובדה שהוא מאפשר פרמטרים קטנים יותר בפקטור של עשר בקירוב לעומת אלגוריתם כמו RSA. עם עקום אליפטי אפשר ליישם פונקציה חד-כיוונית ואיתה לממש הצפנה אסימטרית המבוססת על בעיה מתמטית כמו בעיית הלוגריתם הבדיד בעקום אליפטי. בעיית הלוגריתם הבדיד בעקום אליפטי מקבילה לבעיה הכללית והיא כדלהלן:
:{| width="500"
|-
|
:נתון עקום אליפטי <math>E</math> המוגדר מעל השדה <math>\mathbb{F}_q</math>, נתונה נקודה <math>P\in E(\mathbb{F}_q)</math> מסדר <math>n</math> ונקודה <math>Q\in\langle P\rangle</math>, מצא שלם <math>l</math> בטווח <math>[0,n-1]</math> המקיים <math>Q=lP</math>.
|}

השלם <math>l</math> נקרא הלוגריתם הבדיד של הנקודה <math>Q</math> בבסיס הנקודה <math>P</math> או בקיצור <math>l=\log_PQ</math>. אם הפרמטרים של העקום <math>E</math> נבחרו בזהירות כדי להבטיח שלא יהיו קיצורי דרך לפתרון הבעיה בעקום זה, הדרך הטובה ביותר לפתרונה היא באמצעות אלגוריתם רו של פולרד בסיבוכיות של <math>\sqrt{n}</math>. הסימון <math>\langle P\rangle</math> מייצג את כל הנקודות שהן כפולות של <math>P</math>. (כגון <math>P,2P,3P,4P,...</math> וכן הלאה עד <math>n</math>). במילים אחרות, הנקודה <math>Q</math> היא תוצאה של חיבור הנקודה <math>P</math> בעצמה (הנקראת בקיצור POINT_DBL) בדיוק <math>l</math> פעמים והבעיה היא לגלות כמה פעמים בוצע החיבור, קרי לגלות את ערכו של <math>l</math>. לא קיימת דרך פשוטה לבצע זאת כי המסלול של הנקודות נראה אקראי. שיטת כוח גס אינה מעשית משום שבמקרה הממוצע יש צורך לבדוק לפחות מחצית מהנקודות עד שנמצא <math>lP</math>. אם <math>n\ge 2^{128}</math> כוח גס אינו מעשי. כמובן שיש לשים לב של-<math>n</math> יש לפחות גורם ראשוני אחד גדול דיו. שאם לא כן אפשר לנצל את אלגוריתם פוליג-הלמן בזמן שהוא ביחס ישיר לגודל הגורמים הראשוניים שלו. למעשה ככל שהגורם הראשוני שלו (לפחות אחד מהם) גדול יותר סיבוכיות ההתקפה תהיה גבוהה יותר.

===תיאור כללי===
כמו בחבורה ציקלית, הרעיון של אלגוריתם רו בעקום אליפטי הוא למצוא שני זוגות שלמים (<math>c,d</math>) וכן (<math>e,f</math>) מודולו <math>n</math> המקיימים:
::::<math>cP+dQ=eP+fQ</math>
ואז
::::<math>(c-e)P=(f-d)Q=(f-d)lP</math>
ולכן
::::<math>(c-e)\equiv(f-d)l\text{ (mod }n)</math>
מזה נובע שאפשר לחשב את <math>l=\log_PQ</math> על ידי <math>l=(c-e)(f-d)^{-1}\text{ mod }n</math>.

הדרך הישירה למצוא זוגות המקיימים את המשוואה האמורה היא על ידי בחירה אקראית ואחסון בטבלה. אם מכינים טבלה המכילה את כל השלשות: (<math>c,d,cP+dQ</math>) וממיינים לפי הערך השלישי, מובטח שבסופו של דבר הערך הזה יופיע פעם נוספת מה שיאפשר לגלות את הלוגריתם הבדיד כאמור. תופעה שבה הערך השלישי מופיע פעמיים כאשר הערכים האחרים שונים נקראת "התנגשות". לפי פרדוקס יום ההולדת מספר הניסיונות הצפוי לפני שתופיע התנגשות הוא בערך <math>\textstyle\sqrt{\pi n/2}</math> שזה בערך <math>\textstyle 1.2533\sqrt{n}</math>. אולם החסרון בשיטה זו הוא שיש צורך בזיכרון רב, ליתר דיוק <math>\textstyle\sqrt{\pi n/2}</math> שלשות. אלגוריתם רו מנסה להימנע משימוש בזיכרון על ידי שיטת הצב והארנב. מגדירים פונקציה איטרטיבית אקראית <math>\langle P\rangle\rightarrow\langle P\rangle</math> כך שבהינתן <math>X\in\langle P\rangle</math> והערכים <math>c</math> ו-<math>d</math> כך שמתקיים <math>X=cP+dQ</math> יהיה קל לחשב את <math>\overline{X}=f(X)</math> ואת <math>\overline{c},\overline{d}</math> כך שמתקיים <math>\overline{X}=\overline{c}P+\overline{d}Q</math>.

לדוגמה, אם מחלקים את החבורה הציקלית <math>\langle P\rangle</math> ל-<math>L</math> רשימות בגודל זהה בקירוב (למשל <math>L=32</math>), מציבים כל נקודה <math>X_i</math> ברשימה המתאימה <math>S_j</math> אם הערך של 5 הסיביות הכי פחות משעותיות של הקואורדינטה <math>x</math> של הנקודה <math>X_i</math> הוא <math>j-1</math>. נניח ששיטת חלוקה זו תסומן ב-<math>H(X)</math> ונניח שהערכים <math>a_j</math> ו-<math>b_j</math> הם שלמים אקראיים כלשהם הנמוכים מ-<math>n</math> כאשר <math>j</math> מתפרס על פני כל הרשימות של <math>L</math>, במקרה זה פונקציה אקראית איטרטיבית יכולה להיות:
:<math display="block">f(X)=X+a_jP+b_jQ</math> כאשר <math>j=H(X)</math>
ולכן אם <math>X=cP+dQ</math> אז הפונקציה האקראית היא <math>f(X)=\overline{X}=\overline{c}P+\overline{d}Q</math> כאשר <math>\overline{c}=c+a_j\text{ mod }n</math> וכן <math>\overline{d}=d+b_j\text{ mod }n</math>.
כל נקודה התחלתית <math>X_0\in\langle P\rangle</math> מגדירה סדרה אחרת <math>\{X_i\}_{i\ge 0}</math> של נקודות כאשר כל נקודה מחושבת על ידי הנקודה הקודמת, <math>X_i=f(X_{i-1})</math>. היות שהחבורה הזו סופית בהכרח שתיגרם התנגשות, כלומר ערך של <math>X_i</math> כלשהו יופיע שוב ומנקודה זו ואילך הסדרה תחזור על עצמה במעגל אין סופי. כלומר יופיע האינדקס הקטן ביותר <math>t</math> המקיים <math>X_t=X_{t+s} </math>עבור <math>s</math> כלשהו ומכאן ואילך <math>X_i=X_{i-s}</math> עבור כל <math>i\ge t+s</math>. כאן <math>t</math> הוא אורך השובל ו-<math>s</math> הוא היקף מעגל במונחים של מספר האיטרציות של הפונקציה האיטרטיבית האקראית. אם <math>f</math> היא פונקציה אקראית אז ההתנגשות הראשונה צפויה לקרות לאחר <math>\textstyle\sqrt{\pi n/2}</math> צעדים בקירוב. אורך השובל הוא <math>\textstyle t\approx\sqrt{\pi n/8}</math> ואורך המעגל צריך להיות <math>\textstyle s\approx\sqrt{\pi n/8}</math> בקירוב.

התנגשות היא מצב שבו <math>X_i=X_j</math> כאשר <math>i\ne j</math> ואותה אפשר למצוא ללא צורך בזיכרון באמצעות שיטת פלויד או שיטת הצב והארנב. בשיטה זו מחשבים בכל צעד את הנקודות <math>X_i</math> ו-<math>X_{2i}</math> ומנסים למצוא התאמה. מספר הזוגות הצפוי שיש לבדוק הוא לכל הפחות <math>t</math> זוגות ולכל היותר <math>t+s</math> זוגות, עד שתמצא התנגשות. ליתר דיוק בהנחה ש-<math>f</math> אקראית מספר הזוגות הצפוי שצריך לבדוק עד שתמצא התנגשות הוא <math>\textstyle k=1.0308\sqrt{n}</math>. מספר החישובים שיש לבצע בעקום האליפטי הוא בערך <math>\textstyle 3\sqrt{n}</math> פעולות חיבור נקודות.

===פירוט מהלכי האלגוריתם===
אלגוריתם רו של פולרד לחישוב לוגריתם בדיד בעקום אליפטי.

קלט: הנקודה <math>P\in E(\mathbb{F}_q)</math> מסדר <math>n</math> והנקודה <math>Q\in\langle P\rangle</math>

פלט: הלוגריתם הבדיד <math>l=\log_PQ</math>.

# תחילה בוחרים את מספר הענפים או רשימות <math>L</math> ואת פונקציית החלוקה <math>H</math> שמציבה כל נקודה ברשימה המתאימה לפי הכלל <math>j</math>.
# עבור <math>j=1</math> עד <math>L</math> מבצעים:
## מגרילים שני שלמים <math>a_j,b_j</math> ומחשבים את <math>R_j=a_jP+b_jQ</math>.
#מגרילים זוג שלמים נוספים <math>c,d</math> ומחשבים את <math>X'=cP+dQ</math>.
# מציבים <math>X=X',e=c,f=d</math>.
# חוזרים על המהלכים הבאים:
## <math>j=H(X')</math>
## <math>X'=X'+R_j, c=c+a_j,d=d+b_j\text{ (mod }n)</math>.
## עבור <math>i=1</math> עד 2 מבצעים:
### <math>j=H(X)</math>
### <math>X'=X'+R_j,c=c</math>
### <math>X=X+R_j,e=e+a_j,f=f+b_j\text{ (mod }n)</math>.
## עד שמתקבל <math>X'=X</math>.
#אם <math>d=f</math> האלגוריתם הסתיים בכישלון, אחרת מחזירים את <math>l=(c-e)(f-d)^{-1}\text{ mod }n</math>.

===דוגמה במספרים קטנים===
נתון העקום <math>E(\mathbb{F}_{229})</math> עם המשוואה <math>E:y^2=x^3+x+44</math>. נקודה <math>P=(x,y)=(5,116)</math> היא מסדר ראשוני <math>n=239</math>. תהי הנקודה <math>Q=(155,166)\in\langle P\rangle</math>. כדי למצוא את <math>l=\log_PQ</math> מגדירים תחילה <math>L=4</math> ובוחרים פונקציית חלוקה <math>H:\langle P\rangle\rightarrow\{1,2,3,4\}</math> לפי הכלל:
:<math>H(x,y)=(x\text{ mod }4)+1</math>
בוחרים ומחשבים ארבע שלשות:
:<math>[a_1,b_1,R_1]=[79,163,(135,117)]</math>
:<math>[a_2,b_2,R_2]=[206,19,(96,97)]</math>
:<math>[a_3,b_3,R_3]=[87,109,(84,62)]</math>
:<math>[a_4,b_4,R_4]=[219,68,(72,134)]</math>
הטבלה הבאה מציגה את השלשות (<math>c,d,X'</math>) ו-(<math>e,f,X</math>) המתקבלות לאחר הצעד הרביעי באלגוריתם עבור המקרה <math>(c,d)=(54,175)</math>.

<center>
{| class="wikitable" dir="ltr"
|-
! <math>i</math> !! <math>c</math> !! <math>d</math> !! <math>X</math> !! <math>c</math> !! <math>d</math> !! <math>X</math>
|-
| – || 54 || 175 || (39,159) || 54 || 175 || (39,159)
|-
| 1 || 34 || 4 || (160,9) || 113 || 167 || (130,182)
|-
| 2 || 113 || 167 || (130,182) || 180 || 105 || (36,97)
|-
| 3 || 200 || 37 || (27,17) || 0 || 97 || (108,89)
|-
| 4 || 180 || 105 || (36,97) || 46 || 40 || (223,153)
|-
| 5 || 20 || 29 || (119,180) || 232 || 127 || (167,57)
|-
| 6 || 0 || 97 || (108,89) || 192 || 24 || (57,105)
|-
| 7 || 79 || 21 || (81,168) || 139 || 111 || (185,227)
|-
| 8 || 46 || 40 || (223,153) || 193 || 0 || (197,92)
|-
| 9 || 26 || 108 || (9,18) || 140 || 87 || (194,145)
|-
| 10 || 232 || 127 || (167,57) || 67 || 120 || (223,153)
|-
| 11 || 212 || 195 || (75,136) || 14 || 207 || (167,57)
|-
| 12 || 192 || 24 || (57,105) || 213 || 104 || (57,105)
|}
</center>

אפשר לראות בשורה האחרונה בטבלה שהאלגוריתם מצא התנגשות כי:
:<math>192P+24Q=213P+104Q</math>
לכן
:<math>l=(192-213)\cdot (104-24)^{-1}\text{ mod }239=176</math>.

===שיפורים===
בגלל הפופולריות של עקומים אליפטיים בקריפטוגרפיה, נעשה מאמץ לשפר את אלגוריתם רו של פולרד בין היתר על ידי עיבוד מקבילי. נניח שזמינים <math>M</math> מחשבים לצורך פתרון הבעיה. הדרך הנאיבית היא להריץ את האלגוריתם על כל מחשב בנפרד עם נקודות התחלה אקראיות שונות, עד שאחד מהם יגלה התנגשות. שיטה זו אינה מנצלת את פוטנציאל המקביליות כי השיפור בביצועים הוא בפקטור <math>\sqrt{M}</math> לכל היותר. פול ואן-אורשוט ומייקל ויינר הציעו גרסה מקבילית של אלגוריתם רו שמניבה שיפור בביצועים בפקטור של <math>M</math>. הרעיון הוא לאפשר לכל הסדרות <math>\{X_i\}_{i\ge 0}</math> של כל המעבדים להתנגש אחת עם השנייה. ביתר פירוט, כל מעבד בוחר לעצמו נקודת התחלה <math>X_0</math> באופן אקראי בנפרד מהאחרים, אולם כל המעבדים משתמשים באותה פונקציה איטרטיבית כדי לחשב את האלמנט הבא בסדרה <math>X_{i+1}</math>. לכן, אם נוצרת התנגשות בין שתי סדרות, כל הנקודות של שתי הסדרות החל בנקודה שבה הופיעה התנגשות תהיינה זהות. כדי להתאים את אלגוריתם פלויד למציאת מחזוריות בין סדרות נפרדות שנוצרות על ידי מעבדים שונים, נוקטים באסטרטגיה הבאה, בוחרים מאפיין ייחודי קל לזיהוי המשמש כ"נקודה מובחנת" (Distinguished Point). נקודה מובחנת יכולה להיות כזו המכילה למשל רצף של <math>t</math> אפסים מובילים בקואורדינטה <math>x</math> שלה. בכל פעם שמעבד נתקל בנקודה מובחנת כזו הוא משדר את הנקודה לשרת מרכזי שאוסף את כל הנקודות המובחנות מכל המעבדים וממיין אותם בזיכרון. אם השרת מקבל בשלב כלשהו נקודה מובחנת שכבר התקבלה קודם לכן, הוא מחשב את הלוגריתם הבדיד ומסיים בהצלחה.

אם הפרופורציה של הנקודות המובחנות ב-<math>\langle P\rangle</math> היא <math>\theta</math> הסיכויים לקבל התנגשות הם בערך <math>1/\theta</math> לכן מספר פעולות כפל נקודות בעקום הצפוי מכל מעבד עד שמתקבלת התנגשות אחת הוא
:<math>\frac{1}{M}\sqrt{\frac{\pi n}{2}}+\frac{1}{\theta}</math>.
בכך מושגת האצה ליניארית במהירות הביצוע של האלגוריתם ביחס למספר המעבדים הזמינים. ההתקשרות עם השרת המרכזי היא מינימלית וכן אין צורך בתקשורת כלשהי של המחשבים בינם לבין עצמם מלבד עם השרת. אפשר לשלוט בכמות הזיכרון הנדרשת בשרת המרכזי על ידי בחירה נכונה של תכונת ההבחנה באופן כזה שמצד אחד לא תהיה נדירה ויהיה קשה למצוא נקודה כזו אך מצד שני שלא תהיה תדירה מדי ואז כמות הזיכרון עלולה להיות מופרזת.

דרך נוספת לשפר ביצועים היא על ידי שימוש באוטומורפיזם. יהי <math>\psi:\langle P\rangle\rightarrow\langle P\rangle</math> אוטומורפיזם של חבורה, כאשר <math>P</math> היא נקודה בעקום מסדר <math>n</math>. בהנחה שקל לחשב את <math>\psi</math> והיא מסדר <math>t</math>. כלומר <math>t</math> הוא השלם הקטן ביותר כך ש-<math>\psi^t(R)=R</math> עבור כל <math>R</math> ב-<math>\langle P\rangle</math>. מגדירים יחס שקילות על <math>\langle P\rangle</math> המסומן <math>\sim</math> על ידי
:<math>R_1\sim R_2</math> אם ורק אם <math>R_1=\psi^j(R_2)</math> עבור <math>j</math> בטווח <math>[0, t-1]</math>. מחלקת השקילות [R] היא
:<math>[R]=\{R,\psi(R),\psi^2(R),...,\psi^{l-1}(R)\}</math>
כאשר <math>l</math> הוא המחלק הקטן ביותר של <math>t</math> המקיים <math>\psi^l(R)=R</math>.
הרעיון בהאצת האלגוריתם הוא לשנות את פונקציית האיטרציה <math>f</math> שתהיה מעל מחלקת השקילות <math>[R]</math>. כדי לעשות זאת מגדירים הצגה קנונית של <math>\overline{R}</math> של כל מחלקת שקילות <math>[R]</math>. למשל <math>\overline{R}</math> יכולה להיות הנקודה ב-<math>[R]</math> שהקואורדינטה <math>x</math> שלה היא השלם הקטן ביותר. או למשל העתקת השלילה <math>\psi(P)=-P</math>. שאז אפשר להגדיר את פונקציית האיטרציה <math>g</math> על ידי
:<math>g(R)=\overline{f(R)}</math>.
אם נניח שקיים שלם <math>\lambda</math> המקיים <math>\psi(P)=\lambda P</math> אז, היות ש-<math>\psi</math> היא אוטומורפית מתקבל <math>\psi(R)=\lambda R</math> עבור כל <math>R\in\langle P\rangle</math>. אם מוצאים שני שלמים <math>a,b</math> המקיימים <math>X=aP+bQ</math> אז אפשר לחשב בקלות את השלמים <math>a',b'</math> המקיימים <math>\overline{X}=a'P+b'Q</math>. אם <math>\overline{X}=\psi^j(X)</math> אז <math>a'=\lambda^ja\text{ mod }n</math> וכן <math>b'=\lambda^jb\text{ mod }n</math>. הפונקציה <math>g</math> כאן משמשת כפונקציה איטרטיבית באלגוריתם רו בגרסה המקבילית שלו עם <math>M</math> מעבדים. הנקודה התחלתית של כל סדרה היא <math>X_0'=\overline{X_0}</math> כאשר <math>X_0=a_0P+b_0Q</math> ו-<math>a_0,b_0</math> הם שלמים אקראיים הנמוכים מ-<math>n</math>. הנקודות הבאות בכל סדרה מחושבות על ידי <math>X_i'=g(X_{i-1}')</math>. אם רוב מחלקות השקילות של <math>\langle P\rangle</math> הן באורך <math>t</math> אז טווח החיפוש מצטמצם ל-<math>n/t</math> ולכן זמן הרצוי המשוער של האלגוריתם בגרסה משופרת זו הוא
:<math>\frac{1}{M}\sqrt{\frac{\pi n}{2t}}+\frac{1}{\theta}</math>.
זהו שיפור בפקטור של <math>\sqrt{t}</math> במהירות הביצוע. אם משתמשים בהעתקת השלילה <math>\psi(P)=-P</math> כאוטומורפיזם, מושג שיפור בפקטור של <math>\sqrt{2}</math>.

במקרה של עקום קובליץ <math>E_a</math> מעל <math>\mathbb{F}_2</math> שהוא עקום פופולרי בתקנים של NIST וסרטיקום, העתקת פרובניוס <math>\tau:E_a(\mathbb{F}_{2^m})\rightarrow E_a(\mathbb{F}_{2^m})</math> המוגדרת על ידי <math>\tau(\mathcal{O})=\mathcal{O}</math> וכן <math>\tau(x,y)=(x^2,y^2)</math> גם היא אוטומורפיזם של חבורה מסדר <math>m</math> והיא קלה לחישוב היות שהעלאה בריבוע היא פעולה קלה בשדה הבינארי (בהצגה פולינומית העלאה בריבוע מודולו 2 שקולה למעשה להכנסת אפסים בין כל הספרות לסירוגין). אם <math>P\in E_a</math> הוא מסדר ראשוני <math>n</math> כך ש-<math>n^2</math> אינו מחלק של סדר העקום המסומן ב-<math>\#E_a</math> אז <math>\tau(P)\in\langle P\rangle</math> ולכן <math>\tau</math> היא אוטומורפית. יהי <math>\mu=(-1)^{1-a}</math> אפשר להוכיח שאחד מהפתרונות <math>\lambda</math> של המשוואה המודולרית <math>\lambda^2-\mu\lambda+2\equiv 0\text{ (mod }n)</math> מקיים <math>\tau(P)=\lambda P</math>. לכן באופן דומה, הגרסה המקבילית של אלגוריתם רו עם <math>M</math> מעבדים המשתמשת במחלקות השקילות תחת העתקת פרובניוסמגיעה לזמן ריצה של
:<math>\frac{1}{M}\sqrt{\frac{\pi n}{2m}}+\frac{1}{\theta}</math>.
ואם מנצלים גם את העתקת השלילה מושג שיפור כולל בזמן הריצה בפקטור של <math>\sqrt{2m}</math>.

למשל ההערכה המקורית שניתנה ב-1996 הייתה שכדי לפתור את בעיית הלוגריתם הבדיד בעקום אליפטי מסדר 113 בהנחה שזמינים 10,000 מעבדים לצורך המשימה כשכל אחד מהם מסוגל לבצע איטרציה אחת בעשר מילישניות, אם <math>\theta=2^{-30}</math> אז מספר החזרות הצפוי בכל מעבד לפני שמוצאים לוגריתם הוא
:<math>\frac{ \sqrt{\pi 2^{113}}}{2\cdot 10000}+2^{30}\approx 9.03\times 10^{13}</math>.
שזה שקול בערך ל-1045 ימים או שלוש שנות עיבוד עם כמות של כארבע גיגה-בית זיכרון. הערכות יותר מעודכנות קצת יותר אופטימיות. לדוגמה ב-2002 הצליח צוות חוקרים בראשות קריס מוניקו לפצח את העקום האליפטי ECCp-109 עם 10,000 מחשבים שעבדו במקביל בסך הכול 549 ימים. הם השתמשו בגרסה משופרת של אלגוריתם רו של פולרד והצליחו לפתור את בעיית דיפי-הלמן בעקום זה.

==לקריאה נוספת==
*Hankerson, Darrel, Menezes, Alfred J., Vanstone, Scott (2004) [https://web.archive.org/web/20180403175058/http://crypto.cs.mcgill.ca/~simonpie/webdav/ipad/EBook/Crypto/Guide%20to%20Elliptic%20Curve%20Cryptography%20-%20D.%20Hankerson,%20A.%20Menezes,%20S.%20Vanstone.pdf Guide to Elliptic Curve Cryptography]

==הערות שוליים==

קטגוריה:תורת המספרים
קטגוריה:קריפטוגרפיה
קטגוריה:אלגוריתמים