Java KeyStore API

Java Top

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

1. Áttekintés

Ebben az oktatóanyagban a kriptográfiai kulcsok és tanúsítványok kezelését vizsgáljuk a Java-ban a KeyStore API.

2. Kulcstárak

Ha Java-ban kell kezelnünk a kulcsokat és a tanúsítványokat, akkor a kulcstár, amely egyszerűen egy álnevek biztonságos gyűjteménye bejegyzés kulcsok és tanúsítványok.

A kulcstárakat általában fájlrendszerbe mentjük, és jelszóval megvédhetjük.

Alapértelmezés szerint a Java kulcstárfájlja a következő helyen található: JAVA_HOME /jre/ lib / security / cacerts. Ehhez a kulcstárhoz az alapértelmezett kulcstár jelszóval férhetünk hozzá változtasd meg.

Most, azzal a kis háttérrel, térjünk rá az első létrehozására.

3. Kulcstár létrehozása

3.1. Építkezés

Könnyen létrehozhatunk kulcstárat a kulcstartó használatával, vagy megtehetjük programozottan a KeyStore API:

KeyStore ks = KeyStore.getInstance (KeyStore.getDefaultType ());

Itt az alapértelmezett típust használjuk, bár van néhány kulcstár típus, mint például jceks vagy pcks12.

Az a használatával felülírhatjuk az alapértelmezett „JKS” (egy Oracle saját kulcstároló protokoll) típust -Dkeystore.type paraméter:

-Dkeystore.type = pkcs12

Vagy természetesen felsorolhatjuk a támogatott formátumok egyikét getInstance:

KeyStore ks = KeyStore.getInstance ("pcks12"); 

3.2. Inicializálás

Kezdetben meg kell Betöltés a kulcstár:

char [] pwdArray = "jelszó" .toCharArray (); ks.load (null, pwdArray); 

Használunk Betöltés akár új kulcstárat hozunk létre, akár nyitunk egy meglévőet.

És elmondjuk KeyStore hogy áthaladással újat hozzon létre nulla első paraméterként.

Megadunk egy jelszót is, amelyet a jövőben használunk a kulcstár eléréséhez. Ezt is beállíthatjuk nulla, bár ezzel nyitva állnánk a titkainkon.

3.3. Tárolás

Végül az új kulcstárunkat elmentjük a fájlrendszerbe:

try (FileOutputStream fos = new FileOutputStream ("newKeyStoreFileName.jks")) {ks.store (fos, pwdArray); } 

Ne feledje, hogy a fentiekben nem látható a több ellenőrzött kivétel getInstance, Betöltés, és bolt minden dobás.

4. Kulcstár betöltése

A kulcstár betöltéséhez először létre kell hoznunk a KeyStore például, mint korábban.

Ezúttal azonban adjuk meg a formátumot, mivel egy létezőt töltünk be:

KeyStore ks = KeyStore.getInstance ("JKS"); ks.load (új FileInputStream ("newKeyStoreFileName.jks"), pwdArray);

Ha JVM-ünk nem támogatja az általunk átadott kulcstárolótípust, vagy ha nem egyezik a megnyitott fájlrendszer kulcstárolójának típusával, akkor kapunk egy KeyStoreException:

java.security.KeyStoreException: A KEYSTORE_TYPE nem található

Továbbá, ha rossz a jelszó, akkor kapunk egy UnrecoverableKeyException:

java.security.UnrecoverableKeyException: A jelszó ellenőrzése nem sikerült

5. A bejegyzések tárolása

A kulcstárolóban három különböző típusú bejegyzést tárolhatunk, mindegyik bejegyzés az álneve alatt található:

  • Szimmetrikus kulcsok (a JCE-ben titkos kulcsoknak nevezik),
  • - aszimmetrikus kulcsok (a JCE-nél nyilvános és magánkulcsoknak nevezik őket), és
  • Megbízható tanúsítványok

Vessünk egy pillantást mindegyikre.

5.1. Szimmetrikus kulcs mentése

A legegyszerűbb, amit egy kulcstárolóban tárolhatunk, a szimmetrikus kulcs.

