التشفير في جافا. الطبقة الشفرات

مرحبا يا هبر! أقدم إليكم ترجمة المقال الثاني "Java Cipher" لجاكوب جينكوف من سلسلة من المقالات للمبتدئين الذين يرغبون في تعلم أساسيات التشفير في جافا.


جدول المحتويات:


  1. التشفير
  2. صفر
  3. MessageDigest
  4. ماك
  5. توقيع
  6. KeyPair
  7. KeyGenerator
  8. KeyPairGenerator
  9. تخزين المفاتيح
  10. Keytool
  11. شهادة
  12. CertificateFactory
  13. CertPath

جافا تشفير (تشفير)


فئة Java Cipher ( javax.crypto.Cipher ) هي خوارزمية تشفير. المصطلح "تشفير" هو مصطلح قياسي لخوارزمية تشفير في عالم التشفير. هذا هو السبب في أن فئة Java تسمى Cipher ، وليس Encryptor / Decryptor أو أي شيء آخر. يمكنك استخدام مثيل Cipher لتشفير وفك تشفير البيانات في Java. يشرح هذا الفصل كيفية عمل فئة التشفير.


إنشاء الشفرات


قبل استخدام تشفير ، يجب إنشاء مثيل لفئة Cipher عن طريق استدعاء الأسلوب getInstance () الخاص به مع معلمة تشير إلى نوع خوارزمية التشفير التي تريد استخدامها. فيما يلي مثال على إنشاء مثيل Java Cipher:


Cipher cipher = Cipher.getInstance("AES"); 

ينشئ هذا المثال مثيل Cipher باستخدام خوارزمية تشفير AES.


أوضاع التشفير


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


  • EBC - الكود الإلكتروني ( وضع الكود الإلكتروني)
  • CBC - تشفير بلوك التسلسل
  • CFB - ملاحظات التشفير ( وضع ملاحظات التشفير)
  • OFB - ردود الفعل الإخراج
  • نسبة النقر إلى الظهور - عداد ( وضع العداد)

عند إنشاء مثيل للشفرة ، يمكنك إضافة وضعه إلى اسم خوارزمية التشفير. يمكنك إنشاء مثيل تشفير AES باستخدام وضع اقتران الكتلة - Cipher Block Chaining (CBC) ، كما يلي:


 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

نظرًا لأن وضع اقتران كتل التشفير يتطلب أيضًا "مخطط الحشو" ، تتم إضافة مخطط الحشو ( PKCS5Padding ) إلى نهاية سلسلة اسم خوارزمية التشفير.
من المهم معرفة أن خوارزميات وأوضاع التشفير ليست كلها مدعومة افتراضيًا بواسطة موفر تشفير Java SDK. لإنشاء مثيل التشفير الذي تحتاجه مع الوضع المطلوب ونمط التعبئة ، قد تحتاج إلى تثبيت موفر جهة خارجية ، مثل Bouncy Castle.


تهيئة التشفير


قبل استخدام مثيل Cipher ، يجب تهيئته. تتم تهيئة التشفير عن طريق استدعاء الأسلوب init () الخاص به . تأخذ طريقة init () معلمتين:


  • نظام الحكم
  • مفتاح

مثال على تهيئة مثيل تشفير في وضع التشفير:


 Key key = ... // /    cipher.init(Cipher.ENCRYPT_MODE, key); 

فيما يلي مثال على تهيئة مثيل تشفير بالفعل في وضع فك التشفير:


 Key key = ... ///    cipher.init(Cipher.DECRYPT_MODE, key); 

تشفير البيانات وفك التشفير


لتشفير البيانات أو فك تشفيرها باستخدام مثيل Cipher ، تسمى إحدى الطريقتين التاليتين:


  • update()
  • doFinal()

هناك العديد من الإصدارات المتجاوزة من أساليب التحديث () و doFinal () التي تأخذ معلمات مختلفة. النظر في الأكثر استخداما هنا. إذا كنت بحاجة إلى تشفير أو فك تشفير كتلة واحدة من البيانات ، ما عليك سوى استدعاء doFinal () مع البيانات لتشفير أو فك تشفير. مثال:


 byte[] plainText = "abcdefghijklmnopqrstuvwxyz".getBytes("UTF-8"); byte[] cipherText = cipher.doFinal(plainText); 

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


 byte[] plainText = cipher.doFinal(cipherText); 

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


 byte[] data1 = "abcdefghijklmnopqrstuvwxyz".getBytes("UTF-8"); byte[] data2 = "zyxwvutsrqponmlkjihgfedcba".getBytes("UTF-8"); byte[] data3 = "01234567890123456789012345".getBytes("UTF-8"); byte[] cipherText1 = cipher.update(data1); byte[] cipherText2 = cipher.update(data2); byte[] cipherText3 = cipher.doFinal(data3); 

