Digital Signature Algorithm

Digital Signature Algorithm (בתרגום חופשי אלגוריתם חתימה דיגיטלית) הוא מנגנון קריפטוגרפי לחתימה דיגיטלית שאומץ על ידי ממשלת ארצות הברית כתקן פדרלי (FIPS) לאימות והבטחת שלמות מסמכים דיגיטליים בתחילת 1993. 

אלגוריתם DSA הוצע לראשונה על ידי המכון הלאומי לתקנים וטכנולוגיה באוגוסט 1991 כחלק מתקן חתימה דיגיטלית DSS הקרוי תקן FIPS 186. ב-1996 פורסם עדכון FIPS 186-1 שהורחב בשנת 2000 בתקן FIPS 186-2. ב-2009 פורסם עדכון FIPS 186-3 וב-2013 פורסם עדכון FIPS 186-4. האלגוריתם רשום כפטנט בארצות הברית מאז 1991 על שמו של דויד קרביץ, עובד לשעבר של NSA והזכויות על הפטנט הוענקו לממשלת ארצות הברית. לאחר מכן פורסם האלגוריתם והופץ על ידי NIST באופן רשמי לשימוש חופשי.

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

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

כמעט כל אלגוריתם מפתח-פומבי יכול לשמש כבסיס למנגנון חתימה דיגיטלית. הרעיון של מנגנון החתימה של DSA מבוסס על בעיית הלוגריתם הבדיד והוא וריאציה של אל-גמאל. הוא מנצל את הקושי שבפתרון בעיית חישוב לוגריתמים בחבורות, שהיא כידוע בעיה קשה מבחינה חישובית. למעשה האלגוריתם מסתמך על שתי בעיות קשורות של לוגריתם בדיד. האחת לוגריתם בדיד בחבורה כיפלית <math>\ Z^{*}_ {p}</math> מודולו <math>\ p</math> (ראשוני) גדול. והשנייה מציאת לוגריתמים בתת-חבורה ציקלית מסדר ראשוני <math>\ q</math> כלשהו (<math>\ q < p</math>). כמו כן מנגנון החתימה כולל, שימוש בפונקציית גיבוב.
250px

== חתימה ואימות ==
אלגוריתם חתימה דיגיטלית DSA כולל מספר פרמטרים בסיסיים: מפתח פרטי <math>x</math>, מספר חד-פעמי <math>k</math> המתאים למסר יחיד, שניהם סודיים ופונקציית גיבוב מוסכמת כמו SHA-2 המסומנת כאן בקיצור <math>H</math>. אימות החתימה נעשה בעזרת אותם פרמטרים יחד עם מפתח ציבורי <math>y</math> המשויך באופן מתמטי למפתח הפרטי שאיתו בוצעה החתימה ואלגוריתם הגיבוב <math>H</math>. הפרמטרים מתוארים להלן:

:<math>\ p</math> מודולוס ראשוני גדול, המקיים <math>\ 2^ {L-1} < p < 2^ {L}</math>
::(<math>\ L</math> מייצג את גודל <math>\ p</math> בסיביות, ראו להלן).

:<math>\ q</math> מחלק ראשוני של (<math>\ p - 1</math>), המקיים <math>\ 2^ {N-1} < q < 2^ {N}</math> 
::(<math>\ N</math> מייצג את גודל <math>\ q</math> בסיביות, ראו להלן).

:<math>\ g</math> יוצר של תת-חבורה מסדר <math>\ q</math> מודולו <math>\ p</math>, כאשר <math>1 < g < p</math>. 
::להכנת <math>\ g</math> בוחרים שלם <math>\ h</math> כך ש-<math>\ 1 < h < (p-1)</math> ומחשבים את <math>\ g = h^ {(p-1)/q} \mbox{ mod } p</math>, אם <math>\ g = 1</math> חוזרים על התהליך עם <math>\ h</math> אחר.

:<math>\ x</math> מפתח פרטי וסודי. <math>\ x</math> צריך להיבחר באופן אקראי בטווח <math>\left[1 ,q-1 \right]</math>.

