הצפנה ופענוח קבצים ב- Java

ג'אווה טופ

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:

>> בדוק את הקורס

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

במדריך זה נבחן כיצד להצפין ולפענח קובץ באמצעות ממשקי API קיימים של JDK.

2. כתיבת מבחן ראשונה

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

מכיוון שאנו משתמשים רק בפונקציונליות קיימת של JDK, אין צורך בתלות חיצונית.

ראשון, אנו נצפין את התוכן באמצעות מפתח סודי שנוצר לאחרונה (אנו משתמשים ב- AES, Advanced Encryption Standard, כאלגוריתם ההצפנה הסימטרי בדוגמה זו).

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

נניח שֶׁלָנוּ FileEncrypterDecrypter class יכתוב את הפלט לקובץ שנקרא baz.enc. לאחר מכן, אנו מפענחים קובץ זה באמצעות אותו מפתח סודי ובדוק שהתוכן המפענח שווה לתוכן המקורי:

@Test הציבור בטל כאשר EncryptingIntoFile_andDecryptingFileAgain_thenOriginalStringIsReturned () {String originalContent = "foobar"; SecretKey secretKey = KeyGenerator.getInstance ("AES"). CreateKey (); FileEncrypterDecrypter fileEncrypterDecrypter = FileEncrypterDecrypter חדש (secretKey, "AES / CBC / PKCS5Padding"); fileEncrypterDecrypter.encrypt (originalContent, "baz.enc"); מחרוזת decryptedContent = fileEncrypterDecrypter.decrypt ("baz.enc"); assertThat (decryptedContent, is (originalContent)); קובץ חדש ("baz.enc"). delete (); // לנקות }

3. הצפנה

אנו מאותחלים את הצופן בבנאי שלנו FileEncrypterDecrypter בכיתה באמצעות השינוי שצוין חוּט.

זה מאפשר לנו להיכשל מוקדם במקרה שצוין טרנספורמציה שגויה:

FileEncrypterDecrypter (SecretKey secretKey, Transform String) {this.secretKey = secretKey; this.cipher = Cipher.getInstance (טרנספורמציה); }

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

הצפנה בטלה (תוכן מחרוזת, שם מחרוזת) {cipher.init (Cipher.ENCRYPT_MODE, secretKey); בייט [] iv = cipher.getIV (); נסה (FileOutputStream fileOut = FileOutputStream חדש (fileName); CipherOutputStream cipherOut = CipherOutputStream חדש (fileOut, cipher)) {fileOut.write (iv); cipherOut.write (content.getBytes ()); }}

ג'אווה מאפשרת לנו למנף את הנוח CipherOutputStream מחלקה לכתיבת התוכן המוצפן לאחר OutputStream.

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

שימוש ב- IV הוא חובה בעת שימוש במצב CBC, על מנת לאקראי את הפלט המוצפן. אולם הרביעי אינו נחשב סוד, ולכן זה בסדר לכתוב אותו בתחילת הקובץ.

4. פענוח

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

שוב נוכל להשתמש בשיעור Java מיוחד, CipherInputStream, אשר מטפל בשקיפות בפענוח בפועל:

פענוח מחרוזת (String fileName) {מחרוזת תוכן; נסה (FileInputStream fileIn = FileInputStream חדש (fileName)) {בתים [] fileIv = בתים חדשים [16]; fileIn.read (fileIv); cipher.init (Cipher.DECRYPT_MODE, secretKey, IvParameterSpec חדש (fileIv)); נסה (CipherInputStream cipherIn = חדש CipherInputStream (fileIn, cipher); InputStreamReader inputReader = InputStreamReader חדש (cipherIn); BufferedReader reader = new BufferedReader (inputReader)) {StringBuilder sb = StringBuilder חדש (); קו מיתרים; בעוד ((שורה = reader.readLine ())! = null) {sb.append (שורה); } תוכן = sb.toString (); }} להחזיר תוכן; }

5. מסקנה

ראינו שאנחנו יכולים לבצע הצפנה ופענוח בסיסיים באמצעות שיעורי JDK רגילים, כגון צוֹפֶן, CipherOutputStream ו CipherInputStream.

כרגיל, הקוד השלם למאמר זה זמין במאגר GitHub שלנו.

בנוסף, תוכלו למצוא כאן את רשימת הצפנים הזמינים ב- JDK.

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

תחתית Java

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:

>> בדוק את הקורס