הדף הזה רלוונטי ל-Apigee ול-Apigee Hybrid.
לעיון במסמכי התיעוד של
Apigee Edge
מדיניות HMAC מחשבת קוד אימות הודעות (HMAC) מבוסס-גיבוב (hash) ומאמתת אותו (אופציונלית). לפעמים נקרא HMAC גם קוד אימות הודעה עם מפתח או גיבוב עם מפתח. הוא משתמש בפונקציית גיבוב קריפטוגרפית כמו SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 או MD-5, שמוחלת על 'הודעה', יחד עם מפתח סודי, כדי ליצור חתימה או קוד אימות הודעה על ההודעה הזו. המונח 'הודעה' כאן מתייחס לכל זרם של בייטים. בשימוש רגיל ב-HMAC, שולח ההודעה שולח הודעה ואת ה-HMAC שלה לנמען, והנמען יכול להשתמש ב-HMAC יחד עם מפתח הסוד המשותף כדי לאמת את ההודעה.
המדיניות הזו היא מדיניות רגילה ואפשר לפרוס אותה בכל סוג של סביבה. מידע על סוגי המדיניות והזמינות שלהם בכל סוג סביבה זמין במאמר סוגי מדיניות.
מידע נוסף על HMAC זמין במאמר HMAC: Keyed-Hashing for Message Authentication (rfc2104).
דוגמאות
יצירת HMAC
<HMAC name='HMAC-1'> <Algorithm>SHA256</Algorithm> <!-- the default encoding of the SecretKey is UTF-8 --> <SecretKey encoding='base64' ref='private.secretkey'/> <IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables> <!-- optional --> <!-- The Message element accepts a template, which means the "message" the policy operates on can include fixed and multiple variable parts, including newlines and static functions. Whitespace, such as newlines and space characters, is significant. --> <Message>Fixed Part {a_variable} {timeFormatUTCMs(timeFormatString1,system.timestamp)} {nonce}</Message> <!-- default encoding is base64 --> <Output encoding='base16'>name_of_variable</Output> </HMAC>
אימות HMAC
<HMAC name='HMAC-1'> <Algorithm>SHA256</Algorithm> <!-- the default encoding of the SecretKey is UTF-8 --> <SecretKey encoding='base16' ref='private.secretkey'/> <IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables> <!-- optional --> <!-- The Message element accepts a template. This policy verifies an HMAC on the request content. --> <Message>{request.content}</Message> <!-- VerificationValue is optional. Include it to perform an HMAC check. --> <VerificationValue encoding='base16' ref='expected_hmac_value'/> <!-- default encoding of the output is base64 --> <Output encoding='base16'>name_of_variable</Output> </HMAC>
חישוב החתימה ואימות החתימה מתבצעים בדיוק באותו תהליך. מדיניות ה-HMAC מחשבת HMAC, ויכולה לאמת את החתימה המחושבת מול ערך צפוי. האלמנט האופציונלי VerificationValue
(אם הוא קיים) מכוון את המדיניות לבדוק את הערך המחושב מול ערך ידוע או נתון.
הפניה לרכיב של HMAC
בהפניה למדיניות מפורטים האלמנטים והמאפיינים של מדיניות HMAC.
מאפיינים שחלים על הרכיב ברמה העליונה
<HMAC name="HMAC" continueOnError="false" enabled="true" async="false">
המאפיינים הבאים משותפים לכל רכיבי ההורה של המדיניות.
| מאפיין | תיאור | ברירת מחדל | נוכחות |
|---|---|---|---|
| name |
השם הפנימי של המדיניות. התווים שאפשר להשתמש בהם בשם מוגבלים ל:
A-Z0-9._\-$ %. עם זאת, בממשק המשתמש של Apigee יש הגבלות נוספות, כמו הסרה אוטומטית של תווים שהם לא אלפאנומריים.
אופציונלי. אפשר להשתמש ברכיב |
לא רלוונטי | חובה |
| continueOnError |
מגדירים את הערך false כדי להחזיר שגיאה אם המדיניות נכשלת. זו התנהגות צפויה ברוב המדיניות.
הגדרה ל- |
FALSE | אופציונלי |
| מופעל |
מגדירים את המדיניות למצב true כדי לאכוף אותה.
מגדירים את הערך |
TRUE | אופציונלי |
| אסינכרוני | המאפיין הזה הוצא משימוש. | FALSE | הוצא משימוש |
<Algorithm>
<Algorithm>algorithm-name</Algorithm>
מציין את אלגוריתם הגיבוב שבו יש להשתמש כשמחשבים את ה-HMAC.
| ברירת מחדל | לא רלוונטי |
| נוכחות | חובה |
| סוג | String |
| ערכים אפשריים | SHA-1, SHA-224, SHA-256, SHA-384,
SHA-512 וגם MD-5
הגדרת המדיניות מקבלת שמות של אלגוריתמים בלי להבחין בין אותיות רישיות לאותיות קטנות, ועם או בלי מקף בין האותיות והמספרים. לדוגמה,
|
<DisplayName>
<DisplayName>Policy Display Name</DisplayName>
משתמשים בו בנוסף למאפיין name כדי לתת למדיניות תווית בכלי לעריכת proxy בממשק המשתמש של Apigee, עם שם אחר בשפה טבעית.
| ברירת מחדל | אם לא מציינים את הרכיב הזה, המערכת משתמשת בערך של מאפיין השם של המדיניות. |
| נוכחות | אופציונלי |
| סוג | String |
<Message>
<Message>message_template_here</Message> or <Message ref='variable_here'/>
מציין את מטען ההודעה לחתימה. הקלט של הרכיב הזה תומך בתבניות של הודעות (החלפת משתנים) כדי לאפשר הכללה של פריטים נוספים בזמן הריצה, כמו חותמות זמן, מספרים חד-פעמיים, רשימות של כותרות או מידע אחר. לדוגמה:
<Message>Fixed Part {a_variable} {timeFormatUTCMs(timeFormatString1,system.timestamp)} {nonce} </Message>
תבנית ההודעה יכולה לכלול חלקים קבועים ומשתנים, כולל שורות חדשות ופונקציות סטטיות. לרווחים, כמו שורות חדשות ותווי רווח, יש משמעות.
| ברירת מחדל | לא רלוונטי |
| נוכחות | חובה |
| סוג | String |
| ערכים אפשריים | כל מחרוזת היא ערך טקסט תקין. אם תספקו מאפיין ref, הוא יקבל עדיפות על פני ערך הטקסט. המדיניות בודקת את ערך הטקסט או את המשתנה שאליו יש הפניה כתבנית של הודעה. |
<Output>
<Output encoding='encoding_name'>variable_name</Output>
מציין את שם המשתנה שהמדיניות צריכה להגדיר עם ערך ה-HMAC המחושב. הוא גם מציין את הקידוד שבו יש להשתמש בפלט.
| ברירת מחדל |
משתנה הפלט שמוגדר כברירת מחדל הוא ערך ברירת המחדל של מאפיין |
| נוכחות | זה שינוי אופציונלי. אם הרכיב הזה לא קיים, המדיניות מגדירה את משתנה הזרימה hmac.POLICYNAME.output עם ערך בקידוד Base64. |
| סוג | String |
| ערכים אפשריים | לקידוד, הערכים לא תלויי-רישיות. למשל, ערך הטקסט של רכיב |
<SecretKey>
<SecretKey encoding='encoding_name' ref='private.secretkey'/>
קובעת את המפתח הסודי שמשמש לחישוב ה-HMAC. המפתח מתקבל מהמשתנה שאליו מתבצעת ההפניה, והוא מפוענח בהתאם לקידוד הספציפי.
| ברירת מחדל |
אין ערך ברירת מחדל למשתנה שאליו יש הפניה;
המאפיין אם לא מצוין מאפיין |
| נוכחות | חובה |
| סוג | String |
| ערכים אפשריים | במאפיין שימוש במאפיין קידוד מאפשר לציין מפתח שכולל בייטים מחוץ לטווח של תווים שניתנים להדפסה ב-UTF-8. לדוגמה, נניח שהגדרת המדיניות כוללת את הדברים הבאים: <SecretKey encoding='hex' ref='private.encodedsecretkey'/>
נניח שהמשתנה
במקרה הזה, הבייטים המרכזיים יפוענחו כך: [53 65 63 72 65 74 31 32 33]
(כל בייט מיוצג בפורמט הקסדצימלי). דוגמה נוספת: אם משתמשים ב- |
<VerificationValue>
<VerificationValue encoding='encoding_name' ref='variable_name'/> or <VerificationValue encoding='encoding_name'>string_value</VerificationValue>
(אופציונלי) מציין את ערך האימות, וגם את הקידוד ששימש לקידוד ערך האימות. המדיניות תשתמש בקידוד הזה כדי לפענח את הערך.
| ברירת מחדל | אין ערך אימות שמוגדר כברירת מחדל. אם הרכיב קיים אבל המאפיין encoding לא מופיע, המדיניות משתמשת בקידוד ברירת מחדל של base64 |
| נוכחות | אופציונלי |
| סוג | String |
| ערכים אפשריים |
הערכים התקפים של מאפיין הקידוד הם: הקידוד של |
<IgnoreUnresolvedVariables>
<IgnoreUnresolvedVariables>true|false</IgnoreUnresolvedVariables>
מגדירים את הערך false אם רוצים שהמדיניות תקפיץ הודעת שגיאה כשלא ניתן לפתור משתנה כלשהו שמוגדר במדיניות. הגדרה ל-true תגרום להתייחסות לכל משתנה שלא ניתן לפתור כמחרוזת ריקה (null).
הערך הבוליאני IgnoreUnresolvedVariables משפיע רק על משתנים שההפניה אליהם מופיעה בתבנית ההודעה. אפשר להפנות למשתנה גם ב-SecretKey וגם ב-VerificationValue, אבל צריך להיות אפשר לפתור את שניהם, ולכן ההגדרה ignore לא חלה עליהם.
| ברירת מחדל | לא נכון |
| נוכחות | אופציונלי |
| סוג | בוליאני |
| ערכים אפשריים | נכון או לא נכון |
משתני Flow
המדיניות יכולה להגדיר את המשתנים האלה במהלך ההפעלה.
| משתנה | תיאור | דוגמה |
|---|---|---|
hmac.policy_name.message |
המדיניות מגדירה את המשתנה הזה עם ההודעה האפקטיבית, שהיא התוצאה של הערכת תבנית ההודעה שצוינה ברכיב Message. |
hmac.HMAC-Policy.message = "Hello, World" |
hmac.policy_name.output |
מקבל את התוצאה של חישוב ה-HMAC, כשאלמנט Output לא מציין שם משתנה. |
hmac.HMAC-Policy.output = /yyRjydfP+fBHTwXFgc5AZhLAg2kwCri+e35girrGw4= |
hmac.policy_name.outputencoding |
מקבל את השם של קידוד הפלט. | hmac.HMAC-Policy.outputencoding = base64 |
בעיות נפוצות
ברמה מסוימת, מדיניות ה-HMAC נראית פשוטה: מספקים מפתח והודעה, ומקבלים בתגובה HMAC מחושב. יכול להיות שזה יתסכל אתכם אם תקבלו ערך HMAC לא צפוי לשילוב ידוע של הודעה ומפתח. בסעיף הזה נסביר כמה הערות שימוש שיעזרו לכם לפתור בעיות כאלה.
יש שתי בעיות נפוצות שגורמות לאי התאמה של HMAC במהלך האימות:
הבדלים ברווחים הלבנים בהודעה והבדלים בקידוד ובפענוח.
האחרון חל גם על הרכיב SecretKey וגם על הרכיב Output.
הבדלים ברווחים הלבנים
הבדלים שאולי נראים לא חשובים לאדם, משפיעים על ערך ה-HMAC של הפלט. לדוגמה,
נניח שיש מפתח סודי שאפשר לייצג אותו כ-Secret123. אחרי פענוח בקידוד UTF-8, הבייטים של המפתח יהיו: [53 65 63 72 65 74 31 32 33]. השימוש במפתח הזה כדי לחשב HMAC-SHA256 בהודעה abc מניב את התוצאה a7938720fe5749d31076e6961360364c0cd271443f1b580779932c244293bc94.
הוספת רווח בודד להודעה, כך שהיא תהיה abc<SPACE>, כאשר
<SPACE> מייצג ASCII 32, תגרום ל-HMAC-SHA256 של 274669b2a85d2532da48e2ce3d8e52ee17346d1bcd1a606d87db1934b5ab294b.
באופן דומה, אם ההודעה היא abc<NEWLINE>, כאשר
<NEWLINE> מרמז ASCII 10,
ה-HMAC הוא 0780370844ca07f896066837e8230d3b6a775f678a4ae03e6b5e864c674831f5.
שינויים קלים בהודעה יוצרים ערכי HMAC שונים מאוד. זה קורה בכוונה.
זוהי התנהגות מכוונת ורצויה של HMAC.
המסקנה: חשוב לוודא שגוף ההודעה שמשמש לחישוב ה-HMAC המקורי וגוף ההודעה שמשמש לאימות ה-HMAC זהים לחלוטין. אם המאמת של HMAC משנה את מטען ההודעה בכל דרך שהיא, על ידי הוספת רווח לבן או עיצוב מחדש של הטקסט, ה-HMAC המחושב ישתנה.
חשוב להיזהר במיוחד כשמשתמשים בתבנית הודעה בהגדרת המדיניות. לדוגמה, בקטע ההגדרה הבא של המדיניות מוצגת בעיה פוטנציאלית:
<HMAC name='HMAC-1'>
...
<!-- the result of this message template will include surrounding whitespace -->
<Message>
{request.content}
</Message>
...
</HMAC>התוצאה של הערכת תבנית ההודעה בתוך הרכיב <Message>
תכלול שורות חדשות ורווחים מסביב לתוכן ההודעה. זה כנראה לא מה שהתכוונתם. הגדרה טובה יותר תיראה כך:
<HMAC name='HMAC-1'>
...
<Message>{request.content}</Message>
...
</HMAC>הבדלים בקידוד
פענוחים שונים של אותו חומר מפתח יוצרים מפתחות שונים. נניח שיש מפתח סודי שאפשר לייצג אותו בתור U2VjcmV0S2V5MTIz. אחרי פענוח בקידוד UTF-8, הבייטים של המפתח כמו שהם מוצגים בקידוד base16 יהיו: [55 32 56 6a 63 6d 56 30 53 32 56 35 4d 54 49 7a].
אחרי פענוח בקידוד Base64, בייטי המפתח יהיו [53 65 63 72 65 74 4b 65 79 31 32 33].
פענוח שונה של חומר המקור יניב מפתחות שונים, וכתוצאה מכך ערכי HMAC שונים.
המסקנה: חשוב לוודא שחומר המפתח שמשמש לחישוב ה-HMAC המקורי והמפתח שמשמש לאימות ה-HMAC זהים לחלוטין. המשמעות היא כנראה שצריך לוודא שמשתמשים באותו קידוד של המפתח בשני הצדדים. במדיניות HMAC, אפשר להשתמש במאפיין encoding ברכיב SecretKey כדי לציין את קידוד המפתח.
כדאי גם לשקול קידודים בפלט. HMAC-SHA256 בקידוד הקסדצימלי base16, 27f17e11c8ece93844c5eb5e55161d993368628a214f9a51c25d0185e8ea06e2, זהה ל-HMAC-SHA256 בקידוד base64, J/F+Ecjs6ThExeteVRYdmTNoYoohT5pRwl0BhejqBuI=.
הן נראות שונה, אבל שתי המחרוזות האלה מייצגות את אותו ערך. מוודאים שנעשה שימוש באותו קידוד כדי לקודד את ה-HMAC שחושב במקור ואת ה-HMAC שמאמת. במדיניות HMAC,
אפשר להשתמש במאפיין encoding ברכיב Output
כדי לציין את קידוד הפלט הרצוי, ובאותו מאפיין ברכיב VerificationValue
כדי לציין איך לבצע פענוח קוד של מאמת החתימה.
הפניה לשגיאה
בקטע הזה מתוארים קודי השגיאות והודעות השגיאה שמוחזרים, ומשתני השגיאה שמוגדרים על ידי Apigee כשהמדיניות הזו מפעילה שגיאה. חשוב לדעת את המידע הזה אם אתם מפתחים כללי תקלות לטיפול בתקלות. מידע נוסף על שגיאות שקשורות למדיניות ועל טיפול בשגיאות
שגיאות זמן ריצה
השגיאות האלה יכולות להתרחש כשהמדיניות מופעלת.
| קוד תקלה | סטטוס HTTP | מתרחש כאשר |
|---|---|---|
steps.hmac.UnresolvedVariable |
401 | השגיאה הזו מתרחשת אם משתנה שצוין במדיניות HMAC הוא אחד מהבאים:
|
steps.hmac.HmacVerificationFailed |
401 | אימות ה-HMAC נכשל. ערך האימות שסופק לא תואם לערך המחושב. |
steps.hmac.HmacCalculationFailed |
401 | המדיניות לא הצליחה לחשב את ה-HMAC. |
steps.hmac.EmptySecretKey |
401 | הערך של משתנה המפתח הסודי ריק. |
steps.hmac.EmptyVerificationValue |
401 | המשתנה שמכיל את ערך האימות ריק. |
שגיאות פריסה
השגיאות האלה יכולות להתרחש כשפורסים שרת proxy שמכיל את המדיניות הזו.
| שם השגיאה | סטטוס HTTP | מתרחש כאשר |
|---|---|---|
steps.hmac.MissingConfigurationElement |
401 | השגיאה הזו מתרחשת כשחסר אלמנט או מאפיין נדרש. |
steps.hmac.InvalidValueForElement |
401 | השגיאה הזו מתרחשת אם הערך שצוין ברכיב Algorithm לא תואם לאחד מהערכים הבאים: SHA-1, SHA-224, SHA-256, SHA-512 או MD-5. |
steps.hmac.InvalidSecretInConfig |
401 | השגיאה הזו מתרחשת אם יש ערך טקסט שצוין במפורש עבור SecretKey. |
steps.hmac.InvalidVariableName |
401 | השגיאה הזו מתרחשת אם המשתנה SecretKey לא מכיל את הקידומת private (private.).
private |
משתני תקלות
המשתנים האלה מוגדרים כשמתרחשת שגיאת זמן ריצה. מידע נוסף על שגיאות שקשורות למדיניות
| משתנים | כאשר: | דוגמה |
|---|---|---|
fault.name="fault_name" |
fault_name הוא שם התקלה, כפי שמופיע בטבלה Runtime errors שלמעלה. שם התקלה הוא החלק האחרון של קוד התקלה. | fault.name Matches "UnresolvedVariable" |
hmac.policy_name.failed |
המדיניות מגדירה את המשתנה הזה במקרה של כשל. | hmac.HMAC-Policy.failed = true |
דוגמה לתגובת שגיאה
לצורך טיפול בשגיאות, מומלץ ללכוד את החלק errorcode בתגובת השגיאה. אל תסתמכו על הטקסט ב-faultstring, כי הוא עשוי להשתנות.
דוגמה לכלל שגיאה
<FaultRules>
<FaultRule name="HMAC Policy Errors">
<Step>
<Name>AM-Unauthorized</Name>
<Condition>(fault.name Matches "HmacVerificationFailed")</Condition>
</Step>
<Condition>hmac.HMAC-1.failed = true</Condition>
</FaultRule>
</FaultRules>