Rozhranie Java KeyStore API

Java Top

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ

1. Prehľad

V tomto výučbe sa zameriavame na správu kryptografických kľúčov a certifikátov v Jave pomocou súboru KeyStore API.

2. Knižnice

Ak potrebujeme spravovať kľúče a certifikáty v Jave, potrebujeme a sklad kľúčov, čo je jednoducho bezpečná zbierka aliasov záznamy kľúčov a certifikátov.

Sklady kľúčov zvyčajne ukladáme do súborového systému a môžeme ich chrániť heslom.

V predvolenom nastavení má Java súbor s úložiskom kľúčov umiestnený na JAVA_HOME /jre/ lib / security / cacerts. Do tohto úložiska kľúčov môžeme získať prístup pomocou predvoleného hesla úložiska kľúčov Zmeň to.

Teraz, s tým trochou pozadia, poďme na vytvorenie nášho prvého.

3. Vytvorenie úložiska kľúčov

3.1. Konštrukcia

Sklad klávesníc môžeme ľahko vytvoriť pomocou nástroja na kľúče, alebo to môžeme urobiť programovo pomocou nástroja KeyStore API:

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

Tu používame predvolený typ, aj keď je k dispozícii niekoľko typov úložísk kľúčov ako jceks alebo pcks12.

Predvolený typ „JKS“ (protokol úložiska kľúčov Oracle) môžeme prepísať pomocou a -Dkeystore.typ parameter:

-Dkeystore.type = pkcs12

Alebo môžeme v zozname samozrejme uviesť jeden z podporovaných formátov getInstance:

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

3.2. Inicializácia

Spočiatku musíme naložiť sklad kľúčov:

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

Používame naložiť či už vytvárame nový sklad kľúčov alebo otvárame už existujúci.

A povieme KeyStore vytvoriť nový prechodom nulový ako prvý parameter.

Poskytujeme tiež heslo, ktoré sa v budúcnosti použije pre prístup do skladu kľúčov. Môžeme to tiež nastaviť na nulový, aj keď by sa tým naše tajomstvá otvorili.

3.3. Skladovanie

Nakoniec uložíme naše nové úložisko kľúčov do súborového systému:

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

Nezabudnite, že vyššie uvedené nie je niekoľko kontrolovaných výnimiek getInstance, naložiť, a obchod každý hod.

4. Načítanie úložiska kľúčov

Na načítanie úložiska kľúčov je potrebné najskôr vytvoriť a KeyStore napríklad ako predtým.

Tentokrát však upresnime formát, pretože načítavame existujúci:

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

Ak náš JVM nepodporuje typ úložiska kľúčov, ktorý sme prešli, alebo ak sa nezhoduje s typom úložiska kľúčov v súborovom systéme, ktorý otvárame, dostaneme KeyStoreException:

java.security.KeyStoreException: KEYSTORE_TYPE sa nenašiel

Ak je heslo nesprávne, dostaneme UnrecoverableKeyException:

java.security.UnrecoverableKeyException: Overenie hesla zlyhalo

5. Ukladanie záznamov

V obchode s kľúčmi môžeme uložiť tri rôzne druhy záznamov, z ktorých každý má svoj alias:

  • Symetrické kľúče (v JCE označované ako tajné kľúče),
  • Asymetrické kľúče (v JCE označované ako verejný a súkromný kľúč) a
  • Dôveryhodné certifikáty

Poďme sa na každú z nich pozrieť.

5.1. Uloženie symetrického kľúča

Najjednoduchšia vec, ktorú môžeme uložiť v obchode s kľúčmi, je symetrický kľúč.

Na uloženie symetrického kľúča budeme potrebovať tri veci:

  1. alias - toto je jednoducho meno, ktoré v budúcnosti použijeme na označenie záznamu
  2. kľúč - ktorý je zabalený v a KeyStore.SecretKeyEntry.
  3. heslo - ktorý je zabalený v tom, čo sa nazýva a ProtectionParam.
KeyStore.SecretKeyEntry secret = nový KeyStore.SecretKeyEntry (secretKey); KeyStore.ProtectionParameter heslo = nový KeyStore.PasswordProtection (pwdArray); ks.setEntry ("db-encryption-secret", tajný kód, heslo);

Pamätajte, že heslo nemôže byť nulový, môže to však byť prázdny údaj String.Ak necháme heslo nulový za vstup dostaneme a Výnimka KeyStore:

java.security.KeyStoreException: na vytvorenie SecretKeyEntry sa vyžaduje nenulové heslo

Môže sa to zdať trochu čudné, že musíme zabaliť kľúč a heslo do tried wrapperov.

Kľúč zabalíme, pretože setEntry je všeobecná metóda, ktorú je možné použiť aj pre ostatné typy záznamov. Typ vstupu umožňuje KeyStore API s tým zaobchádzať inak.

Zabalíme heslo, pretože KeyStore API podporuje spätné volania do GUI a CLI na získanie hesla od koncového používateľa. Pozrite sa na KeyStore.CallbackHandlerProtection Javadoc pre viac informácií.

Túto metódu môžeme použiť aj na aktualizáciu existujúceho kľúča. Musíme to znova zavolať s rovnakým aliasom a heslom a naším novým tajomstvo.

5.2. Uloženie súkromného kľúča

Ukladanie asymetrických kľúčov je o niečo zložitejšie, pretože sa musíme zaoberať reťazcami certifikátov.

Tiež KeyStore API nám poskytuje špecializovanú metódu s názvom setKeyEntry čo je pohodlnejšie ako všeobecné setEntry metóda.

