بطاقات ذكية. الجزء 4. JavaCard

مرحبا Giktayms!

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

لذا ، فإن البطاقة الذكية القائمة على JavaCard هي بطاقة يتم تشغيل التطبيقات عليها على JavaCard Virtual Machine (نسخة محدودة من Java Virtual Machine المكيفة للبطاقات الذكية) في ما يسمى JavaCard Runtime Environment (التي تشترك في القليل مع بيئة وقت التشغيل Java) .

من حيث المصطلحات ، تسمى التطبيقات تطبيقات صغيرة وهي موجودة في الحزم. يتم توزيع الحزم في ملفات CAP (بدلاً من ملفات Jar). الحزم والتطبيقات لها AID الخاص بها (معرف التطبيق). يعد ذلك ضروريًا بحيث يمكن تحديدها بشكل فريد في أوامر مثل: SELECT و INSTALL و DELETE وما إلى ذلك. (SELECT موصوفة في ISO7816-4 ، وجافا كارد وأوامر أخرى موصوفة في المنصة العالمية).

تختلف دورة حياة التطبيقات الصغيرة قليلاً عن دورة الحياة المعتادة لتطبيقات الكمبيوتر. بريمج هو أي فئة ترث من الفئة الأساسية بريمج. عند تثبيت التطبيقات ، تسمى طريقة التثبيت الثابتة الخاصة به. يجب أن تنشئ هذه الطريقة كائنًا من الفئة المقابلة وتستدعي طريقة التسجيل الموجودة عليه. بعد ذلك ، سيتم حفظ الكائن في النظام وسيتلقى AID الخاص به ، والذي سيتم استخدامه لمزيد من التواصل مع التطبيق. يتم تخزين الكائن وحقول البيانات الخاصة به في NVM (ذاكرة غير متطايرة). كل كائن أو صفيف تم إنشاؤه بواسطة التطبيق باستخدام عامل التشغيل "الجديد" سيكون أيضًا في NVM. هذا يعني أنه على عكس برامج الكمبيوتر التقليدية ، فإن حالة تطبيقات JavaCard ثابتة ولا تضيع حتى عند إيقاف تشغيل البطاقة.

التواصل مع التطبيق


في أي وقت ، لكل قناة منطقية مفتوحة تطبيق نشط واحد. التطبيق النشط هو التطبيق الذي يستقبل جميع وحدات APDU المرسلة من قبل الجهاز. عند استلام APDU ، تستدعي JavaCard طريقة العملية للتطبيق النشط ، والتي تأخذ APDU المستلم كمعلمة فقط. هذه الطريقة هي جوهر التطبيق الصغير ، لأنها تعالج الطلبات من المحطة الطرفية. يتم استخدام APDU الناتج أيضًا لإرسال الردود.

يمكن تنشيط التطبيق الصغير بطريقتين:

  • عند إعادة تعيين البطاقة أو عند فتح قناة منطقية ، يقوم النظام عادة بتنشيط التطبيق الذي تم وضع علامة "تطبيق افتراضي" عليه
  • باستخدام الأمر SELECT مع P1 = 0 × 0 و AID (كامل أو جزئي) للتطبيق في البيانات

عندما يتم تنشيط التطبيق باستخدام الأمر SELECT ، مباشرة بعد التنشيط ، سيتم استدعاء طريقة العملية مع APDU التي تحتوي على هذا الأمر. وبالتالي ، فإن التطبيق الصغير قادر على إرسال المعلومات استجابة لأمر SELECT عند التنشيط. توفر فئة التطبيق الصغير طريقة selectApplet () لتحديد ما إذا كان الأمر المستلم قد تسبب في تنشيط التطبيق.

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

يمكن فتح القنوات المنطقية وإغلاقها باستخدام أمر إدارة القناة. من خلال القنوات المنطقية المفتوحة ، يمكنك إرسال أي أوامر ، بما في ذلك SELECT. إن SELECT and MANAGE CHANNEL هي الأوامر الوحيدة التي تتم معالجتها مباشرة بواسطة النظام ، وليس بواسطة التطبيق النشط. على الرغم من أنه في حالة الأمر SELECT ، يمكننا القول أنه تمت معالجته بواسطة كل من النظام والتطبيق النشط.

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

إدارة الذاكرة


