Kako čitati PEM datoteku za dobivanje javnih i privatnih ključeva

Java Top

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ

1. Pregled

U kriptografiji s javnim ključem (poznata i kao asimetrična kriptografija), mehanizam šifriranja oslanja se na dva povezana ključa, javni i privatni ključ. Javni ključ koristi se za šifriranje poruke, dok samo vlasnik privatnog ključa može dešifrirati poruku.

U ovom uputstvu vidjet ćemo kako čitati javne i privatne ključeve iz PEM datoteke.

Prvo ćemo proučiti neke važne koncepte oko kriptografije javnog ključa. Zatim ćemo naučiti čitati PEM datoteke koristeći čistu Javu.

Na kraju ćemo istražiti knjižnicu BouncyCastle kao alternativni pristup.

2. Pojmovi

Prije nego što započnemo, shvatimo neke ključne pojmove.

X.509 je standard koji definira format certifikata javnih ključeva. Dakle, ovaj format među ostalim informacijama opisuje i javni ključ.

DER najpopularniji je format kodiranja za pohranu podataka poput certifikata X.509, privatnih ključeva PKCS8 u datoteke. To je binarno kodiranje i rezultirajući sadržaj ne može se gledati pomoću uređivača teksta.

PKCS8 je standardna sintaksa za pohranu podataka privatnog ključa. Privatni ključ može se prema želji šifrirati pomoću simetričnog algoritma.

Ovim se standardom ne mogu upravljati samo RSA privatnim ključevima, već i drugim algoritmima. Privatni ključevi PKCS8 obično se zamjenjuju putem formata PEM kodiranja.

PEM je mehanizam kodiranja base-64 DER certifikata. PEM također može kodirati druge vrste podataka poput javnih / privatnih ključeva i zahtjeva za certifikatom.

PEM datoteka također sadrži zaglavlje i podnožje koje opisuje vrstu kodiranih podataka:

----- POČNITE JAVNI KLJUČ ----- ... Base64 kodiranje DER kodiranog certifikata ... ----- ZAVRŠITE JAVNI KLJUČ -----

3. Korištenje čiste Jave

3.1. Pročitajte PEM podatke iz datoteke

Počnimo s čitanjem PEM datoteke i spremanjem njenog sadržaja u niz:

Ključ niza = novi niz (Files.readAllBytes (file.toPath ()), Charset.defaultCharset ());

3.2. Nabavite javni ključ iz PEM niza

Izgradit ćemo korisnu metodu koja dobiva javni ključ iz PEM kodiranog niza:

----- ----- početi javni ključ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjtGIk8SxD + OEiBpP2 / T + JUAF0upwuKGMk6wH8Rwov88VvzJrVm2NCticTk5FUg UG5r8JArrV4tJPRHQyvqK wF4NiksuvOjv3HyIf4oaOhZjT8hDne1Bfv + cFqZJ61Gk0MjANh / T5q9vxER / 7TdU NHKpoRV + NVlKN5bEU / NQ5FQjVXicfswxh6Y6fl2PIFqT2CfjD + FkBPU1iT9qyJYH A38IRvwNtcitFgCeZwdGPoxiPPh1WHY8VxpUVBv / 2JsUtrB / rAIbGqZoxAIWvijJ Pe9o1TY3VlOzk9ASZ1AeatvOir + iDVJ5OpKmLnzc46QgGPUsjIyo6Sje9dxpGtoG QQIDAQAB ----- END JAVNI KLJUČ -----

Pretpostavimo da primimo Datoteka kao parametar:

