تتحرك. مدينة جديدة. البحث عن وظيفة. حتى بالنسبة لمتخصصي تكنولوجيا المعلومات ، قد يستغرق هذا وقتًا طويلاً. سلسلة من المقابلات ، والتي ، بشكل عام ، تشبه إلى حد كبير بعضها البعض. وكما يحدث عادة عندما تجد وظيفة بالفعل ، بعد فترة ، يتم الإعلان عن مكتب واحد مثير للاهتمام.
كان من الصعب فهم ما كانت تفعله على وجه التحديد ، ومع ذلك ، كان مجال اهتمامها هو دراسة برامج الآخرين. يبدو الأمر مثيرا للاهتمام ، على الرغم من أنك عندما تدرك أن هذا لا يبدو أنه بائع يقوم بإصدار برامج للأمن السيبراني ، فإنك تتوقف لمدة ثانية وتبدأ في خدش اللفت.

باختصار: لقد ألقوا الأرشيف وعرضوا فحصه كمهمة اختبار ومحاولة حساب توقيع معين بناءً على بيانات الإدخال المقدمة. تجدر الإشارة إلى أنه كان لدي خبرة قليلة جدًا في مثل هذه الأنشطة ، وربما ، لهذا السبب لم يكن لدي سوى بضع ساعات في التكرار الأول للحل - ثم جاء الدافع للقيام بذلك. ونعم ، بالطبع ، أول شيء حاولت تشغيله على الهاتف / المحاكي - هذا التطبيق غير صالح.
ما لدينا: أرشيف مع التمديد
".apk" . لقد وضعت المهمة نفسها تحت المفسد بحيث لا يتم فهرستها بواسطة محركات البحث: ماذا لو أن الشباب لم يعجبهم ، أنني وضعت الحل على هبر؟
المهمة نفسهايحتوي ملف APK على وظيفة لإنشاء التواقيع لمجموعة مصفوفة.
حاول الحصول على توقيع لمجموعة البيانات التالية:
{ "user" : "LeetD3vM4st3R", "password": "__s33cr$$tV4lu3__", "hash": "34765983265937875692356935636464" }
نشمر عن الأكمام
يقال أن الأرشيف يحتوي على وظيفة توقيع مجموعة اقتران. من خلال امتداد الملف ، نتفهم على الفور أننا نتعامل مع تطبيق مكتوب لنظام Android. أولا نحن فك الأرشيف. في الواقع ، هذا أرشيف ZIP منتظم ، وأي أرشيف سوف يتعامل معه بسهولة. لقد استخدمت الأداة المساعدة apktool ، وكما اتضح ، تجاوزت عن طريق الخطأ بضع أشعل النار. نعم ، يحدث ذلك (عادة ما يكون العكس ، نعم؟). تعويذة بسيطة جدا:
apktool d task.zip
اتضح أن الكود والموارد في ملف apk مخزنة أيضًا في ثنائيات منفصلة ، وستكون هناك حاجة لبرامج أخرى لاستخراجها. apktool سحب ضمنيًا بايت بايت الموارد والموارد وتحلل الكل في التسلسل الهرمي للملفات الطبيعية. يمكنك المتابعة.
├── AndroidManifest.xml ├── apktool.yml ├── lib │ └── arm64-v8a ├── original │ ├── AndroidManifest.xml │ └── META-INF ├── res │ ├── anim │ ├── color │ ├── drawable │ ├── layout │ ├── layout-watch-v20 │ ├── mipmap-anydpi-v26 │ ├── values │ └── values-af ├── smali │ ├── android │ ├── butterknife │ ├── com │ ├── net │ └── org └── unknown └── org
نرى تسلسل هرمي مماثل (ترك نسخته المبسطة) ونحاول معرفة من أين نبدأ. تجدر الإشارة إلى أنني ما زلت أكتب مرة واحدة تطبيقين صغيرين على نظام أندرويد ، وبالتالي فإن جوهر جزء من الأدلة ، وبشكل عام ، مبادئ جهاز تطبيقات أندرويد ، أنا واضح للغاية.
بادئ ذي بدء ، قررت فقط "المشي" عبر الملفات. أفتح AndroidManifest.xml وابدأ القراءة بشكل مفيد. تجذب انتباهي سمة غريبة
android:supportsRtl="true"
اتضح أنه مسؤول عن دعم اللغات بحرف "من اليمين إلى اليسار" في التطبيق. نبدأ في الضغط. ليس جيد
علاوة على ذلك ، تتمسك نظري إلى المجلد غير المعروف. تحته تسلسل هرمي للنموذج:
org.apache.commons.codec.language.bm وعدد كبير من الملفات النصية ذات المحتوى الغامض. غوغل الاسم الكامل للحزمة ويظهر ما تم تخزينه هنا ، وهو شيء متعلق بخوارزمية البحث عن الكلمات المشابهة صوتيًا للكلمة المحددة. بصراحة ، هنا بدأت في الضغط بشدة. بعد أن اكتشفت الدلائل قليلاً ، وجدت في الحقيقة الكود نفسه ، ثم بدأت المتعة. لم تقابلني شفرة جافا المعتادة ، والتي تمكنت من اللعب بها في أي وقت ، لكنني شيء آخر. مشابهة جدا ، ولكن مختلفة.
كما اتضح فيما بعد ، يمتلك Android الجهاز الافتراضي الخاص به - Dalvik. ومثل أي جهاز افتراضي محترم ، فإنه يحتوي على رمز ثانوي خاص به. يبدو أنه في المحاولة الأولى لحل هذه المشكلة ، كان في هذه الملاحظة المحزنة أنني أعلنت استراحة ، وانحنى ، وإسقاط الستار ورمي كل شيء لمدة 4 أشهر حتى فضولي الانتهاء تماما لي.
نشمر الأكمام [2]
"لكن لا يمكن أن يكون الأمر أسهل؟" - هذا هو السؤال الذي طرحته على نفسي عندما بدأت المهمة للمرة الثانية. لقد بدأت البحث في الإنترنت عن برنامج فك تشفير من smali إلى Java. لقد رأيت أنه من المستحيل تنفيذ هذه العملية بشكل لا لبس فيه. عبث قليلا ، ذهب إلى جيثب وقاد بضع عبارات رئيسية في خط البحث. الأول جاء
smali2java .
git clone gradle build java -jar smali2java.jar ..
خطأ. أرى تتبعًا مكدسًا كبيرًا وأخطاءًا على عدة صفحات من الجهاز. بعد قراءة القليل عن جوهر المحتوى (وتقييد المشاعر من حجم تتبع المكدس) ، أجد أن هذه الأداة تعمل على أساس قواعد معينة تم وصفها وأن الكود الثنائي الذي قابلته بوضوح لا يتوافق معه. أفتح bytecode smali ونرى التعليقات التوضيحية والأساليب الاصطناعية وغيرها من المنشآت الغريبة فيها. لم يكن هناك شيء من هذا القبيل في جافا bytecode! الى متى؟ حذف!
مزيد من التفاصيلالجهاز الظاهري Dalvik (وكذلك JVM) ، كما اتضح فيما بعد ، لا يدرك وجود مفاهيم مثل الطبقات الداخلية / الخارجية (قراءة الطبقات المتداخلة) ، ويقوم المترجم بإنشاء ما يسمى بالطرق "الاصطناعية" لتوفير الوصول من الفصل المتداخل إلى الحقول الخارجية ، على سبيل المثال.
كمثال:
إذا كانت الطبقة الخارجية (OuterClass) بها مجال
public class OuterClass { List a; ... }
بحيث يمكن للفئة الخاصة الوصول إلى حقل الفئة الخارجية ، سيقوم المترجم ضمنيًا بإنشاء الطريقة التالية:
static synthetic java.util.List getList(OuterClass p1) { p1 = p1.a; return p1; }
أيضًا ، نظرًا لمطبخ "مقصورة المحرك" ، يتم إنجاز بعض الآليات الأخرى التي توفرها اللغة.
يمكنك البدء في دراسة هذا السؤال بمزيد
من التفاصيل
من هنا .
لا يساعد انه يقسم حتى على ما يبدو غير المشبوهة. أفتح الكود المصدري لبرنامج فك الرموز ، قرأ وشاهد شيئًا غريبًا للغاية: حتى المبرمجين الهندوس (مع كل الاحترام الواجب) لم يكتبوا هذا. تزحف الفكر إلى: ليس في الحقيقة الكود الذي تم إنشاؤه. أرفض الفكرة لمدة 30 دقيقة ، وأحاول أن أفهم ماهية الخطأ. صعوبة. أفتح Github مرة أخرى - وحقًا ، محلل لغوي تم إنشاؤه. وهنا المولد نفسه. وضع كل شيء بعيدا ومحاولة الاقتراب من الجانب الآخر.
تجدر الإشارة إلى أنه بعد ذلك بقليل ، ما زلت أحاول تغيير قواعد اللغة وفي الأماكن حتى الرمز الثنائي نفسه بحيث لا يزال بإمكان أداة فك الشفرة استيعابها. ولكن حتى عندما أصبح الرمز الثنائي صالحًا فيما يتعلق بقواعد إلغاء ترجمته ، فإن البرنامج ببساطة لم يعيد أي شيء إلي. المصدر المفتوح ...أنا ورقة من خلال bytecode وتعثر على الثوابت غير معروف لي. غوغلينغ ، وأنا أقابل نفسه في الكتاب على تطبيقات أندرويد العكسي. أتذكر أن هذا هو المعرف الذي تم تعيينه بواسطة المعالج المسبق لبرنامج التحويل البرمجي فقط ، والذي تم تعيينه لموارد تطبيق Android (ثابت وقت كتابة التعليمات البرمجية هو R. *). في النصف ساعة القادمة ، سأدرس بإيجاز السجلات التي تكون مسؤولة عن أي ترتيب يتم تمرير الحجج ، وبصورة عامة الخوض في بناء الجملة.
كيف تبدو؟