:<math>\ y</math> מפתח ציבורי, אותו מחשבים כך: <math>\ y = g^ {x} \mbox{ mod } p</math>.

:<math>\ k</math> מספר ייחודי חד-פעמי עבור כל מסר. ייבחר באופן אקראי בטווח <math>\left[1 ,q-1 \right]</math>.

הערה: במקום לחשב תחילה את <math>\ p</math> ולאחר מכן למצוא מחלק ראשוני <math>\ q</math> של <math>\ (p - 1)</math>, אפשר קודם למצוא את <math>\ q</math> לאחר מכן לבדוק אם <math>\ q \cdot i+1 = p</math> הוא ראשוני, עבור <math>\ i</math> שלם כלשהו הגדול מ-1. למעשה התקן של NIST מפרט אלגוריתם מומלץ למציאת <math>\ p,q</math>.

לצורך קביעת גודל הפרמטרים, התקן מפרט מבחר זוגות של <math>N</math> ו-<math>L</math> המבטאים גודל בסיביות של <math>p</math> ו-<math>q</math> בהתאמה לפי הטבלה הבאה: 
{| class="wikitable"
|-
| N = 160 || L = 1024
|-
| N = 224 || L = 2048
|-
| N = 256 || L = 2048
|-
| N = 256 || L = 3072
|}

== חתימת DSA ==
החתימה על המסר <math>\ m</math> מורכבת מזוג המספרים <math>\ s</math> ו-<math>\ r</math> המחושבים כדלהלן:

::# <math>\ r = (g^ {k} \mbox{ mod } p) \mbox{ mod } q</math>
::# יהיה <math>\ z</math> שווה <math>\ \mbox{min}(N, outlen)</math> הסיביות הנמוכות של <math>\ \mbox{H}(m)</math> כאשר <math>\ outlen</math> מייצג את האורך בסיביות של תוצאת פונקציית הגיבוב.
::# <math>\ s = (k^ {-1} (z + xr)) \mbox{ mod } q</math>

<math>\ \mbox{H}(m)</math> הוא ערך גיבוב שנוצר באמצעות פונקציית גיבוב המצוינת בתקן. <math>\ k^{-1}</math> הוא ההופכי של <math>\ k</math> מודולו <math>\ q</math>. יש לוודא כי <math>\ s</math> או <math>\ r</math> לא שווים 0, אף על פי שמקרה כזה נדיר אם תהליך החתימה בוצע נכון. כמו כן כחלק משלב הכנה מוקדם אפשר לחשב את <math>\ r</math> ללא תלות ב-<math>\ m</math>.

== אימות ואישור החתימה ==
אישור החתימה נעשה על ידי כל גורם, בעזרת המפתח הפומבי של החותם. תחילה, על המידע הפומבי הנחוץ להיות נגיש לבודק החתימה באופן מזוהה ומוכח. למשל באמצעות תעודה חתומה על ידי רשות אשרור (CA) מקובלת או במפגש אישי בין הצדדים. כמובן על הבודק לוודא כי הערכים <math>\ r</math> ו-<math>\ s</math> אינם שווים 0 או גדולים מ-<math>\ q</math>. תחילה מחשבים את הערכים הבאים:

::# <math>\ w = s^ {-1} \mbox{ mod } q</math> (ההופכי של <math>\ s</math> מודולו <math>\ q</math>)
::# יהיה <math>\ z</math> שווה <math>\ \mbox{min}(N, outlen)</math> הסיביות הנמוכות של <math>\ \mbox{H}(m)</math>
::# <math>\ u_1 = (zw) \mbox{ mod } q</math>
::# <math>\ u_2 = (rw) \mbox{ mod } q</math>
::# <math>\ v = ((g^{u_1} y^{u_2}) \mbox{ mod } p) \mbox{ mod } q</math>

אם ורק אם <math>\ v = r</math>, החתימה מתקבלת כאותנטית, אחרת מניחים כי המסר או החתימה שונו בידי גורם שלישי לא ידוע, אולי בניסיון לזייף את החתימה. או שחלה טעות במהלך החתימה או האימות.

