💡 דוגמה מלאה עובדת זמינה ב‑GitHub:
sign-word-with-ml-dsa-certificates-dotnet

הדרך הישנה הייתה תכנית פרויקט

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

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

חתימת ML‑DSA היא יכולת של GroupDocs.Signature עבור .NET החותמת על מסמכי Word עם תעודות המבוססות על FIPS 204, תקן החתימה הפוסט‑קוואנטית של NIST. היא הגיעה ב‑26.9, ומנקודת המבט של הקוד המתקשר היא קובץ PFX שונה.

יש דרך טובה יותר

הנה כל שינוי הקוד:

using var signature = new Signature(sourcePath);

var options = new DigitalSignOptions(pfxPath)
{
    Password = certificatePassword
};

SignResult result = signature.Sign(outputPath, options);

זהו אותו קריאה המשמשת לתעודת RSA. האלגוריתם הוא תכונה של התעודה, ולכן אין אפשרות לבחירתו, אין צורך בשכבת הפשטה, ואין נתיב קוד שני שמופיע לתקופת המעבר. הפנו את DigitalSignOptions ל‑PFX של ML‑DSA והתוצאה היא חתימה של ML‑DSA.

קריאת התעודה חזרה מהתוצאה שווה לעשות כאשר כמה תעודות נמצאות בתהליך:

var created = result.Succeeded.OfType<DigitalSignature>().FirstOrDefault();
return created?.Certificate?.Subject ?? "(no certificate returned)";

בחירת רמה, עם מספרים במקום דעות

ML‑DSA מגיעה בשלושה סטים של פרמטרים, הממופים לקטגוריות האבטחה של NIST 2, 3 ו‑5. חזק יותר משמעותו גדול יותר – הן המפתח והן החתימה – והדרך ההגיונית להחליט היא לחתום על המסמך שלכם שלוש פעמים ולצפות:

var levels = new Dictionary<string, string>
{
    ["ML-DSA-44"] = MlDsa44Pfx,
    ["ML-DSA-65"] = MlDsa65Pfx,
    ["ML-DSA-87"] = MlDsa87Pfx
};

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

ML‑DSA‑65 היא ברירת המחדל ההגיונית כאשר אין מדיניות שמכתיבה אחרת. פרופילים כמו CNSA 2.0 מציינים במפורש את ML‑DSA‑87, ו‑ML‑DSA‑44 הגיונית רק כאשר הגודל חשוב יותר מהשוליים.

האימות דורש רק את התעודה הציבורית

סיפור ההפצה אינו משתנה מ‑RSA, וזהו החלק השני של החדשות הטובות:

var options = new DigitalVerifyOptions(certificatePath);
if (password != null)
{
    options.Password = password;
}

VerificationResult result = signature.Verify(options);

המקבל צריך רק את קובץ .cer של החותם ולא דבר נוסף. התוצאה תקפה רק כאשר החתימה תואמת לתוכן והתעודה תואמת לפי מספר סידורי וטביעת אצבע, ולכן מסמך חתום על ידי גורם אחר ייכשל בבדיקה – כפי שהדוגמה מוכיחה על‑ידי הרצת האימות פעמיים, פעם עם התעודה הנכונה ופעם עם תעודה של מישהו אחר.

זה לצד זה: צפוי מול בפועל

מה שמניח תכנית ההגירה מה ש‑26.9 דורש בפועל
שינוי קוד שכבת הפשטה מעל החתימה נתיב PFX שונה
משטח API שיטות פוסט‑קוואנטיות חדשות DigitalSignOptions, ללא שינוי
בחירת רמה קונפיגורציית ספרייה איזו תעודה נטענת
אימות כלי חדש למקבלים קובץ .cer הציבורי של החותם
עבודה בפלטפורמה טיפול במפתחות לפי מערכת הפעלה אין – הספרייה מתמודדת פנימית
כיסוי פורמטים כל הפורמטים פורמטים של Word בלבד, לעת עתה

השורה האחרונה היא זו שמגבילה תכנון, והיא מובילה לחלק הכנה של מאמר זה.

מה עדיין לא עובד

שתי מגבלות, ששווה לדעת לפני שמבטיחים משהו.

