כיצד לקרוא קובץ PEM כדי לקבל מפתחות ציבוריים ופרטיים

ג'אווה טופ

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

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

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

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

במדריך זה, נראה כיצד לקרוא מפתחות ציבוריים ופרטיים מקובץ PEM.

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

לבסוף, נחקור את ספריית BouncyCastle כגישה חלופית.

2. מושגים

לפני שנתחיל, בואו נבין כמה מושגי מפתח.

X.509 הוא תקן המגדיר את הפורמט של אישורי מפתח ציבורי. לכן, פורמט זה מתאר מפתח ציבורי בין מידע אחר.

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

PKCS8 הוא תחביר סטנדרטי לאחסון מידע על מפתח פרטי. ניתן להצפין את המפתח הפרטי באמצעות אלגוריתם סימטרי.

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

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

קובץ PEM מכיל גם כותרת עליונה וכותרת תחתונה המתארת ​​את סוג הנתונים המקודדים:

----- התחל מפתח ציבורי ----- ... קידוד Base64 של האישור המקודד של DER ... ----- END PUBLIC KEY -----

3. שימוש ב- Java טהור

3.1. קרא נתוני PEM מקובץ

נתחיל בקריאת קובץ ה- PEM ונשמור את תוכנו במחרוזת:

מפתח מחרוזת = מחרוזת חדשה (Files.readAllBytes (file.toPath ()), Charset.defaultCharset ());

3.2. קבל מפתח ציבורי ממחרוזת PEM

אנו הולכים לבנות שיטת שירות שתקבל את המפתח הציבורי ממחרוזת ה- PEM המקודדת:

----- BEGIN מפתח ציבורי ----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjtGIk8SxD + OEiBpP2 / T JUAF0upwuKGMk6wH8Rwov88VvzJrVm2NCticTk5FUg + UG5r8JArrV4tJPRHQyvqK wF4NiksuvOjv3HyIf4oaOhZjT8hDne1Bfv + cFqZJ61Gk0MjANh / T5q9vxER / 7TdU NHKpoRV + NVlKN5bEU / NQ5FQjVXicfswxh6Y6fl2PIFqT2CfjD + FkBPU1iT9qyJYH A38IRvwNtcitFgCeZwdGPoxiPPh1WHY8VxpUVBv / 2JsUtrB / rAIbGqZoxAIWvijJ Pe9o1TY3VlOzk9ASZ1AeatvOir + iDVJ5OpKmLnzc46QgGPUsjIyo6Sje9dxpGtoG QQIDAQAB ----- סיום מפתח ציבורי-----

נניח שנקבל א קוֹבֶץ כפרמטר:

RSAPublicKey סטטי ציבורי readPublicKey (קובץ קובץ) זורק חריג {מפתח מחרוזת = מחרוזת חדשה (Files.readAllBytes (file.toPath ()), Charset.defaultCharset ()); מחרוזת publicKeyPEM = מפתח .replace ("----- BEGIN PUBLIC KEY -----", "") .replaceAll (System.lineSeparator (), "") .replace ("----- END PUBLIC KEY ----- "," "); בייט [] מקודד = Base64.decodeBase64 (publicKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance ("RSA"); X509EncodedKeySpec keySpec = X509EncodedKeySpec חדש (מקודד); החזר (RSAPublicKey) keyFactory.generatePublic (keySpec); }

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

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

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

3.3. קבל מפתח פרטי ממחרוזת PEM

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

אנו נשתמש במפתח פרטי מקודד PEM בפורמט PKCS8. בואו נראה איך נראים הכותרת העליונה וכותרת התחתונה:

----- התחל מפתח פרטי ----- ... מפתח מקודד Base64 ... ----- סיים מפתח פרטי -----

כפי שלמדנו בעבר, אנו זקוקים לכיתה המסוגלת להתמודד עם חומרי מפתח PKCS8. ה PKCS8EncodedKeySpec הכיתה ממלאת את התפקיד הזה.

אז בואו נראה את האלגוריתם:

ציבורי RSAPrivateKey readPrivateKey (קובץ קובץ) זורק חריג {String key = new String (Files.readAllBytes (file.toPath ()), Charset.defaultCharset ()); מחרוזת privateKeyPEM = key .replace ("----- BEGIN PRIVATE KEY -----", "") .replaceAll (System.lineSeparator (), "") .replace ("----- END PRIVATE KEY ----- "," "); בייט [] מקודד = Base64.decodeBase64 (privateKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance ("RSA"); PKCS8EncodedKeySpec keySpec = PKCS8EncodedKeySpec חדש (מקודד); return (RSAPrivateKey) keyFactory.generatePrivate (keySpec); }

4. שימוש בספריית BouncyCastle

4.1. קרא מפתח ציבורי

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

בואו נקבל את המפתח הציבורי:

ציבורי RSAPublicKey readPublicKey (קובץ קובץ) זורק חריג {KeyFactory factory = KeyFactory.getInstance ("RSA"); נסה (FileReader keyReader = FileReader חדש (קובץ); PemReader pemReader = PemReader חדש (keyReader)) {PemObject pemObject = pemReader.readPemObject (); בייט [] תוכן = pemObject.getContent (); X509EncodedKeySpec pubKeySpec = X509EncodedKeySpec חדש (תוכן); return (RSAPublicKey) factory.generatePublic (pubKeySpec); }}

ישנם כמה שיעורים חשובים שעלינו להיות מודעים אליהם בעת השימוש ב- BouncyCastle:

  • PemReader - לוקח קוֹרֵא כפרמטר ומנתח את תוכנו. זה מסיר את הכותרות המיותרות ו מפענח את נתוני Base64 PEM הבסיסיים לפורמט בינארי.
  • PemObject מאחסן את התוצאה שנוצרה על ידי PemReader.

יתר על כן, בואו נראה גישה אחרת שעוטפת את שיעורי Java (X509EncodedKeySpec, KeyFactory) לשיעור עצמו של BouncyCastle (JcaPEMKeyConverter):

ציבורי RSAPublicKey readPublicKeySecondApproach (קובץ קובץ) זורק IOException {try (FileReader keyReader = FileReader חדש (קובץ)) {PEMParser pemParser = PEMParser חדש (keyReader); ממיר JcaPEMKeyConverter = חדש JcaPEMKeyConverter (); SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance (pemParser.readObject ()); return (RSAPublicKey) converter.getPublicKey (publicKeyInfo); }}

4.2. קרא מפתח פרטי

אנו נראה שתי דוגמאות הדומות מאוד לאלו שהוצגו לעיל.

בדוגמה הראשונה, אנחנו רק צריכים להחליף את ה- X509EncodedKeySpec שיעור עם PKCS8EncodedKeySpec כיתה והחזרת RSAPrivateKey חפץ במקום RSAPublicKey:

ציבורי RSAPrivateKey readPrivateKey (קובץ קובץ) זורק חריג {KeyFactory factory = KeyFactory.getInstance ("RSA"); נסה (FileReader keyReader = FileReader חדש (קובץ); PemReader pemReader = PemReader חדש (keyReader)) {PemObject pemObject = pemReader.readPemObject (); בייט [] תוכן = pemObject.getContent (); PKCS8EncodedKeySpec privKeySpec = PKCS8EncodedKeySpec חדש (תוכן); return (RSAPrivateKey) factory.generatePrivate (privKeySpec); }}

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

ציבורי RSAPrivateKey readPrivateKeySecondApproach (קובץ קובץ) זורק IOException {try (FileReader keyReader = FileReader חדש (קובץ)) {PEMParser pemParser = PEMParser חדש (keyReader); ממיר JcaPEMKeyConverter = חדש JcaPEMKeyConverter (); PrivateKeyInfo privateKeyInfo = PrivateKeyInfo.getInstance (pemParser.readObject ()); convert (RSAPrivateKey) converter.getPrivateKey (privateKeyInfo); }}

כפי שאנו רואים, פשוט החלפנו SubjectPublicKeyInfo עם PrivateKeyInfo ו RSAPublicKey עם RSAPrivateKey.

4.3. יתרונות

ישנם מספר יתרונות המסופקים על ידי ספריית BouncyCastle.

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

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

5. מסקנה

במאמר זה למדנו כיצד לקרוא מפתחות ציבוריים ופרטיים מקבצי PEM.

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

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

קוד המקור המלא לגישות Java ו- BouncyCastle זמין ב- GitHub.

תחתית Java

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

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