== הוכחה לנכונות האלגוריתם ==
אם <math>\ r</math> ו-<math>\ s</math> הופקו על ידי בעל החתימה הלגיטימי מהערך <math>\ z</math>, אזי חייב להתקיים:
:<math>\ z \equiv -xr+ks \ (\mbox{mod }q)</math>. 
אם מכפילים את שני אגפי השקילות הזו ב-<math>\ w</math>, אחרי העברת אגפים מתקבל:
:<math>\ w \cdot z+xrw \equiv k \ (\mbox{mod }q)</math>. 
תוצאה זו למעשה שקולה ל:
:<math>\ u_1+xu_2 \equiv k \ (\mbox{mod }q)</math>. 
אם מעלים את <math>\ g</math> בחזקת שני אגפי השקילות האחרונה מתקבל:
:<math>\ (g^{u_1} \cdot y^{u_2} \mbox{ mod }p)\mbox{ mod }q = (g^k \mbox{ mod }p) \mbox{ mod }q</math>. 
על כן <math>\ v=r</math>.

== דוגמה ==
הכנת מפתח חתימה: בוחרים את הראשוני <math>\ q=787</math> וכן <math>\ p=6 \cdot q+1=4723</math>, היוצר <math>\ g=3045</math>. ובוחרים מפתח פרטי למשל <math>\ x=211</math> ומחשבים את <math>\ y=3045^{211} \mbox{ mod }4723=4583</math>. המפתחות הפומביים יהיו: <math>\ \{4723,787,3045,4583\}</math> ואילו המפתח הפרטי יהיה: <math>\ 211</math>.

תהליך החתימה: בוחרים אלמנט אקראי, נניח <math>\ k=293</math>, מחשבים את <math>\ r=(3045^{293} \mbox{ mod }4723) \mbox{ mod }787=519</math> וכן מחשבים את ההופכי <math>\ k^{-1}=231 \ (\mbox{mod }787)</math>. אם המסר המיועד לחתימה הוא <math>\ m=344865</math>, אזי: <math>\ s=231 \cdot (344865+211 \cdot 519)\mbox{ mod }787 = 565</math>. החתימה על המסר היא אם כן <math>\ s=565, \ r=519</math>.

תהליך אימות החתימה: כדי לוודא כי החתימה על הערך <math>\ z=159</math> נכונה, המקבל משתמש במפתחות הפומביים תחילה כדי לחשב את: <math>\ w=565^{-1} = 748 \ (\mbox{mod }787)</math> ואז מחשב את: <math>\ u_1=748 \cdot 159 \mbox{ mod }787=95</math> וכן <math>\ u_2=519 \cdot 748 \mbox{ mod }787=221</math> ולבסוף: <math>\ v=(3045^{95} \cdot 4583^{221})\mbox{ mod }4723) \mbox{ mod }787 = 519</math> וכיוון ש- <math>\ r=v</math> החתימה מתקבלת.

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

==ECDSA==
תקן ANS X9.62 (הצפנת מפתח ציבורי למגזר העסקי) שפותח על ידי Accredited Standards Committee X9 עבור ANSI, מכיל תקן חתימה דיגיטלית מבוססת עקום אליפטי הנקראת ECDSA (קיצור של Elliptic Curve Digital Signature Algorithm) שהיא אנלוגית לחתימת DSA המתוארת. התקן מפרט פרמטרים בטוחים שיטות ותהליכים של חתימה ואימות לצורך חתימה דיגיטלית המשתמשת בעקום אליפטי וכן מנחה כיצד לבחור מפתחות (מפתח פרטי/מפתח ציבורי) בהתאם לסט פרמטרים מסוים שנקרא פרמטרי תחום של העקום האליפטי, שהם בדרך כלל אוסף של ערכים קבועים שיכולים להיות משותפים למספר גדול של משתמשים ומגובלים לתקופה מסוימת, בדרך כלל מספר שנים.

