מדריך כיתת הצופן

1. סקירה כללית

במילים פשוטות, הצפנה היא תהליך של קידוד הודעה כך שרק משתמשים מורשים יכולים להבין אותה או לגשת אליה.

ההודעה, המכונה טקסט פשוט, מוצפן באמצעות אלגוריתם הצפנה - א צוֹפֶן - מחולל טקסט צופן שניתן לקרוא רק על ידי משתמשים מורשים באמצעות פענוח.

במאמר זה אנו מתארים בפירוט הליבה צוֹפֶן class, המספק פונקציות הצפנה ופענוח הצפנה בג'אווה.

2. כיתת צופן

סיומת הקריפטוגרפיה של Java (JCE) היא ה- חלק מארכיטקטורת הקריפטוגרפיה של Java (JCA) המספק לאפליקציה צופני הצפנה להצפנת נתונים ופענוח, כמו גם לגיבוב נתונים פרטיים.

ה צוֹפֶן בכיתה - ממוקם ב javax.crypto חבילה - מהווה את הליבה של מסגרת JCE, המספקת פונקציונליות להצפנה ופענוח.

2.1. מייצב צופן

לייצר א צוֹפֶן חפץ, אנחנו קוראים לסטטי getInstance שיטה, העברת שם השינוי המבוקש. באופן אופציונלי, ניתן לציין את שם הספק.

בוא נכתוב שיעור לדוגמא הממחיש את האינסטינציה של a צוֹפֶן:

Class class Encryptor {byte [] encryptMessage ציבורי (הודעה בתא [], בייט [] keyBytes) זורק InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5Padding"); // ...}}

השינוי AES / ECB / PKCS5Padding אומר ל getInstance שיטה להסדיר את צוֹפֶן אובייקט כצופן AES עם מצב פעולה של ECB ותכנית ריפוד PKCS5.

אנחנו יכולים גם להסדיר את צוֹפֶן אובייקט על ידי ציון רק האלגוריתם בשינוי:

צופן צופן = Cipher.getInstance ("AES");

במקרה זה, Java תשתמש בערכי ברירת מחדל ספציפיים לספק עבור מצב ומערכת הריפוד.

ציין זאת getInstance יזרוק א NoSuchAlgorithmException אם השינוי הוא ריק, ריק או בפורמט לא חוקי, או אם הספק אינו תומך בכך.

זה יזרוק א NoSuchPaddingException אם השינוי מכיל ערכת ריפוד שאינה נתמכת.

2.2. חוט-בטיחות

ה צוֹפֶן מחלקה היא מדינה סטטית ללא כל סוג של סנכרון פנימי. למען האמת, שיטות כמו init () אוֹ עדכון() ישנה את המצב הפנימי של מסוים צוֹפֶן למשל.

לכן, ה צוֹפֶן הכיתה אינה בטוחה בחוטים. אז עלינו ליצור אחד צוֹפֶן מופע לכל הצפנה / הצפנה.

2.3. מפתחות

ה מַפְתֵחַ ממשק מייצג מפתחות לפעולות הצפנה. מפתחות הם מיכלים אטומים המכילים מפתח מקודד, פורמט קידוד המפתח ואלגוריתם ההצפנה שלו.

מפתחות מתקבלים בדרך כלל באמצעות מחוללי מפתח, אישורים או מפרטי מפתח באמצעות מפעל מפתח.

בואו ניצור סימטריה מַפְתֵחַ מבית המפתח שסופק:

SecretKey secretKey = SecretKeySpec חדש (keyBytes, "AES");

2.4. אתחול צופן

אנו קוראים init () שיטה לאתחול ה- Cipher לְהִתְנַגֵד עם מַפְתֵחַ אוֹ תְעוּדָה ו אופציה המציין את מצב הפעולה של הצופן.

אופציונלי, אנחנו יכולים לעבור במקור של אקראיות. כברירת מחדל, א SecureRandom נעשה שימוש ביישום של הספק המותקן בעדיפות הגבוהה ביותר. אחרת, הוא ישתמש במקור המסופק על ידי המערכת.

אנו יכולים לציין קבוצה של פרמטרים ספציפיים לאלגוריתם באופן אופציונלי. לדוגמא, אנו יכולים להעביר IvParameterSpec ל ציין וקטור אתחול.

להלן מצבי פעולת הצפנה הזמינים:

  • ENCRYPT_MODE: אתחול צוֹפֶן התנגד למצב הצפנה
  • DECRYPT_MODE: אתחול צוֹפֶן התנגד למצב פענוח
  • WRAP_MODE: אתחול צוֹפֶן התנגד למצב גלישת המפתחות
  • UNWRAP_MODE: אתחול צוֹפֶן התנגד למצב ביטול מפתח

בוא נתחיל את צוֹפֶן לְהִתְנַגֵד:

צופן צופן = Cipher.getInstance ("AES / ECB / PKCS5Padding"); SecretKey secretKey = SecretKeySpec חדש (keyBytes, "AES"); cipher.init (Cipher.ENCRYPT_MODE, secretKey); // ...

עכשיו ה init שיטה זורקת InvalidKeyException אם המפתח המסופק אינו מתאים לאתחול הצופן, כמו כאשר אורך / קידוד מפתח אינו תקף.

זה נזרק גם כאשר הצופן דורש פרמטרים מסוימים של אלגוריתם שלא ניתן לקבוע מהמפתח, או אם למפתח יש גודל מפתח העולה על גודל המפתח המרבי המותר (נקבע מתוך קבצי מדיניות השיפוט המוגדרים של JCE).

בואו נסתכל על דוגמא באמצעות תְעוּדָה:

בייט ציבורי [] encryptMessage (הודעה בתא [], תעודת תעודה) זורק InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {Cipher cipher = Cipher.getInstance ("RSA / ECB / PKCS1Padding"); cipher.init (Cipher.ENCRYPT_MODE, תעודה); // ...}

ה צוֹפֶן האובייקט מקבל את המפתח הציבורי להצפנת נתונים מהאישור על ידי קריאה ל- getPublicKey שיטה.

2.5. הצפנה ופענוח

לאחר אתחול ה- צוֹפֶן אובייקט, אנו מכנים doFinal () שיטה לביצוע פעולת ההצפנה או הפענוח. שיטה זו מחזירה מערך בתים המכיל את ההודעה המוצפנת או המוצפנת.

ה doFinal () השיטה מאפסת גם את צוֹפֶן התנגדות למצב בו הייתה כאשר אתחל בעבר באמצעות שיחה init () שיטה, מה שהופך את צוֹפֶן אובייקט זמין להצפנה או לפענוח הודעות נוספות.

בוא נתקשר doFinal בשלנו encryptMessage שיטה:

בתים ציבוריים [] encryptMessage (בתים [] הודעה, בתים [] keyBytes) זורק InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException {צופן צופן = Cipher.getInstance ("AES5 / ECB; SecretKey secretKey = SecretKeySpec חדש (keyBytes, "AES"); cipher.init (Cipher.ENCRYPT_MODE, secretKey); החזר cipher.doFinal (הודעה); }

כדי לבצע פעולת פענוח, אנו משנים את אופציה ל DECRYPT_MODE:

בייט ציבורי [] decryptMessage (בתים [] encryptedMessage, בייט [] keyBytes) זורק NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {Cipher.Cipher = Cipher.getInstance (") SecretKey secretKey = SecretKeySpec חדש (keyBytes, "AES"); cipher.init (Cipher.DECRYPT_MODE, secretKey); החזר cipher.doFinal (encryptedMessage); }

2.6. ספקים

נועד להשתמש בארכיטקטורה מבוססת ספקים, ה- JCE מאפשר לחבר ספריות הצפנה מוסמכות כגון BouncyCastle כספקי אבטחה ואלגוריתמים חדשים להוסיף בצורה חלקה.

עכשיו בואו נוסיף את BouncyCastle כספק אבטחה. אנו יכולים להוסיף ספק אבטחה באופן סטטי או דינמי.

כדי להוסיף את BouncyCastle באופן סטטי, אנו משנים את ה- java.security קוֹבֶץ ממוקם ב / jre / lib / אבטחה תיקיה.

אנו מוסיפים את השורה בסוף הרשימה:

... security.provider.4 = com.sun.net.ssl.internal.ssl.Provider security.provider.5 = com.sun.crypto.provider.SunJCE security.provider.6 = sun.security.jgss.SunProvider security.provider.7 = org.bouncycastle.jce.provider.BouncyCastleProvider

בעת הוספת מאפיין הספק, מפתח הנכס הוא בפורמט אבטחה. ספק איפה המספר נ הוא אחד יותר מהאחרון ברשימה.

אנחנו יכולים גם להוסיף את ספק האבטחה BouncyCastle באופן דינמי מבלי לשנות את קובץ האבטחה:

Security.addProvider (חדש BouncyCastleProvider ());

כעת אנו יכולים לציין את הספק במהלך אתחול הצפנה:

צופן צופן = Cipher.getInstance ("AES / ECB / PKCS5Padding", "BC");

לִפנֵי הַסְפִירָה מציין את BouncyCastle כספק. אנו יכולים להשיג את רשימת הספקים הרשומים באמצעות Security.getProviders () שיטה.

3. בדיקת הצפנה ופענוח

בואו נכתוב מבחן לדוגמא להמחשת הצפנת ופענוח הודעות.

במבחן זה אנו משתמשים באלגוריתם הצפנה AES עם מפתח 128 סיביות וקובעים שהתוצאה המפוענחת שווה לטקסט ההודעה המקורי:

@Test הציבור בטל כאשר IsEncryptedAndDecrypted_thenDecryptedEqualsOriginal () זורק חריג {String encryptionKeyString = "thisisa128bitkey"; String originalMessage = "זו הודעה סודית"; בתים [] encryptionKeyBytes = encryptionKeyString.getBytes (); צופן צופן = Cipher.getInstance ("AES / ECB / PKCS5Padding"); SecretKey secretKey = SecretKeySpec חדש (encryptionKeyBytes, "AES"); cipher.init (Cipher.ENCRYPT_MODE, secretKey); בתים [] encryptedMessageBytes = cipher.doFinal (message.getBytes ()); cipher.init (Cipher.DECRYPT_MODE, secretKey); בתים [] decryptedMessageBytes = cipher.doFinal (encryptedMessageBytes); assertThat (originalMessage) .isEqualTo (מחרוזת חדשה (decryptedMessageBytes)); }

4. מסקנה

במאמר זה דנו ב צוֹפֶן בכיתה והציג דוגמאות לשימוש. פרטים נוספים על צוֹפֶן בכיתה ובמסגרת JCE ניתן למצוא בתיעוד הכיתה ובמדריך ההפניה של Java Cryptography Architecture (JCA).

יישום של כל הדוגמאות וקטעי הקוד יכול להמצא נגמר ב- GitHub. זהו פרויקט מבוסס Maven, כך שיהיה קל לייבא ולהפעיל אותו כפי שהוא.