כיסוי הפורמטים הוא Word בלבד ב‑26.9 – DOCX, DOC, ODT ושאר משפחת Word. PDF, גיליונות אלקטרוניים והצגות אינם ניתנים לחתימה עם ML‑DSA. עבור צינור עבודה שמתחיל ב‑PDF, שחרור זה מיועד לניסויים ולמדידה ולא למעבר מלא.

תמיכת המאמתים היא המגבלה השנייה. עדיין אין מזהה XML‑DSig סטנדרטי ל‑ML‑DSA, ולכן Microsoft Word עשוי לא לדווח על החתימה כתקפה למרות שהיא קריפטוגרפית נכונה ונבדקת כראוי דרך ה‑API. זה פער תקני ולא תקלה, ומשמעותו שהאימות צריך להתבצע בקוד שלכם ולא בבדיקה של קובץ על‑ידי סוקר.

קיימת גם פרט פלטפורמה שלא דורש פעולה: .NET אינו יכול לקרוא מפתחות ML‑DSA בכל מקום, כולל Linux על .NET 8. במקומות שבהם הוא אינו יכול, GroupDocs.Signature קוראת את התעודה דרך מנוע Word, ולכן אותה בנייה פועלת על מחשב מפתח ובמכולת Linux ללא קוד מותנה.

האם זה שווה לעשות עכשיו, לאור המגבלות?

כן, משתי סיבות שאין להן קשר לקוד. רכישת תעודות היא תהליך איטי – רשות תעודות ציבוריות עדיין משיקה הנפקת ML‑DSA – ולכן העבודה מהצד הארגוני מרוויחה מהתחלה מוקדמת. ו‑„האם נוכל לייצר חתימה פוסט‑קוואנטית היום?“ היא שאלה שמחלקות הציות מתחילות לשאול; היכולת לענות עם מסמך חתום ולא עם תכנית היא שווה את זמן אחר הצהריים שנדרש.

מה הדוגמה באמת מוכיחה

ארבע שיטות, רצות בסדר, עם קוד יציאה הקשור לתוצאה. היא חותמת את החוזה עם ML‑DSA‑65 ומדפיסה את
ה‑subject של התעודה שהשתמשו בה. היא חותמת את אותו חוזה בשלוש הרמות ומדפיסה את הגדלים המתקבלים. היא
מאמתת את הקובץ החתום פעמיים – פעם עם תעודת הציבור של החותם, מצפה להצלחה, ופעם עם תעודה של חותם אחר, מצפה לכישלון. לאחר מכן היא מציגה את החתימות הדיגיטליות שנמצאו בפלט.

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

דוגמה מהעולם האמיתי: חוזה של שלושים שנה

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

עבור ארכיון כזה, הצעד המעשי היום הוא מסלול כפול: לשמור על RSA עבור הפורמטים ש‑ML‑DSA עדיין לא מכסה, להתחיל לחתום פלט של Word עם ML‑DSA‑65 או 87, ולתעד איזו אלגוריתם השתמשו בו לכל מסמך כך שבדיקה עתידית תוכל להבדיל ביניהם ללא פתיחת הקבצים.

דבר אחד לתקן בדוגמה לפני שמעתיקים אותה

המאגרים כוללים תעודות ML‑DSA חותמות עצמאיות כך שההדגמה פועלת מיד, מה שאומר שיש ארבעה קבצי PFX ו‑
סיסמה קבועה ב‑documents/. עבור תעודת בדיקה חד‑פעמית תקפה רק בתוך הדוגמה, זה מקובל.

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

סיכום

החלקים היקרים במעבר פוסט‑קוואנטי הם תעודות, מדיניות ומאמתים. הקוד, לפחות עבור מסמכי Word ב‑.NET, הוא PFX שונה והקריאה ל‑DigitalSignOptions זהה. שיבטו את הדוגמה, הפנו אותה לאחד מהחוזים שלכם, ותקבלו שלושה קבצים חתומים, שני תוצאות אימות והשוואת גדלים בתוך כמה דקות – וזה בסיס טוב יותר לתכנית מעבר מאשר הערכה.

משאבים נוספים