===הכנת פרמטרים===
לצורך החתימה הדיגיטלית, החותמת אליס צריכה להכין תחילה מספר פרמטרים קבועים של המערכת וכן מפתחות אימות וחתימה. תחילה אליס בוחרת שדה מסדר <math>q</math>, מתוכו היא בוחרת באופן אקראי שני מקדמים <math>a</math> ו-<math>b</math> המייצגים את העקום האליפטי <math>E:y^2=x^3+ax+b</math> במקרה שסדר השדה הוא <math>p=q</math> ראשוני, או <math>E:y^2+xy=x^3+ax^2+b</math> במקרה של שדה בינארי מורחב כאשר <math>q=2^m</math>. היא מחשבת את <math>N=\#E(\mathbb{F}_q)</math> מספר הנקודות בעקום האליפטי <math>E</math> ומוודא שהוא מתחלק במספר ראשוני <math>n</math> גדול <math>(n>2^{160})</math>. היא בוחרת את הקואורדינטות <math>(x_G,y_G)</math> ומגדירה את נקודת הבסיס <math>G</math> שהיא מסדר <math>n</math> ראשוני גדול ב-<math>E(\mathbb{F}_q)</math>. ולבסוף מחשבת את הגורם המשלים <math>h</math> כך שמתקיים <math>h=\#E(\mathbb{F}_q)/n</math>. לסיכום פרמטרי התחום הבסיסיים של ECDSA הם: <math>(q,a,b,G,n,h)</math>.

בנוסף אליס קובעת את הבסיס האריתמטי לצורך חישוב הפעולות בשדה. אם השדה מסדר ראשוני כאשר <math>q=p</math> הקואורדינטות הן שני שלמים חיוביים <math>(x,y)</math> וכל פעולות החיבור והכפל מבוצעות מודולו <math>n</math>. אם השדה הוא בינארי מורחב כאשר <math>q=2^m</math> הקואורדינטות הן פולינומים ממעלה <math>m</math> עם מקדמים בינאריים. התקן כולל שדה אופציונלי הנקרא <math>\text{seed}</math> שהוא מחרוזת סיביות אקראית הנקראת גרעין התחלתי והיא שימושית כאשר העקום נוצר באופן אקראי באמצעות מחולל פסאודו אקראי קריפטוגרפי, שאיתה ניתן יהיה לאמת לאחר מכן בבדיקה פשוטה שלא הוחדרה לפרמטרים של העקום האליפטי דלת אחורית במכוון.

אפשר להכין פרמטרי תחום לבד או להשתמש בסטים מומלצים של תקן X9.62 שהוכנו ונבדקו על ידי מומחים. אם מכינים את הפרמטרים באופן עצמאי רצוי להכין את הנקודה <math>G</math> באופן בטוח. ההמלצה היא להשתמש בפונקציית גיבוב קריפטוגרפית בטוחה לפי תקן SP 800-57 כך שניתן יהיה לוודא שאינה מכילה דלת אחורית. יש לשים לב שביטחון פונקציית הגיבוב לא יהיה נמוך מביטחון פרמטרי התחום הנקבע על ידי <math>n</math>. התקן כולל חמישה סטים מוכנים של עקומים אליפטיים לצורך חתימה דיגיטלית באורכים שונים של <math>n</math> החל מ-160 סיביות ועד 512 סיביות או יותר. השדה יכול להיות שדה ראשוני <math>F_q</math> כאשר <math>q</math> ראשוני או שדה בינארי מורחב <math>F_{2^m}</math> כאשר <math>m</math> הוא שלם חיובי גדול והוא מתחלק לשלושה סוגים:
*עקום אליפטי מעל שדה ראשוני המיוצג על ידי <math>\text{P-xxx}</math>.
*עקום אליפטי מעל שדה בינארי מורחב המיוצג על ידי <math>\text{B-xxx}</math>.
*עקום אליפטי מסוג קובליץ המיוצג על ידי <math>\text{K-xxx}</math>.
xxx מציין את מספר הסיביות של גודל השדה.