لقد وجدت تخطيط نافذة التطبيق الرئيسية ، ومنه فهمت بالفعل ما كان يجري في التطبيق: على الشاشة الرئيسية (النشاط) هناك RecyclerView (مشروط ، طريقة عرض يمكنها إعادة استخدام كائنات واجهة المستخدم غير المعروضة حاليًا لاستخدام الذاكرة) مع حقول الإدخال أزواج المفتاح / القيمة ، واثنين من الأزرار المسؤولة عن إضافة زوج مفتاح / قيمة جديد إلى حاوية مجردة معينة ، وزر يقوم بإنشاء توقيع (توقيع) لهذه الحاوية.
بالنظر إلى التعليقات التوضيحية ومراقبة قدر معين من الشفرة يشبه بشكل مثير للريبة تلك التي تم إنشاؤها ، أبدأ في google. يستخدم المشروع مكتبة ButterKnife ، والتي تتيح استخدام التعليقات التوضيحية
لتضخيم () -> ربط () عناصر واجهة المستخدم تلقائيًا. إذا كانت هناك تعليقات توضيحية في الفصل ، يقوم معالج التعليقات التوضيحية ButterKnife ضمنيًا بإنشاء فئة الموثق أخرى من النموذج
<original_class> __ViewBinding ، التي تقوم بجميع الأعمال القذرة تحت الغطاء. في الواقع ، حصلت على كل هذه المعلومات من ملف MainActivity واحد فقط بعد أن قمت بإعادة إنشاء تشابه مصدر Java منه يدويًا. بعد نصف ساعة ، أدركت أن التعليقات التوضيحية لهذه المكتبة يمكن أيضًا تعيين رد اتصال على إجراءات الأزرار ووجدت تلك الوظائف الأساسية التي كانت مسؤولة فعليًا عن إضافة زوج مفتاح / قيمة إلى الحاوية وإنشاء توقيع.
بالطبع ، خلال الدراسة ، اضطررت للدخول في "الحوارات" الخاصة بمختلف المكتبات والمكونات الإضافية ، لأن حتى landos الجميلة التي تحتوي على ملفات تعريف الارتباط لا تغطي جميع حالات الاستخدام والتفاصيل ، والتي تعتبر بالنسبة لأي "عكس" ممارسة شائعة.الكسل صديق للمبرمج
بعد قضاء بعض الوقت في المصدر الثاني ، شعرت بالتعب التام وأدركت أنه من غير الممكن طهي العصيدة. أنا أتسلق جيثب مرة أخرى ، وهذه المرة أنا أبحث عن كثب. أجد مشروع
Smali2PsuedoJava - أداة فك شفرة في "كود جافا الزائف". حتى لو كانت هذه الأداة مفيدة ، فقد يؤدي شيء على الأقل إلى ظهور إنساني ، فبالنسبة لي المؤلف هو قدح من البيرة المفضلة (جيدًا ، أو وضع علامة النجمة على الأقل على جيثب ، بالنسبة للمبتدئين).
وانها تعمل حقا! التأثير على الوجه:

تلبية Cipher.so
بعد ذلك بقليل ، عند دراسة كود جافا المزيف للمشروع ومقارنته بشكل لا يصدق مع الرمز smali ، أجد مكتبة غريبة في الكود - Cipher.so. غوغل ، أجد أنه تشفير مجموعة من قيم وقت الترجمة داخل أرشيف APK. يعد هذا ضروريًا عادةً عندما يستخدم التطبيق ثوابت النموذج: عناوين IP أو بيانات الاعتماد لقاعدة بيانات خارجية أو الرموز المميزة للترخيص ، إلخ. - ما الذي يمكن الحصول عليه بمساعدة الهندسة العكسية للتطبيق. صحيح أن المؤلف يكتب بوضوح أن هذا المشروع تم التخلي عنه ، كما يقولون ، يذهب بعيداً. هذا هو الحصول على اهتمام.
توفر هذه المكتبة الوصول إلى القيم من خلال مكتبة Java ، حيث الطريقة المحددة هي مفتاح اهتمامنا. يعمل هذا على إذكاء اهتمامي فقط ، وأبدأ في الصعود بشكل أعمق.
باختصار ، ماذا تفعل Cipher.so وكيف تعمل:
- في ملف Gradle لمشروعنا ، يتم تسجيل المفاتيح والقيم المقابلة
- سيتم تجميع جميع القيم الأساسية تلقائيًا في مكتبة ديناميكية منفصلة (.so) ، والتي سيتم إنشاؤها في وقت الترجمة. نعم - نعم ، سوف تتولد.
- ثم يمكن الحصول على هذه المفاتيح من أساليب Java التي تم إنشاؤها بواسطة Cipher.so
- بعد إنشاء ملف APK ، يتم تقسيم الأسماء الأساسية بواسطة MD5 (لمزيد من الأمان ، بالطبع)
بعد العثور على المكتبة الديناميكية التي أحتاجها في مجلد الأرشيف ، انتقل إلى اختيارها. بادئ ذي بدء ، كعكس ذي خبرة (لا) ، أحاول أن أبدأ بعكس بسيط - قررت إلقاء نظرة على القسم مع الثوابت والخطوط المهمة في بينار يشبه ELF. لسوء الحظ ، فإن مستخدمي mac readelf من الصندوق مفقودون ، وقبل البداية نقول لهم العزيزة:
brew install binuitls
ولا تنس أن تكتب المسار إلى
/ usr / local في PATH ، لأن هذا
المشروب يحميك من كل شيء بطريقة مهذبة ...
greadelf -p .rodata lib/arm64-v8a/libcipher-lib.so | head -n 15
نحن نحصر الإخراج في أول 15 سطرًا ، وإلا فقد يؤدي ذلك إلى صدمة لمهندس غير مستعد.