javni statični RSAPublicKey readPublicKey (datoteka datoteke) baca iznimku {String key = new String (Files.readAllBytes (file.toPath ()), Charset.defaultCharset ()); Niz publicKeyPEM = key .replace ("----- POČNI JAVNI KLJUČ -----", "") .replaceAll (System.lineSeparator (), "") .replace ("----- KRAJ JAVNOG KLJUČA ----- "," "); bajt [] kodiran = Base64.decodeBase64 (publicKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance ("RSA"); X509EncodedKeySpec keySpec = novi X509EncodedKeySpec (kodiran); return (RSAPublicKey) keyFactory.generatePublic (keySpec); }

Kao što vidimo, prvo moramo ukloniti zaglavlje, podnožje i nove retke. Zatim, moramo dekodirati niz kodiran s Base64 u odgovarajući binarni format.

Dalje, moramo učitati rezultat u klasu specifikacija ključa koja može obrađivati ​​materijal javnog ključa. U našem ćemo slučaju koristiti X509EncodedKeySpec razred.

Napokon, iz specifikacije možemo generirati objekt javnog ključa pomoću Ključna tvornica razred.

3.3. Nabavite privatni ključ iz PEM niza

Sad kad znamo čitati javni ključ, algoritam za čitanje privatnog ključa vrlo je sličan.

Upotrijebit ćemo PEM kodiran privatni ključ u PKCS8 formatu. Pogledajmo kako izgledaju zaglavlje i podnožje:

----- POČNITE PRIVATNI KLJUČ ----- ... Ključ kodiran u Base64 ... ----- ZAVRŠITE PRIVATNI KLJUČ -----

Kao što smo prethodno naučili, potreban nam je razred koji može obraditi ključni materijal PKCS8. The PKCS8EncodedKeySpec razred ispunjava tu ulogu.

Pa, pogledajmo algoritam:

javni RSAPrivateKey readPrivateKey (datoteka datoteke) baca iznimku {String key = new String (Files.readAllBytes (file.toPath ()), Charset.defaultCharset ()); Niz privateKeyPEM = key .replace ("----- POČINI PRIVATNI KLJUČ -----", "") .replaceAll (System.lineSeparator (), "") .replace ("----- ZAVRŠI PRIVATNI KLJUČ ----- "," "); bajt [] kodiran = Base64.decodeBase64 (privateKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance ("RSA"); PKCS8EncodedKeySpec keySpec = novi PKCS8EncodedKeySpec (kodiran); return (RSAPrivateKey) keyFactory.generatePrivate (keySpec); }

4. Korištenje knjižnice BouncyCastle

4.1. Pročitajte javni ključ

Istražit ćemo knjižnicu BouncyCastle i vidjeti kako se ona može koristiti kao alternativa čistoj implementaciji Jave.

Uzmimo javni ključ:

javni RSAPublicKey readPublicKey (datoteka datoteke) baca iznimku {KeyFactory factory = KeyFactory.getInstance ("RSA"); probajte (FileReader keyReader = novi FileReader (datoteka); PemReader pemReader = novi PemReader (keyReader)) {PemObject pemObject = pemReader.readPemObject (); bajt [] sadržaj = pemObject.getContent (); X509EncodedKeySpec pubKeySpec = novo X509EncodedKeySpec (sadržaj); return (RSAPublicKey) factory.generatePublic (pubKeySpec); }}

Postoji nekoliko važnih klasa kojih moramo biti svjesni kada koristimo BouncyCastle:

  • PemReader - traje a Čitač kao parametar i raščlanjuje njegov sadržaj. Uklanja nepotrebna zaglavlja i dekodira osnovne Base64 PEM podatke u binarni format.
  • PemObject pohranjuje rezultat generiran PemReader.

Štoviše, pogledajmo još jedan pristup koji obavija Java klase (X509EncodedKeySpec, KeyFactory) u vlastiti razred BouncyCastlea (JcaPEMKeyConverter):

javni RSAPublicKey readPublicKeySecondApproach (datoteka datoteke) baca IOException {try (FileReader keyReader = novi FileReader (datoteka)) {PEMParser pemParser = novi PEMParser (keyReader); JcaPEMKeyConverter pretvarač = novi JcaPEMKeyConverter (); SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance (pemParser.readObject ()); return (RSAPublicKey) converter.getPublicKey (publicKeyInfo); }}

4.2. Pročitajte privatni ključ

Vidjet ćemo dva primjera koja su vrlo slična onima prikazanim gore.

U prvom primjeru samo trebamo zamijeniti X509EncodedKeySpec razred s PKCS8EncodedKeySpec razred i vratiti an RSAPrivateKey objekt umjesto RSAPublicKey:

javni RSAPrivateKey readPrivateKey (datoteka datoteke) baca iznimku {KeyFactory factory = KeyFactory.getInstance ("RSA"); probajte (FileReader keyReader = novi FileReader (datoteka); PemReader pemReader = novi PemReader (keyReader)) {PemObject pemObject = pemReader.readPemObject (); bajt [] sadržaj = pemObject.getContent (); PKCS8EncodedKeySpec privKeySpec = novi PKCS8EncodedKeySpec (sadržaj); return (RSAPrivateKey) factory.generatePrivate (privKeySpec); }}

Sada, preradimo malo drugi pristup iz prethodnog odjeljka kako bismo pročitali privatni ključ:

javni RSAPrivateKey readPrivateKeySecondApproach (datoteka datoteke) baca IOException {try (FileReader keyReader = novi FileReader (datoteka)) {PEMParser pemParser = novi PEMParser (keyReader); JcaPEMKeyConverter pretvarač = novi JcaPEMKeyConverter (); PrivateKeyInfo privateKeyInfo = PrivateKeyInfo.getInstance (pemParser.readObject ()); return (RSAPrivateKey) converter.getPrivateKey (privateKeyInfo); }}

Kao što vidimo, samo smo zamijenili SubjectPublicKeyInfo s PrivateKeyInfo i RSAPublicKey s RSAPrivateKey.

4.3. Prednosti

Postoji nekoliko prednosti koje nudi knjižnica BouncyCastle.

Jedna od prednosti je ta ne trebamo ručno preskakati ili uklanjati zaglavlje i podnožje. Još jedno je to nismo odgovorni za dekodiranje Base64 ili. Stoga pomoću BouncyCastle možemo napisati manje kôda sklonih pogreškama.

Štoviše, Biblioteka BouncyCastle podržava format PKCS1 također. Unatoč činjenici da je PKCS1 također popularan format koji se koristi za pohranu kriptografskih ključeva (samo RSA ključevi), Java ga ne podržava samostalno.

5. Zaključak

U ovom smo članku naučili kako čitati javne i privatne ključeve iz PEM datoteka.

Prvo smo proučavali nekoliko ključnih pojmova oko kriptografije s javnim ključem. Zatim smo vidjeli kako čitati javne i privatne ključeve koristeći čistu Javu.

Na kraju, istražili smo knjižnicu BouncyCastle i saznali da je to dobra alternativa jer pruža nekoliko prednosti u usporedbi s čistom Java implementacijom.

Potpuni izvorni kod za Java i BouncyCastle pristupe dostupan je na GitHubu.

Dno Java

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