===הכנת מפתחות===
בנוסף לפרמטרים הקבועים של העקום האליפטי המשמש לחתימה אליס צריכה להכין מפתחות אימות וחתימה. המפתח הפרטי של אליס הוא שלם אקראי סודי <math>d</math> ואילו המפתח הציבורי הוא נקודה בעקום <math>Q</math>. להכנת המפתחות מוצעות שתי שיטות:
*תחילה מכינים מספר אקראי <math>c</math> באורך המומלץ על ידי התקן באמצעות מחולל פסאודו אקראי קריפטוגרפי ואז מחשבים את <math>d=(c\text{ mod }(n-1))+1</math> והמפתח הציבורי הוא <math>Q=d\times G</math>. כלומר מכפלה סקלרית של הנקודה <math>G</math> ב-<math>d</math>.
*לחלופין, בוחרים באותה דרך מספר אקראי <math>c</math> עד שמתקיים <math>c\le n-2</math> אם התנאי אינו מתקיים בוחרים מספר אחר. ואז המפתח הפרטי הוא <math>d=c+1</math> והמפתח הציבורי הוא <math>Q=d\times G</math>.

כמובן שיש לוודא את שלמות, תקינות ושייכות כל הפרמטרים המעורבים בתהליך החתימה. התקן מפרט שיטות לבדיקת תקפות ואמינות הערכים של פרמטרי התחום ומפתחות החתימה והאימות.

===חתימה ואימות===
כדי לחתום על המסר <math>m</math> החותמת אליס משתמשת בפרמטרי התחום <math>(q,a,b,G,n,h)</math> השייכים למפתח הפרטי והציבורי המתאימים שלה <math>(d,Q)</math> ומבצעת כדלהלן:
# בוחרת שלם אקראי <math>k</math> הנמוך מ-<math>n</math>. 
# מחשבת את הנקודה <math>kG</math> ונוטלת את הקואורדינטה ה-<math>x</math> שלה וממירה אותה למספר שלם <math>x_1</math>.
# מחשבת את <math>r=x_1\text{ mod }n</math>. אם <math>r=0</math> חוזרת להתחלה.
# מחשבת את <math>k^{-1}\text { mod }n</math>.
# מחשבת את ערך הגיבוב של המסר <math>e=\text{SHA-2}(m)</math> ומתייחסת ל-<math>e</math> כאל מספר שלם.
# מחשבת את <math>s=k^{-1}(e+dr)\text{ mod }n</math>. אם <math>s=0</math> חוזרת להתחלה.
# החתימה של אליס על <math>m</math> היא <math>(r,s)</math>.

כדי לאמת את החתימה <math>(r,s)</math> על המסמך <math>m</math> המוודא בוב משיג תחילה עותק אותנטי של המפתח הציבורי של אליס <math>Q</math> יחד עם פרמטרי התחום של העקום האליפטי ששימש לחתימה <math>(q,a,b,G,n,h)</math> ופועל כדלהלן:
# מוודא ש-<math>r</math> ו-<math>s</math> הם שלמים חיוביים בטווח <math>[1,n-1]</math> אם לא הוא דוחה את החתימה.
# מחשב את ערך הגיבוב של המסר <math>e=\text{SHA-2}(m)</math>.
# מחשב את <math>w=s^{-1}\text{ mod }n</math>.
# מחשב את <math>u_1=ew\text{ mod }n</math> וכן <math>u_2=rw\text{ mod }n</math>.
# מחשב את הנקודה <math>X=u_1G+u_2Q</math>. אם <math>X=\mathcal{O}</math> דוחה את החתימה.
# ממיר את הקואורדינטה <math>x</math> של הנקודה <math>X</math> למספר שלם <math>x_1</math>.
# מחשב את <math>v=x_1\text{ mod }n</math>.
# החתימה מתקבלת כאוטנתית רק אם <math>v=r</math>.

הוכחת נכונות: אם החתימה <math>(r,s)</math> על המסר <math>m</math> נוצרה על ידי אליס אז <math>s=k^{-1}(e+dr)\text{ mod }n</math>, לאחר סידור מחדש מתקבל:
:<math>k\equiv s^{-1}(e+dr)\equiv s^{-1}e+s^{-1}rd\equiv we+wrd\equiv u_1+u_2d\text{ (mod }n)</math>,
לכן <math>u_1G+u_2Q=(u_1+u_2d)G=kG</math> ומזה נובע <math>v=r</math> כנדרש.