A szimmetrikus kulcs mentéséhez három dologra lesz szükségünk:

  1. egy álnév - egyszerűen az ő neve, amelyet a jövőben a bejegyzésre utalunk
  2. kulcs - amelyet egy a KeyStore.SecretKeyEntry.
  3. jelszót - amely be van tekerve az úgynevezett a ProtectionParam.
KeyStore.SecretKeyEntry secret = új KeyStore.SecretKeyEntry (secretKey); KeyStore.ProtectionParameter jelszó = new KeyStore.PasswordProtection (pwdArray); ks.setEntry ("db-encryption-secret", titok, jelszó);

Ne feledje, hogy a jelszó nem lehet nulla, lehet azonban üres is Húr.Ha elhagyjuk a jelszót nulla egy bejegyzésért kapunk egy KeyStoreException:

java.security.KeyStoreException: nem titkos jelszó szükséges a SecretKeyEntry létrehozásához

Kicsit furcsának tűnhet, hogy a kulcsot és a jelszót burkoló osztályokba kell csomagolnunk.

Becsomagoljuk a kulcsot, mert setEntry egy általános módszer, amely a többi bejegyzés típushoz is használható. A bejegyzés típusa lehetővé teszi a KeyStore API másként kezelni.

Csomagoljuk a jelszót, mert a KeyStore Az API támogatja a GUI-k és a CLI-k visszahívását, hogy összegyűjtse a jelszót a végfelhasználótól. Nézze meg a KeyStore.CallbackHandlerProtection Javadoc további részletekért.

Használhatjuk ezt a módszert egy meglévő kulcs frissítésére is. Csak újra kell hívnunk ugyanazzal az álnévvel és jelszóval, valamint az újunkkal titok.

5.2. Privát kulcs mentése

Az aszimmetrikus kulcsok tárolása kissé összetettebb, mivel a tanúsítványláncokkal kell foglalkoznunk.

Továbbá a KeyStore Az API egy dedikált módszert ad nekünk setKeyEntry ami kényelmesebb, mint az általános setEntry módszer.

Tehát egy aszimmetrikus kulcs mentéséhez négy dologra lesz szükségünk:

  1. egy álnév, ugyanaz, mint korábban
  2. egy magánkulcs. Mivel nem az általános módszert használjuk, a kulcs nem lesz becsomagolva. A mi esetünkben a PrivateKey
  3. jelszót a bejegyzés eléréséhez. Ezúttal a jelszó kötelező
  4. tanúsítványlánc amely igazolja a megfelelő nyilvános kulcsot
X509Certificate [] certificateChain = új X509Certificate [2]; lánc [0] = clientCert; lánc [1] = caCert; ks.setKeyEntry ("sso-signing-key", privateKey, pwdArray, certificateChain);

Itt természetesen sok minden elromolhat, például ha pwdArray van nulla:

java.security.KeyStoreException: A jelszó nem lehet null

De van egy nagyon furcsa kivétel, amellyel tisztában kell lenni, és ez az, ha pwdArray egy üres tömb:

java.security.UnrecoverableKeyException: Adott utolsó blokk nincs megfelelően kitöltve

A frissítéshez egyszerűen újra felhívhatjuk a metódust ugyanazzal az álnévvel és egy újonnan privateKey és certificateChain.

Hasznos lehet egy gyors frissítés is hogyan lehet létrehozni egy tanúsítványláncot.

5.3. Megbízható tanúsítvány mentése

Megbízható tanúsítványok tárolása meglehetősen egyszerű. Csak az álnevet és a tanúsítványt igénylimaga, amely típusú Bizonyítvány:

ks.setCertificateEntry ("google.com", trustedCertificate);

Általában a tanúsítvány az, amelyet nem mi generáltunk, hanem egy harmadik féltől származott.

Emiatt itt fontos megjegyezni KeyStore valójában nem ellenőrzi ezt a tanúsítványt. Tárolás előtt egyedül ellenőriznünk kell.

A frissítéshez egyszerűen újra felhívhatjuk a metódust ugyanazzal az álnévvel és egy újonnan trustedCertificate.