Aby sme uložili asymetrický kľúč, budeme potrebovať štyri veci:

  1. alias, rovnaké ako predtým
  2. súkromný kľúč. Pretože nepoužívame všeobecnú metódu, kľúč sa nezabalí. V našom prípade by malo ísť tiež o príklad PrivateKey
  3. heslo pre prístup k záznamu. Tentokrát je heslo povinné
  4. reťaz certifikátov ktorý certifikuje zodpovedajúci verejný kľúč
X509Certificate [] certificateChain = nový X509Certificate [2]; chain [0] = clientCert; reťazec [1] = caCert; ks.setKeyEntry ("sso-podpisový kľúč", privateKey, pwdArray, certificateChain);

Teraz sa tu môže veľa pokaziť, samozrejme, akoby pwdArray je nulový:

java.security.KeyStoreException: heslo nemôže mať hodnotu null

Je však potrebné si uvedomiť skutočne zvláštnu výnimku, a to ak pwdArray je prázdne pole:

java.security.UnrecoverableKeyException: Posledný blok nie je správne vyplnený

Pri aktualizácii môžeme metódu jednoducho zavolať znova s ​​rovnakým aliasom a novým privateKey a certificateChain.

Môže byť tiež užitočné rýchlo sa občerstviť ako vygenerovať reťazec certifikátov.

5.3. Uloženie dôveryhodného certifikátu

Ukladanie dôveryhodných certifikátov je dosť jednoduché. Vyžaduje sa iba alias a certifikátsám, ktorý je typu Osvedčenie:

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

Obvykle je to certifikát, ktorý sme nevygenerovali, ale ktorý pochádza od tretej strany.

Z tohto dôvodu je dôležité si tu uvedomiť, že KeyStore tento certifikát v skutočnosti neoveruje. Pred uložením by sme si to mali sami overiť.

Pri aktualizácii môžeme metódu jednoducho zavolať znova s ​​rovnakým aliasom a novým trustedCertificate.

6. Čítanie záznamov

Teraz, keď sme napísali nejaké záznamy, určite si ich budeme chcieť prečítať.

6.1. Čítanie jedného záznamu

Najskôr môžeme kľúče a certifikáty vytiahnuť podľa ich aliasov:

Kľúč ssoSigningKey = ks.getKey ("sso-podpisový kľúč", pwdArray); Certifikát google = ks.getCertificate ("google.com");

Ak pod týmto menom nie je záznam alebo je iného typu, potom getKey jednoducho sa vráti nulový:

public void whenEntryIsMissingOrOfIncorrectType_thenReturnsNull () {// ... inicializovať úložisko kľúčov // ... pridať záznam s názvom "widget-api-secret" Assert.assertNull (ks.getKey ("some-other-api-secret")); Assert.assertNotNull (ks.getKey ("widget-api-secret")); Assert.assertNull (ks.getCertificate ("widget-api-secret")); }

Ak je však heslo pre kľúč nesprávne, dostaneme tú istú zvláštnu chybu, o ktorej sme hovorili už skôr:

java.security.UnrecoverableKeyException: Posledný blok nie je správne vyplnený

6.2. Kontrola, či úložisko kľúčov obsahuje alias

Odkedy KeyStore iba ukladá položky pomocou a Mapa, vystavuje schopnosť skontrolovať existenciu bez načítania záznamu:

public void whenAddingAlias_thenCanQueryWithoutSaving () {// ... inicializovať úložisko kľúčov // ... pridať záznam s názvom „widget-api-secret“
 assertTrue (ks.containsAlias ​​("widget-api-secret")); assertFalse (ks.containsAlias ​​("some-other-api-secret")); }

6.3. Kontrola druhu vstupu

Alebo KeyStore#entryInstanceOf je o niečo výkonnejší.

Je to ako obsahujeAlias, okrem toho tiež kontroluje typ záznamu:

public void whenAddingAlias_thenCanQueryByType () {// ... inicializovať úložisko kľúčov // ... pridať tajný záznam s názvom „widget-api-secret“
 assertTrue (ks.containsAlias ​​("widget-api-secret")); assertFalse (ks.entryInstanceOf ("widget-api-secret", KeyType.PrivateKeyEntry.class)); }

7. Mazanie záznamov

KeyStore, samozrejme,podporuje mazanie záznamov, ktoré sme pridali:

public void whenDeletingAnAlias_thenIdempotent () {// ... inicializovať úložisko kľúčov // ... pridať záznam s názvom „widget-api-secret“
 assertEquals (ks.size (), 1);
 ks.deleteEntry ("widget-api-secret"); ks.deleteEntry ("some-other-api-secret");
 assertFalse (ks.size (), 0); }

Našťastie deleteEntry je idempotentný, takže metóda reaguje rovnako, či už záznam existuje, alebo nie.

8. Vymazanie úložiska kľúčov

Ak chceme vymazať náš obchod s kľúčmi, API nám nepomôže, ale stále na to môžeme použiť Javu:

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

Alebo môžeme alternatívne ponechať úložisko kľúčov v okolí a jednoducho odstrániť záznamy:

Aliasy výčtu = keyStore.aliases (); while (aliases.hasMoreElements ()) {Alias ​​reťazca = aliases.nextElement (); keyStore.deleteEntry (alias); }

9. Záver

V tomto článku sme hovorili o správe certifikátov a kľúčov pomocou KeyStore API. Diskutovali sme o tom, čo je to úložisko kľúčov, ako ho vytvoriť, načítať a vymazať, ako uložiť kľúč alebo certifikát v úložisku kľúčov a ako načítať a aktualizovať existujúce položky o nové hodnoty.

Celú implementáciu tohto príkladu nájdete na serveri Github.

Java dole

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ

$config[zx-auto] not found$config[zx-overlay] not found