===ערך חד פעמי===
יש לייצר מספר חד-פעמי <math>k</math> שונה עבור כל מסמך שאליס מעוניינת לחתום עליו אחרת ניתן יהיה לחשוף את מפתח החתימה הפרטי שלה בגלל העובדה ש-
:<math>d=r^{-1}(ks-e)\text{ mod }n</math> 
וכל הערכים באגף הימני של המשוואה ידועים למעט <math>k</math>. לכן יש צורך ש-<math>k</math> יהיה חד פעמי ובלתי צפוי. אם אליס תחתום על שני מסמכים שונים עם אותו <math> k</math> אפשר יהיה לבצע התקפה נגד החתימה ולחשוף את המפתח הפרטי של אליס כדלהלן: נניח שהחתימות של אליס הן <math>(r,s_1)</math> ו-<math>(r,s_2)</math> עבור המסרים <math>m_1</math> ו-<math>m_2</math> בהתאמה. אז 
:<math>s_1\equiv k^{-1}(e_1+dr)</math> וכן 
:<math>s_2\equiv k^{-1}(e_2+dr)</math> 
כאשר <math>e_1</math> ו-<math>e_2</math> הם תמציות הגיבוב של המסמכים <math>m_1</math> ו-<math>m_2</math> בהתאמה. מזה נובע
:<math>ks_1\equiv e_1+dr</math> וכן
:<math>ks_2\equiv e_2+dr</math> 
אם מחסרים <math>k(s_1-s_2)\equiv e_1-e_2</math> ואם <math>s_1\ne s_2</math> מה שאמור לקרות בהסתברות גבוהה אז מתקבל
:<math>k\equiv (s_1-s_2)^{-1}(e_1-e_2)</math>. 
בכך היריב הצליח לחלץ את <math>k</math> ואיתו הוא יכול לחשב את המפתח הפרטי של אליס. (כל החישובים כאמור הם מודולו <math>n</math>).

הטעות הזו למעשה ארעה במציאות בתהליך החתימה הדיגיטלית של קונסולת המשחקים פלייסטיישן 3. בנוסף יש להיזהר ממחולל פסאודו אקראי לא בטוח.
ב-2013 התגלתה פרצה חמורה במחולל המספרים האקראיים באנדרואיד שנעשה בו שימוש לצורך חתימת ECDSA במספר ארנקי ביטקוין.


== אלגוריתם גיבוב ==
כחלק ממנגנון חתימה דיגיטלית יש צורך באלגוריתם גיבוב בטוח על המסר לפני תהליך החתימה ואת החתימה לבצע על תוצאת האלגוריתם ולא על המסר ישירות. האלגוריתם מקבל את המסר m המיועד לחתימה ומפיק עבורו ערך ייחודי (H(m בגודל קבוע כאשר H(m) < m. הסיבות לכך הן, האחת עניין של יעילות, חתימה על מסר גדול באורך לא מוגדר, מסורבלת וקשה יותר מחתימה על ערך בגודל קבוע (קטן). שנית, עניין של בטיחות, חתימה על המסר עצמו ישירות, יוצרת פרצה בטיחותית מסוימת. בחתימה דיגיטלית, לא די בכך שהערך יהיה ייחודי אלא שאלגוריתם הגיבוב יהיה בטוח, כדי להקטין כמעט לאפס את הסיכויים לכך שיימצא מסר אחר שעבורו האלגוריתם מפיק ערך זהה. לפי תקן DSA המקורי FIPS 186-1, אלגוריתם גיבוב בטוח SHA-1 מספק. לאחרונה התגלו טכניקות חדשות המטילות בספק את בטיחותו של SHA-1. למעשה תקן FIPS 186 העדכני מגדיר דרישה לפונקציית גיבוב בטוחה לפי תקן SHS, פונקציית הגיבוב SHA-2.

== ראו גם ==
* חתימה דיגיטלית
* אל-גמאל (חתימה דיגיטלית)

== קישורים חיצוניים ==
* [http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf אתר NIST, תקן FIPS 186-4]
* [https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html פוסט על התקלה במחולל המספרים האקראיים באנדרואיד]

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

קטגוריה:מפתח ציבורי
קטגוריה:חתימה דיגיטלית