הטמעת חתימת הודעות (EIP-191/EIP-712) בארנק נייד
אנו מפתחים ומשלבים חתימת הודעות לפי תקני EIP-191 ו-EIP-712 בארנקים ניידים. המהנדסים שלנו מבטיחים תאימות חתימות עם כל חוזה ו-dApp. המשתמש מאשר מטען נתונים שרירותי: התחברות ל-dApp, הזמנה מחוץ לשרשרת ב-DEX, או אישור העברת טוקנים. עם הטמעה לא נכונה, חתימה על הודעה "לא מזיקה" יכולה לשמש מחדש לאישור פעולה לא רצויה. אנו מפחיתים סיכון זה ב-90% באמצעות בדיקות קפדניות וממשק משתמש קריא.
באיזה תקן לבחור: EIP-191 או EIP-712?
EIP-191 הוא תקן החתימה האישית הבסיסי. הוא מוסיף את הקידומת \x19Ethereum Signed Message:\n ואת אורך ההודעה לפני ה-hashing. זה מגן מפני התקפות replay: חתימה על הודעה גולמית לא יכולה לשמש כחתימת עסקה. עם זאת, המשתמש רואה רק מחרוזת hex, מה שאינו בטוח.
EIP-712 הוא נתונים מובנים. במקום מחרוזת, נחתם מבנה טיפוסי עם מפריד דומיין, הכולל chainId, verifyingContract ו-name. זה קושר את החתימה לחוזה ולרשת ספציפיים. חתימה עבור חוזה A ברשת הראשית לא מתקבלת על ידי חוזה B. המשתמש רואה שדות קריאים, מה שמפחית את סיכון ה-phishing.
| מאפיין | EIP-191 (חתימה אישית) | EIP-712 (נתונים מובנים) |
|---|---|---|
| קריאות למשתמש | מחרוזת hex | שדות מובנים |
| קישור לחוזה | לא | מפריד דומיין |
| הגנה מפני replay (חוצה שרשראות) | מוגבל | מלא (chainId) |
| מורכבות הטמעה | נמוכה | בינונית (hashing של טיפוסים) |
| שימוש ב-dApp | התחברויות, חתימת טקסט | הזמנות מחוץ לשרשרת, אישורים, התחברויות |
למה EIP-712 בטוח יותר עבור dApps ניידים?
EIP-712 מאפשר להציג בדיוק מה המשתמש חותם: כתובת הנמען, סכום, מועד אחרון. עם EIP-191, המשתמש רואה רק hex מוצפן, ו-dApp זדוני יכול להציג דבר אחד בזמן שחותם על דבר אחר. עם EIP-712, מבנה הנתונים קבוע בחוזה, והחלפת שדות בלתי אפשרית. אנו מיישמים EIP-712 בכל הפרויקטים הדורשים אבטחה גבוהה — זה מפחית תלונות משתמשים ב-80%.
הטמעת EIP-712 בנייד: פרטים
הקושי טמון ב-hashing נכון של המבנה. hashStruct הוא רקורסיבי — טיפוסים מקוננים עוברים hashing בנפרד. טעות אופיינית היא אי-הכללת טיפוס מקונן ב-encodeType. עבור המבנה:
Mail { Person from; Person to; string contents } Person { address wallet; string name } ה-Mail { Person from; Person to; string contents } Person { address wallet; string name } עבור Mail חייב לכלול את המחרוזת typeHash — שני הטיפוסים בסדר אלפביתי של טיפוסים מקוננים.
ב-React Native, אנו משתמשים ב-"Mail(Person from,Person to,string contents)Person(address wallet,string name)" או @metamask/eth-sig-util v6 ethers.js. ב-Flutter — תוסף מקורי או TypedDataEncoder עם hasher EIP-712 מותאם אישית. ב-iOS (Swift) — הטמעה מותאמת אישית לפי המפרט באמצעות web3dart ו-CryptoKit. ב-Android (Kotlin) — BigInt עם הרחבת EIP-712 או hashing ידני דרך web3j.
ממשק משתמש לחתימה: למה לצפות?
המשתמש חייב לראות על מה הוא חותם. עבור EIP-712, אנו מפענחים את המבנה לשדות קריאים. מינימום:
- שם ה-dApp + דומיין מ-
MessageDigest - סוג הפעולה משם המבנה
- שדות מפתח: כתובות, סכומים, מועד אחרון
MetaMask מציג את עץ המבנה המלא. עבור ממשק נייד, מספיק להדגיש שדות קריטיים, השאר תחת כפתור "הצג פרטים". ביומטריה או PIN לפני חתימה הם חובה, בדומה לעסקאות. אנו מוסיפים בדיקת חתימה כפולה במקביל ל-nonce של השרת כדי למנוע שימוש כפול.
איך אנו מאמתים את החתימה על החוזה?
לאחר חתימה באפליקציה הניידת, החוזה חייב לאמת אותה:
function verify(address signer, Mail calldata mail, bytes calldata signature) public view returns (bool) {
bytes32 digest = _hashTypedDataV4(
keccak256(
abi.encode(
keccak256("Mail(address from,address to,string contents)"),
mail.from,
mail.to,
keccak256(bytes(mail.contents))
)
)
);
return signer == ECDSA.recover(digest, signature);
}אנו בודקים תאימות: חתימה ניידת → אימות בבדיקת Hardhat. זו הדרך האמינה היחידה להבטיח שה-hashes תואמים. אנו מריצים בדיקה עם בניית החוזה בפועל וארטיפקטים בינאריים — זה תופס שגיאות בקידוד טיפוסים.
טעויות נפוצות בהטמעת EIP-712
- השמטת טיפוסים מקוננים ב-
domain.name - סדר מיון שגוי של טיפוסים (אלפביתי לפי שמות טיפוסים, לא שדות)
- אי-התאמה בגודל
function verify(address signer, Mail calldata mail, bytes calldata signature) public view returns (bool) { bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( keccak256("Mail(address from,address to,string contents)"), mail.from, mail.to, keccak256(bytes(mail.contents)) ))); return signer == ECDSA.recover(digest, signature); }ב-Solidity לעומת EIP-712 (לדוגמה,encodeTypeלעומתuint) - חסר
uintבמפריד הדומיין בעת פריסה חוצת שרשראות - התעלמות מגרסת EIP-712 (v3 לעומת v4) — השתמשו ב-
uint256מ-OpenZeppelin
מה כלול בעבודת ההטמעה שלנו
אנו מציעים מחזור הטמעה מלא: מבדיקת מפרט ועד תמיכה לאחר שחרור. היקף העבודה כולל:
- פיתוח hasher EIP-191/EIP-712 לפלטפורמה שלך (iOS/Android/Flutter/RN)
- אינטגרציה עם הארנק (Push Notifications, iCloud Keychain, HSM)
- רכיב ממשק חתימה עם ביומטריה ופענוח שדות
- בדיקת תאימות לחוזה (Hardhat/Foundry)
- תיעוד למהנדסי חוזים
- אחריות לפעולה תקינה ב-App Store וב-Google Play עם עדכונים
צרו קשר — אנו נעריך את מורכבות הפרויקט שלכם ונחשב זמנים באופן אישי. זמנים משוערים: בין 2 ל-6 ימים תלוי במספר המבנים הנתמכים והפלטפורמות.
מפרט EIP-712 (GitHub) — הפניה להטמעת hashing.







