חתימה ואימות של בקשות
חתימת הבקשה מוכיחה את אמיתותו של השולח ואת שלמות התוכן. בניגוד ל-TLS (שמגן על הערוץ), חתימה יישומית הופכת כל הודעה לאומתת ועמידה בפני פרוקסי, מטמון ומשלוח מושהה.
מטרות:1. אותנטיות (מי שלח) ויושרה (לא השתנה).
2. ייחודיות (הגנה מפני שידור חוזר).
3. Decoupling from transport (עבודות על גבי HTTP, תורים, חוברות אינטרנט).
4. שמיעה (בדיקת רבייה לאחר חודשים).
1) מודל איום (מינימום)
החלפת גוף/כותרת לאורך המסלול.
שידור חוזר (חוזר על בקשה לגיטימית).
כותרת הורד/רצועה.
גניבת סודות אינטגרציה.
שעון לא סינכרוני ותורים ארוכים.
2) בחירה של פרימיטיבי
(HMAC (סימטריה: פשוט ומהיר, המפתח מאוחסן בשני הצדדים. מתאים לספרי אינטרנט של בי-2-בי ולרשומות פנימיות.
RSA/ECDSA (אסימטריה): מפתח פרטי מהשולח, מפתח ציבורי מהמקבל. מתאים לשילוב פתוח וכשזה חשוב לא לחלוק סוד.
MTLS: שיגור אימות הדדי שכבתי בשילוב עם NMAC/חתימת גוף.
JWT/JWS: נוח לאסימונים נושאי ובולים עצמיים; כדי לחתום על הגופה, עדיף להשתמש בחתימות מסרים מנותקות/HTTP.
חתימות הודעות HTTP (חתימת חלקים נבחרים של הבקשה): גישה מודרנית למנוחה.
המלצה: עבור חוברות אינטרנט - HMAC + חותמת זמן + nunce + canonicalization; עבור API ציבורי - HTTP מסרים חתימות או JWS; בסיכונים גבוהים - להוסיף mTLS.
3) קנוניקליזציה (מה בדיוק אנחנו חותמים)
אתה צריך לחתום על מחרוזת דטרמיניסטית שניתן לשחזר באותה מידה על ידי שני הצדדים.
הרכב התייחסות:
method \n path_with_query_normalized \n content-type \n digest: SHA-256=BASE64(SHA256(body)) \n x-ts: <unix iso> \n x-nonce: <uuid> \n host \n x-tenant: <tenant_id> \n
שורה כוללת:
canonical = join("\n", fields)
signature = HMAC(secret, canonical) # или ECDSA_sign(private_key, canonical)
כללים:
- לנרמל את הנתיב והסדר של פרמטרים שאילתה.
- רווחים/יוניקוד/מקרה - תיקון (לדוגמה, כותרות במקרה התחתון, קיצוץ).
- גופים גדולים - חשיש (Digest), לא להפעיל ”כמו שהוא”.
4) תבנית כותרת
דוגמה ל ־ HMAC:
X-Signature-Alg: hmac-sha256
X-Signature: v1=hex(hmac),ts=1730379005,nonce=550e8400-e29b-41d4-a716-446655440000,kid=prov_42
Digest: SHA-256=BASE64(SHA256(body))
X-Tenant: brand_eu
דוגמה לאסימטריה (ECDSA P-256):
Signature: keyId="prov_42", alg="ecdsa-p256-sha256",
ts="2025-10-31T12:30:05Z", nonce="550e...", headers="(request-target) host digest x-tenant",
sig="BASE64(raw_signature)"
היכן ש "ילד "/" KeyId' מאפשר לך לבחור מפתח מהמרשם (ראה סיבוב).
5) אימות בקצה המקבל
פסאודו-קוד:python def verify(request):
1) Basic assert abs (now () - request. ts) <= ALLOWED_SKEW # напр., 300 с assert not replayed(request. nonce, window = TTL) # store nonce/ts in KV
2) Restore canonical canonical = build_canonical (
method=request. method,
path=normalize_path(request. path, request. query),
content_type=request. headers["content-type"],
digest=hash_body(request. body),
ts=request. ts,
nonce=request. nonce,
host=request. headers["host"],
tenant=request. headers. get("x-tenant")
)
3) Get the key key = key_registry. get(request. kid) # secret (HMAC) или public key (ECDSA)
4) Verify if request signature. alg. startswith("hmac"):
ok = hmac_compare(key. secret, canonical, request. signature)
else:
ok = asym_verify(key. public, canonical, request. signature)
5) Solution if not ok: return 401, "SIGNATURE_INVALID"
return 200, "OK"
השוואת HMAC בזמן קבוע, אחסון 'nunce '/' ts, event_id' בחלון מסירה מהיר של KV (TTL).
6) אנטי-שידור חוזר וחלונות
Timestamp + Nonce: לדחות בקשות עתיקות יותר מ ־ ”Nethel” (למשל. 5 דקות) ושיחזור נונס בחלון זה.
עבור חוברות אינטרנט: השתמש באורווה "event _ id' ובטבלת תיבת הדואר הנכנס - זה אמין יותר מסתם נונסה.
משלוח מחדש (retrays) צריך להשתמש באותו ts/nonce/event_id, לא ליצור חדשים.
7) רב-דיירים ואזורים
'ילד = <דייר>: <אזור>: <key _ id>'.
בריכות סודיות נפרדות ומגבלות; התבונן התמחות בנתונים.
בכותרות/קנוניקליזציה, מצביע 'X-Tenant' והאזור הוא חלק מההקשר שנבדק.
8) ניהול מפתחות וסבב
רישום מפתחות (KMS/Vault): 'ילד', סוג, אלגוריתם, סטטוס ('active', 'depreacting', 'fression'), 'תקף _ from/תקף _ to'.
סודות כפולים: החזיקו את המפתח הנוכחי ואת המפתח הבא בו זמנית (המקבל מקבל את שניהם).
סיבוב לפי לוח זמנים ובאירוע (פשרה).
הצמדת מפתחות (במידת האפשר) והגבלת הגישה לחומרי מפתח.
יומנים של גישה למפתחות ופעולות איתם.
9) שילוב עם mTLS ו ־ OAuth
MTLS בודק את הערוץ ו ”מי אתה” ברמת התעודה.
החתימה מגינה על המסר (שימושי באמצעות פרוקסי/מטמונים/תורים).
OAuth/JWT משלים אימות/אישור, אך כשלעצמו אינו מבטיח את שלמות הגוף (אלא אם כן הוא חתום בקנוניקליזציה).
המנהגים הטובים ביותר: חתימת גוף (Digest) + HMAC/ECDSA + קיצור 't' - interval.
10) שגיאות וקודי תגובה
'401 SIGNATURE_INVALID' הוא חתימה/אלגוריתם לא תקף.
'401 KEY_REVOKED' -' ילד לא בתוקף/פג תוקף.
ארבע מאות TIMESTAMP_OUT_OF_RANGE' - שעון/חלון.
'409 NONCE_REPLAYED' - רדו זוהה.
ארבע מאות DIGEST_MISMATCH'. הגוף השתנה.
'415 UNSUPPORTED_ALGORITHM' הוא' אלג לא פתור.
429 TOO_MANY_ATTEMPTS' - מפתח/דייר חונק.
בעיטת הסיבה המדויקת במכונה הקריאה ”שגיאה _ קוד”; לא להחזיר סודות/קנוניקליזציה ”כמו שהוא”.
11) יכולת תצפית וביקורת
מדדים:- 'veriate _ p95 _ ms',' valiate _ image _ rate ',' digest _ mismatch _ rate ',' relay _ block _ rate ',' alg _ usage _ hmac, ecdsa ',' clock _ skew _ ms'.
- יומנים (מבניים): "ילד", "אלג", "דייר", "אזור", "ts'," nunce "," digest _ hash "," החלטה "," סיבה ".
- איתור: חתימה של תכונות. ילד, 'חתימה. אלג ', חתימה. ts_skew'.
- ביקורת: יומן בלתי ניתן לשינוי של סיבוב, שימוש מפתח ודגלי סובלנות.
12) ביצועים
חשיש הגוף על ידי זרימה (לא לשמור אותו בזיכרון שלך).
מטמון מפתחות ציבוריים על ידי 'ילד' עם TTL קצר ונכות על ידי אירוע.
על קצה/שער, לבצע בדיקות ראשוניות (ts/nonce/format).
HMAC מהר יותר מאשר ECDSA; ECDSA נוח יותר לשילוב חיצוני ומפתחות ”לא משותפים”.
13) בדיקה
הגדרות קבעון: אותן בקשות * canonicalization/חתימה זהה; מרחבים מלוכלכים/סדר שאילתות/כותרות הם יציבים.
שלילי: ”ילד/אלג” לא תקף, גוף/מארח מותאם, לא חוזר, ts מיושן, רזה שעון.
מבוסס מאפיין: כל שאילתות שקולות מייצרות מחרוזת קנונית אחת.
Interop: cross-language checks (Go/Java/Node/Python).
תוהו ובוהו: עיכובים, נסיגות, שינויים במפתח.
14) ספרי משחק (ספרי הפעלה)
1. חתימה _ INFALID 'Spike
בדוק סיבוב מפתח, היערכות שגויה של השעון, שינויים בקאנוניקליזציה בשולח.
תאפשר באופן זמני ”שתי קבלת פנים” לילד זקן, תודיע לשותף.
2. ”גדילה חוזרת”
הגדל את ה ־ TTL של אחסון הנונס, בדוק את המאמנים בשולח, בדוק את מחסור השעון.
לעקוף IP/ASN פוגעני על קצה.
3. ”Digest _ Mismatch” באופן מאסיבי
בדוק פרוקסי/דחיסה/שכתוב כותרות; לתקן את גרסת הקנוניקליזציה.
לנטרל פורצי גוף/כותרת.
4. פשרת מפתח
מיד לבטל ”ילד”, לתרגם ל ”הילד הבא”, לחדש את כל הסודות/אסימונים, גישה לביקורת.
15) שגיאות אופייניות
חתימה על ”איבר גוף” או JSON מבלי לתקן את הפגיעות לפרמוטציה של השדה.
היעדרו של A 'Digest' # יכול לשנות את הגוף מבלי שיבחינו בו.
חלון זמן 'tt ללא nunce הוא פתוח להילוך חוזר.
שמור סודות במשתני סביבה ללא KMS/Vault.
השווה חתימה לא קבועה בזמן.
התעלם מ ”מארח ”/” נתיב” בהתקפה קדמית.
לערבב 'ילד' דיירים שונים ואזורים.
16) רשימת בדיקות לפני המכירה
[ ] פורמט קנוניקליזציה מוגדר (שיטה, נתיב + שאילתה, תוכן-סוג, Digest, ts, nonce, מארח, דייר).
[ ] ממומש HMAC/ECDSA עם 'ילד', רישום מפתח וסוד כפול.
[ ] כללו שידור חוזר (nunce + ts) ואחסון inbox/event_id לחוברות אינטרנט.
[ ] הגדרת קודי שגיאה/מדיניות מגש מחדש וחניקה לכל דייר/מפתח.
[ ] תצפית: לאמת מדדים, יומנים, עקבות, התראות להתפרצויות.
[ סיבוב מפתח ] הוא אוטומטי; ביקורת וזכויות גישה מוגבלות.
[ ] Canonicalization ו-interlanguage integability test test.
[ ] תיעוד לאינטגרטורים עם דוגמה ב-3-4 שפות ותיקונים.
[ ] MTLS אפשרה אינטגרציה רגישה; JWT משמש רק כתוספת, לא תחליף לחתימה של הגוף.
סיכום
חתימה ואימות בקשות אינה ”כותרת אחת”, אלא משמעת: קנוניקליזציה ברורה, חלונות קצרים של זמן, אנטי-חזרה, סיבוב מפתח, ויכולת תצפית. לבנות סטנדרט יחיד לכל האינטגרציות (API ו-webhooks), להשתמש ב ”ילד ”/KMS, לקבל שני מפתחות במהלך סיבוב, והקווים שלך יהפכו עמידים לזיוף, צפוי וקל לביקורת.