في العناوين السفلية نلاحظ خطوط مشبوهة. كما اكتشفت ، عند دراسة مصادر Cipher.so ، يتم وضع المفاتيح والقيم في
std :: map المعتادة
: هذا يعطي القليل من المعلومات ، لكننا نعلم أنه في binar مع كلمات المرور المشفرة هناك أيضًا مفاتيح غامضة.
كيف يتم تشفير القيم؟ عند دراسة المصدر ، وجدت أن التشفير يحدث باستخدام AES - نظام التشفير المتماثل القياسي. لذلك ، إذا كانت هناك قيم مشفرة ، فيجب أن يكون المفتاح في مكان قريب ... بعد أن درسته لفترة من الوقت ، واجهت مشكلة في نفس المشروع بعنوان استفزازي
"تخزين المفاتيح غير الآمن: أسرار يسهل استرجاعها" . في ذلك ، في الواقع ، اكتشفت أن المفتاح يتم تخزينه في شكل واضح في binar ، والعثور على خوارزمية فك التشفير. في المثال ، كان المفتاح في العنوان صفر ، وعلى الرغم من أنني فهمت أن المترجم يمكنه وضعه في مكان آخر في قسم .rodata في الملف الثنائي ، فقد قررت أن هذه الوحدة المشبوهة في العنوان صفر هي المفتاح.
محاولة رقم 1: أتابع فك رموز القيم وأعتقد أن مفتاح التشفير هو نفسه. الخطأ. يشير OpenSSL إلى أن هناك شيئًا ما غير صحيح. بعد قراءة مصادر Cipher.so قليلاً ، أفهم أنه إذا لم يحدد المستخدم مفتاحًا أثناء التجميع ، فسيتم استخدام المفتاح الافتراضي -
Cipher.so@DEFAULT .
محاولة # 2: خطأ مرة أخرى. هم ... هل هو حقا إعادة تعريف هذا الثابت؟ من السهل جدًا ارتكاب خطأ: رمز مربك مكتوب في Gradle ، مع تنسيق "ذهب". أنا تحقق مرة أخرى. كل شيء يبدو أن يكون كذلك.
بدلاً من المفاتيح هي تجزئة MD5 الخاصة بها ، ثم أحاول تجربة حظي وفتح خدمة مع طاولات قوس قزح. فويلا - أحد المفاتيح هو كلمة "كلمة المرور". لا يوجد ثانية. هذا يعطينا ، بالطبع ، ليس كثيرا. كلا المفتاحين موجودان في العنوانين 240 و 2 a2 ، على التوالي. من حيث المبدأ ، يكون التعرف عليها فورًا سهلًا - 32 حرفًا (MD5).
لقد راجعت كل شيء مرة أخرى وحاولت فك التشفير مع جميع الأسطر الأخرى (الموجودة في العناوين السفلية) كمفتاح لفك التشفير - كل شيء عبث.
لذلك ، هناك مفتاح سري آخر ، يبدو أن خوارزمية الإجراءات صحيحة. أرمي هذه المهمة جانبا وأحاول ألا أدفن نفسي.
بعد أن قمت بالتفتيش قليلاً في خوارزمية توقيع الحاوية ، ما زلت أرى مكالمات إلى مكتبة Cipher.so والرمز الذي يستخدم أيضًا وظائف التشفير لمكتبة Java.
لغز (لم أحله أبدًا)
في الوظيفة المسؤولة عن التشفير ، في البداية هناك فحص للمفاتيح في الحاوية.
public byte[] a(java/util/Map p1) { v0 = p1.size() v1 = 0x0; if (v0 != 0) goto :cond_0 p1 = new byte[v1]; return p1; :cond_0 v0 = "user"; v0 = p1.containsKey(v0) if (v0 == 0) goto :cond_1 p1 = new byte[v1]; return p1; ...
حرفيًا: إذا كان هناك مفتاح "مستخدم" ، فلن يتم توقيع هذه الحاوية (يتم إرجاع توقيع صفري). شعور غريب: يبدو أن المشكلة قد تم حلها ، لكنها تبدو بسيطة بشكل مثير للريبة. ثم لماذا اخترع كل شيء آخر؟ لقيادة ضلال؟ إذن لماذا لم أدرس هذا الكود بطلاقة من قبل؟ هم ...
لا ، ليس صحيحا. لقد حددت الإجابة من مستخدم معين في برنامج messenger أزرق ، تم تزويد جهات اتصاله به عند إعطاء المهمة. مزيد من الحفر. ربما يتغير مفتاح الإدخال / القيمة بطريقة ما حيث يتم إضافته إلى الحاوية؟ قرأت الكود بعناية.
يرجى ملاحظة أن أداة فك التشفير أزلت التعليقات التوضيحية من رمز smali. ماذا لو أزال شيئًا مهمًا؟ أتحقق من الملفات الرئيسية - على ما يبدو ، لا شيء مهم. كل شيء مهم موجود ، لكن المعنى لا يضيع. أتحقق من وظائف رد الاتصال المسؤولة عن كتابة زوج / قيمة زوجي من مربع نص شرطي إلى حاويات داخلية. لم أجد أي شيء جنائي.
أصبحت متشككًا قدر الإمكان في كل سطر من التعليمات البرمجية - لم يعد بإمكاني الوثوق بأي أحد.
الحل البسيط رقم 2: لاحظت أن إجراء التوقيع يبدأ بالتحقق من وجود بعض القيمة (سلسلة فرعية في السلسلة) في توقيع الشهادة التي تم توقيع التطبيق عليها.
@OnClick
المعنى نفسه ، بطبيعة الحال ، يكمن مشفر في هذا المنبر المشؤوم. وفي الواقع ، إذا لم تكن هذه القيمة في التوقيع ، فلن تقوم الخوارزمية بالتوقيع على أي شيء ، ولكن ببساطة تُرجع السلسلة "بلا بيانات" ، لأن التوقيع ... مرة أخرى ، يتم أخذنا من أجل Cipher ...
مفتاح فك التشفير المعركة النهائية
لفهم حجم المأساة ، شعرت بالارتباك مثل هذا:
لقد قمت بتفريغ سداسي عشرية من هذا القسم وطلعت إلى أول سطرين ، الشكوك التي لم تهدأ من البداية.

إذا كنت تهتم ، فإن الحرف الذي يفصل السطور هنا هو "0x00". كما أنها تستخدم عادة من قبل مكتبة C القياسية ، في وظائف السلسلة. من هذا لا يقل إثارة للاهتمام ، ما هو نوع حرف الفضاء في منتصف السطر الأول؟ بعد ذلك ، تبدأ المحاولات المجنونة ، حيث يكون المفتاح:
- الصف الأول كله
- السطر الأول قبل الفضاء
- السطر الأول من الفضاء إلى النهاية
- ...
يمكن بالفعل تقدير درجة جنون العظمة. عندما لا تفهم مدى صعوبة المهمة ومكرتها ، تبدأ في القيادة. وحتى الآن ، ليس هذا. ثم فكرت الفكرة: "هل الخوارزمية تعمل بشكل صحيح من مشكلة على الجهاز الخاص بي؟". بشكل عام ، تسلسل الإجراءات هناك منطقي ولم يطرح أسئلة ، ولكن السؤال هو: هل تفعل الأوامر على الجهاز الخاص بي ما تحتاجه منها؟ إذن ما رأيك؟
بعد التحقق من جميع الخطوات يدويًا ، اتضح ذلك
echo "some_base64_input" | openssl base64 -d
في بعض وسائط الإدخال ، تقوم فجأة بإرجاع سلسلة فارغة. هم.
استبداله بأول وحدة فك ترميز base64 على الجهاز ، والفرز خلال المرشحين الرئيسيين ، تم العثور على مفتاح مناسب على الفور ، وتم فك تشفير المفاتيح وفقًا لذلك.
استرداد التواقيع من الشهادة
class a { public static boolean isKeyInSignature(android.content.Context p1) { v0 = 0x0; try TRY_0{ v1 = p1.getPackageManager() p0 = p1.getPackageName() v2 = 0x40;
هذا هو ما يشبه الكود الكود الناتج بعد التعديلات الطفيفة التي أجريتها. يخلط بين عدة أشياء:
- ضعف المعرفة من التشفير و "المطبخ" من شهادات الجهاز
- وفقًا للوثائق ، لا تضمن هذه الطريقة ترتيب الشهادات في المجموعة التي تم إرجاعها ، وبالتالي ، لن يكون من الممكن الالتفاف حولها بنفس الترتيب - ماذا لو تم توقيع الطلب مع أكثر من شهادة واحدة؟
- عدم معرفة كيفية استخراج الشهادة من APK ، بالنظر إلى أنه ليس من الواضح ما يفعله Android Runtime في هذه الحالة
اضطررت إلى الخوض في كل هذه القضايا وكانت النتيجة على النحو التالي:
- الشهادة نفسها موجودة في الدليل الأصلي / META-INF / CERT.RSA
في هذا الدليل ، يوجد ملف واحد فقط به هذا الملحق - مما يعني أن التطبيق موقّع بشهادة واحدة فقط
- على الموقع الخاص بالهندسة البحثية لتطبيقات Android ، تم العثور على قائمة يمكنها استخراج التوقيع الذي نحتاجه كما يفعل Android. وفقا للمؤلف ، على الأقل.
من خلال تشغيل هذا الرمز ، يمكنني معرفة التوقيع ، وفي الواقع ، المفتاح الذي نحتاجه هو سلسلة فرعية. المضي قدما. تم حل بسيط الحل # 2.
في الواقع ، المفتاح موجود في الشهادة ، يبقى فقط لفهم ما هو التالي ، لأنه إذا كان لدينا مفتاح "المستخدم" ، فإننا جميعًا نحصل على توقيع صفري ، وكما تعلمنا أعلاه ، فهذه هي الإجابة الخاطئة.
اكتب الوثائق بعناية!
يتم تجاهل المزيد من الأبحاث حول حقيقة أن البيانات المدخلة من حقول النص يتم تجاهلها بسبب نقص الأدلة. تتلاشى جنون العظمة بقوة متجددة: ربما تكون الشفرة التي سحبت التوقيع من الشهادة غير صحيحة أم أنها تطبيق رمز لإصدارات Android القديمة؟ أفتح الوثائق مرة أخرى وأرى ما يلي: (
https://developer.android.com/reference/android/content/pm/Signature.html#toChars () ):
ملاحظة: تقوم الدالة بترميز التوقيع كنص ASCII. كان الإخراج الذي تلقيته أعلاه تمثيلًا سادسًا للبيانات. بدا أن واجهة برمجة التطبيقات هذه غريبة بالنسبة لي ، ولكن إذا كنت تعتقد أن الوثائق ، فقد تبين لي أنني توقفت مرة أخرى ، وأن المفتاح المشفر ليس سلسلة فرعية للتوقيع. بعد الجلوس بعمق على الكود لفترة ، لم أتمكن من الوقوف وفتح الكود المصدري لهذه الفئة.
https://android.googlesource.com/platform/frameworks/base/+/e639da7/core/java/android/content/pm/Signature.javaالجواب لم يمض وقت طويل. وفي الواقع ، في الكود نفسه - لوحة زيتية: تنسيق الإخراج عبارة عن سلسلة سداسية عادية. والآن فكر: إما أنني لا أفهم شيئًا ما ، أو أن الوثائق مكتوبة "قليلاً" بشكل غير صحيح. بعد أن وبخت بأي حال من الأحوال ، أعدت العمل مرة أخرى.
يؤدي
لقد مرت الساعات n التالية:
- التحقق من صحة العمل في الكود باستخدام RecyclerView والتأكد من سلوكه من خلال الكود المصدري منذ ذلك الحين مرة أخرى ، لا يتم تغطية جميع النقاط بالتفصيل في قفص الاتهام وحتى على Stackoverflow
- إلغاء التجميع اليدوي لشريحة التعليمات البرمجية المسؤولة عن توقيع المجموعة في Java المترجمة. أخذت على افتراض أنني ما زلت أفتقد شيئًا وأن المفتاح الأول في الحاوية ("المستخدم") تم إسقاطه ضمنيًا من المجموعة. قررت ضبط بقية البيانات على الكود.
بشكل عام ، رفض هذا الرمز التوقيع حتى على الوسيطات المتبقية (كذلك في التعليمات البرمجية عند التعامل مع التشفير ، هذه الوسائط دفعتني ضمنيًا من بعيد).لا. , . , , , , . . — , , , .
, , . . , . , - , , « », , .
إذا كان هناك من يريد أن يحاول التعمق في هذه المهمة أكثر من ذلك بقليل أو طرح سؤال - اكتب لي في رسول arturbrsg الأزرق .ترقبوا.