كما قلت أعلاه ، يتم تخزين الكائنات والمصفوفات بشكل افتراضي في NVM. بالإضافة إلى NVM ، تتيح JavaCard أيضًا إنشاء صفائف في ذاكرة الوصول العشوائي باستخدام عدد من الأساليب من فئة JCSystem. هناك نوعان من الذاكرة المؤقتة: Clear on Reset و Clear on Deselect. يتم مسح البطاقة الأولى عند إيقاف تشغيل البطاقة أو إعادة ضبطها. يتم مسح الثاني عند توقف نشاط التطبيق الصغير (أي عند تحديد تطبيق آخر أو إيقاف التشغيل أو إعادة التعيين ، إلخ). وتجدر الإشارة إلى أنه على الرغم من محو محتويات الصفيف (أي أن جميع الأصفار أو الكاذبة مكتوبة هناك) ، فإن الصفيف نفسه يبقى ، ويمكن ، على سبيل المثال ، تخزينه في حقل بيانات الكائن.

ما يتم حفظه في NVM:
  • جميع الكائنات وحقول البيانات الخاصة بها.
  • جميع المصفوفات.
  • محتويات المصفوفات التي تم إنشاؤها بواسطة عامل التشغيل الجديد.

ما يتم تخزينه في ذاكرة الوصول العشوائي (CLEAR_ON_RESET أو CLEAR_ON_DESELECT):
  • , JCSystem.makeTransient<>Array. , , , JCSystem.makeTransientObjectArray(), NVM. RAM.
  • Global Arrays: (APDU Install Parameters ), Global Arrays, JCSystem.makeGlobalArray().
  • . .


يجب على التطبيق ، كقاعدة عامة ، إنشاء جميع العناصر والمصفوفات التي يحتاجها أثناء التثبيت ، وليس بشكل ديناميكي. والسبب في ذلك هو عاملين رئيسيين:

1) الرغبة في التأكد من أنه عند التثبيت الناجح للتطبيق ، لن يتوقف عن العمل إذا كان هناك تطبيق آخر يأخذ كل الذاكرة المجانية.
2) جامع القمامة - وظيفة اختيارية (وإن كانت شائعة جدًا). هذا يعني أنه عند إنشاء كائنات ديناميكيًا ، هناك خطر من عدم حذف الكائنات التي تم إنشاؤها أبدًا. بمرور الوقت ، سيؤدي هذا إلى نقص في الذاكرة الخالية. حتى إذا كان هناك جامع القمامة ، فإن هذا الإجراء لا يحدث تلقائيًا ، ولكن بناءً على طلب التطبيق (JCSystem.requestObjectDeletion ()).

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

ومن الجدير بالذكر دور كائن APDU. يتم مسح المخزن المؤقت الموجود في ذاكرة الوصول العشوائي قبل تلقي كل أمر. من المعتاد استخدامه ليس فقط لتشكيل إجابة ، ولكن غالبًا حتى كمخزن مؤقت. يبلغ حجمها 256 بايت على الأقل أو أكبر بكثير إذا كانت البطاقة تدعم Extended Length.

تطبيق صغير لجدار الحماية


ميزة مهمة في JavaCard يمكن أن تربك المبرمجين هي وجود ما يسمى بجدار حماية التطبيق الصغير. الهدف من جدار الحماية هو منع أي تطبيق صغير من الوصول إلى بيانات أخرى. يجب أن أقول على الفور أن JavaCard تسمح بالاتصال بين التطبيقات التي تستخدم واجهات Shareable ، وكذلك أن الحزم هي مكتبات من الفئات والوظائف التي يمكن استخدامها في تطبيقات مختلفة. هذا هو السبب في الحاجة إلى جدار حماية. المبادئ الأساسية لجدار حماية التطبيق الصغير هي كما يلي:

  • ينتمي كل تطبيق إلى سياق واحد. تنتمي جميع التطبيقات من نفس الحزمة إلى نفس السياق.
  • ينتمي كل كائن إلى تطبيق أو نظام واحد.
  • حزمة بدون تطبيقات (مكتبة) ليس لها سياق. تنتمي الكائنات من فئاتها إلى التطبيق الذي أنشأها.
  • يوجد دائمًا سياق نشط واحد في النظام.
  • (/ ) , .
  • .
  • . . , , firewall.
  • CLEAR_ON_DESELECT , .

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

يمكن للتطبيق أيضًا الوصول إلى بعض الكائنات التي تنتمي إلى النظام. تسمى هذه الأشياء نقاط الدخول. هناك نوعان من نقاط الدخول: مؤقتة ودائمة. نقاط الدخول الدائمة بسيطة ، ويسمح بالوصول إليها من أي سياق. مثال على ذلك هي كائنات من فئة AID. من ناحية أخرى ، فإن نقاط الدخول المؤقتة لها قيود تمنعها من التخزين في حقول بيانات الكائن أو الحقول الثابتة للفئة. مثال على نقطة إدخال مؤقتة هو كائن APDU.

بدءًا من JavaCard 3.0.4 ، من الممكن أيضًا إنشاء مصفوفات عمومية باستخدام طريقة JCSystem.makeGlobalArray (). سلوكهم هو بالضبط نفس سلوك نقاط الدخول المؤقتة. وهي مطلوبة بشكل أساسي كمعلمة لطرق تسمى استخدام تقنية واجهة قابلة للمشاركة.

الذرية والمعاملات


يضمن JavaCard العمليات الذرية عند تغيير حقول البيانات الخاصة بالكائنات أو الفئات. يتم توفير الذرية أيضًا من خلال طرق تعمل على المصفوفات (باستثناء تلك التي تحتوي على اللاحقة غير الذرية في الاسم). هذا يعني ، على سبيل المثال ، أن Util.arrayCopy سينسخ كل وحدات البايت (في حالة نجاحها) ، أو يترك الصفيف دون تغيير في حالة حدوث خطأ أو فقدان للطاقة.

إذا كنت بحاجة إلى إجراء تغيير في العديد من الحقول والمصفوفات الثابتة في عملية ذرية واحدة ، فإن JavaCard توفر أيضًا وظيفة JCSystem.beginTransaction () لبدء المعاملة و JCSystem.commitTransaction () لإكمالها. جميع التغييرات التي تحدث في المصفوفات والحقول الثابتة بين الاستدعاءات إلى JCSystem.beginTransaction () و JCSystem.commitTransaction () ستصبح تلقائيًا جزءًا من المعاملة. إذا تم إلغاء المعاملة بسبب خطأ أو فقدان للطاقة أو استدعاء لأسلوب JCSystem.abortTransaction () ، سيستعيد النظام الحالة الأصلية. تجدر الإشارة إلى أن التنفيذ الفني للمعاملة يستخدم مخزن مؤقت إضافي للنظام. إذا كان المخزن المؤقت ممتلئًا ، فإن النظام يعطي خطأ TransactionException.

رمي


تدعم JavaCard تقنية RMI (استدعاء Metod عن بعد). في هذه المقالة لن أخصص هذه التكنولوجيا. يمكنني فقط القول أن هذه الوظيفة ليست شائعة ، والعديد من البطاقات لا تدعمها.

API


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

قيود JavaCard الرئيسية مقارنة بـ Java


لغة برمجة تطبيق JavaCard هي Java. تقريبا جافا. لذلك ، لا يتم دعم الأنواع char و float و double و long و enum. النوع int اختياري للبطاقات (عادة ما تدعمها البطاقات الحديثة) واستخدامه ، إذا لم يتم تنشيطه بواسطة الخيار المقابل ، سيؤدي إلى حدوث خطأ عند تحويل التطبيق إلى ملف CAP. نسيان ، مكرر و لامدا. يدعم المحول الإصدارات العامة والاستيراد الثابت والتعليقات التوضيحية (فقط Runtime Invisible) منذ الإصدار 3.0.0 ، لا تؤثر على تنفيذ التعليمات البرمجية.

لتجميع الكود ، يتم استخدام مترجم JDK عادي. ستكون أخطاء عدم التوافق ملحوظة فقط عند التحويل إلى ملف CAP أو عند استخدام IDE الذكي لـ JavaCard.

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

هناك قيود أخرى في تهيئة الحقول الثابتة ، وهي أنه لا يمكن تهيئتها إلا مع الثوابت والمصفوفات التي تحتوي على ثوابت ، ولكن ليس مع الكائنات.

استنتاج


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

Source: https://habr.com/ru/post/ar380543/


All Articles