سبب الحاجة إلى استدعاء doFinal () لآخر كتلة بيانات هو أن بعض خوارزميات التشفير تحتاج إلى استكمال البيانات لتناسب حجم كتلة تشفير معين (على سبيل المثال ، حد 8 بايت). ليس من الضروري استكمال البيانات المشفرة الوسيطة. لذلك ، يتم استدعاء أسلوب التحديث () لكتل البيانات الوسيطة ويتم استدعاء استدعاء doFinal () لآخر كتلة بيانات.
عند فك تشفير كتل بيانات متعددة ، يمكنك أيضًا استدعاء أسلوب التحديث () لكتل البيانات الوسيطة وطريقة doFinal () للكتلة الأخيرة. مثال على فك تشفير العديد من كتل البيانات:


 byte[] plainText1 = cipher.update(cipherText1); byte[] plainText2 = cipher.update(cipherText2); byte[] plainText3 = cipher.doFinal(cipherText3); 

مرة أخرى ، يجب تهيئة مثيل التشفير في وضع فك التشفير حتى يعمل هذا المثال.


تشفير / فك تشفير جزء من صفيف بايت


يمكن لطرق التشفير وفك التشفير لفئة التشفير تشفير أو فك تشفير بعض البيانات المخزنة في صفيف بايت. يحتاج أسلوب التحديث () و / أو doFinal () إلى تمرير الإزاحة والطول.


 int offset = 10; int length = 24; byte[] cipherText = cipher.doFinal(data, offset, length); 

في هذا المثال ، سيتم تشفير البايتات من الفهرس 10 و 24 بايت للأمام (أو فك تشفيرها ، اعتمادًا على تهيئة التشفير).


تشفير / فك تشفير إلى صفيف بايت موجود


ترجع جميع أمثلة التشفير وفك التشفير في هذا الفصل البيانات المشفرة أو المشفرة في صفيف بايت جديد. ومع ذلك ، من الممكن أيضًا تشفير البيانات أو فك تشفيرها في صفيف بايت موجود. قد يكون ذلك مفيدًا لتقليل عدد صفائف البايت التي تم إنشاؤها. للقيام بذلك ، قم بتمرير صفيف بايت الهدف كمعلمة إلى أسلوب التحديث () و / أو doFinal () .


 int offset = 10; int length = 24; byte[] dest = new byte[1024]; cipher.doFinal(data, offset, length, dest); 

في هذا المثال ، يتم تشفير البيانات من 10 فهرس 24 بايت إلى الأمام إلى صفيف البايت dest مع الإزاحة 0. إذا كنت ترغب في تعيين إزاحة مختلفة لصفيف البايت dest ، فهناك إصدارات (() و doFinal () تقبلان معلمة إزاحة إضافية. مثال على استدعاء الأسلوب doFinal () مع إزاحة في مجموعة dest:


 int offset = 10; int length = 24; byte[] dest = new byte[1024]; int destOffset = 12 cipher.doFinal(data, offset, length, dest, destOffset); 

إعادة استخدام مثيل من التشفير


تهيئة مثيل Cipher هي عملية مكلفة وإعادة استخدام مثيلات Cipher فكرة جيدة. لحسن الحظ ، تم تصميم فئة التشفير مع إعادة الاستخدام في الاعتبار. عند استدعاء الأسلوب doFinal () في مثيل التشفير ، فإنه يعود إلى الحالة التي كان عليها مباشرة بعد التهيئة. يمكن بعد ذلك استخدام مثيل التشفير لتشفير أو فك تشفير المزيد من البيانات.


مثال على إعادة استخدام مثيل Java Cipher:


 Cipher cipher = Cipher.getInstance("AES"); Key key = ... ///    cipher.init(Cipher.ENCRYPT_MODE, key); byte[] data1 = "abcdefghijklmnopqrstuvwxyz".getBytes("UTF-8"); byte[] data2 = "zyxwvutsrqponmlkjihgfedcba".getBytes("UTF-8"); byte[] cipherText1 = cipher.update(data1); byte[] cipherText2 = cipher.doFinal(data2); byte[] data3 = "01234567890123456789012345".getBytes("UTF-8"); byte[] cipherText3 = cipher.doFinal(data3); 

أولاً ، يتم إنشاء مثيل Cipher وتهيئته ، ثم استخدامه لتشفير كتلتين من البيانات المتسقة. لاحظ استدعاء التحديث () ثم doFinal () لكتل البيانات هذه. بعد ذلك ، يمكن استخدام مثيل التشفير مرة أخرى لتشفير البيانات. يتم ذلك عن طريق استدعاء doFinal () مع كتلة بيانات ثالثة. بعد هذه الدعوة إلى doFinal () ، يمكنك تشفير كتلة أخرى من البيانات بنفس مثيل Java Cipher.

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


All Articles