6. Bejegyzések olvasása

Most, hogy írtunk néhány bejegyzést, mindenképpen el akarjuk olvasni.

6.1. Egyetlen bejegyzés elolvasása

Először kihúzhatjuk a kulcsokat és tanúsítványokat álneveik szerint:

Key ssoSigningKey = ks.getKey ("sso-signing-key", pwdArray); Tanúsítvány google = ks.getCertificate ("google.com");

Ha nincs ilyen nevű bejegyzés, vagy más típusú, akkor getKey egyszerűen visszatér nulla:

public void whenEntryIsMissingOrOfIncorrectType_thenReturnsNull () {// ... inicializálja a kulcstárat // ... adjon hozzá egy "widget-api-secret" Assert.assertNull (ks.getKey ("some-other-api-secret") nevű bejegyzést; Assert.assertNotNull (ks.getKey ("widget-api-titok")); Assert.assertNull (ks.getCertificate ("widget-api-secret")); }

De ha a kulcs jelszava rossz, ugyanazt a furcsa hibát kapjuk, amiről korábban beszéltünk:

java.security.UnrecoverableKeyException: Adott utolsó blokk nincs megfelelően kitöltve

6.2. Annak ellenőrzése, hogy a kulcstár tartalmaz-e álnevet

Mivel KeyStore csak tárolja a bejegyzéseket az a használatával Térkép, feltárja a létezés ellenőrzésének lehetőségét a bejegyzés lekérése nélkül:

public void whenAddingAlias_thenCanQueryWithoutSaving () {// ... inicializálja a kulcstárat // ... adjon hozzá egy "widget-api-secret" nevű bejegyzést
 assertTrue (ks.containsAlias ​​("widget-api-secret")); assertFalse (ks.containsAlias ​​("valami-más-api-titok")); }

6.3. A belépés fajtájának ellenőrzése

Vagy, KeyStore#entryInstanceOf egy kicsit erősebb.

Ez olyan, mint tartalmazzaAlias, kivéve, hogy a bejegyzés típusát is ellenőrzi:

public void whenAddingAlias_thenCanQueryByType () {// ... inicializálja a kulcstárat // ... adjon hozzá egy "widget-api-secret" nevű titkos bejegyzést
 assertTrue (ks.containsAlias ​​("widget-api-secret")); assertFalse (ks.entryInstanceOf ("widget-api-secret", KeyType.PrivateKeyEntry.class)); }

7. Bejegyzések törlése

KeyStore, természetesen,támogatja az általunk hozzáadott bejegyzések törlését:

public void whenDeletingAnAlias_thenIdempotent () {// ... inicializálja a kulcstárat // ... adjon hozzá egy "widget-api-secret" nevű bejegyzést
 assertEquals (ks.size (), 1);
 ks.deleteEntry ("widget-api-secret"); ks.deleteEntry ("valami-más-api-titok");
 assertFalse (ks.size (), 0); }

Szerencsére, deleteEntry idempotens, tehát a metódus ugyanúgy reagál, függetlenül attól, hogy létezik-e a bejegyzés vagy sem.

8. Kulcstár törlése

Ha törölni akarjuk a kulcstárunkat, akkor az API nem segít nekünk, de mégis használhatjuk a Java-t:

Files.delete (Paths.get (keystorePath));

Vagy alternatív megoldásként megtarthatjuk a kulcstárat, és csak eltávolíthatjuk a bejegyzéseket:

Felsorolási álnevek = keyStore.aliases (); while (aliases.hasMoreElements ()) {String alias = aliases.nextElement (); keyStore.deleteEntry (alias); }

9. Következtetés

Ebben a cikkben a tanúsítványok és kulcsok kezeléséről beszéltünk KeyStore API. Megbeszéltük, hogy mi a kulcstár, hogyan hozhatunk létre, tölthetünk be és törölhetünk, hogyan tárolhatunk kulcsot vagy tanúsítványt a kulcstárban, és hogyan lehet betölteni és frissíteni a meglévő bejegyzéseket új értékekkel.

A példa teljes megvalósítása a Github oldalon található.

Java alsó

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT