Java KeyStore API

Java Top

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET

1. Oversikt

I denne opplæringen ser vi på å administrere kryptografiske nøkler og sertifikater i Java ved hjelp av KeyStore API.

2. Keystores

Hvis vi trenger å administrere nøkler og sertifikater i Java, trenger vi en keystore, som rett og slett er en sikker samling av alias innganger av nøkler og sertifikater.

Vi lagrer vanligvis nøkkelbutikker i et filsystem, og vi kan beskytte det med et passord.

Som standard har Java en keystore-fil som ligger på JAVA_HOME /jre/ lib / sikkerhet / cacerts. Vi får tilgang til denne nøkkelbutikken ved hjelp av standard nøkkeloppbevaringspassord endre det.

Nå, med den biten bakgrunn, la oss komme til å lage vår første.

3. Opprette en Keystore

3.1. Konstruksjon

Vi kan enkelt lage en nøkkelbutikk ved hjelp av keytool, eller vi kan gjøre det programmatisk ved hjelp av KeyStore API:

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

Her bruker vi standardtypen, selv om det er noen få nøkkelbutiktyper som jceks eller pcks12.

Vi kan overstyre standard “JKS” (en Oracle-proprietær keystore-protokoll) ved hjelp av a -Dkeystore.type parameter:

-Dkeystore.type = pkcs12

Eller så kan vi selvfølgelig liste opp et av de støttede formatene i getInstance:

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

3.2. Initialisering

I utgangspunktet må vi laste nøkkelbutikken:

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

Vi bruker laste om vi oppretter en ny nøkkelbutikk eller åpner en eksisterende.

Og, forteller vi KeyStore å lage en ny ved å passere null som den første parameteren.

Vi gir også et passord som skal brukes til å få tilgang til nøkkelbutikken i fremtiden. Vi kan også sette dette til null, skjønt det ville gjøre hemmelighetene våre åpne.

3.3. Oppbevaring

Til slutt lagrer vi vår nye nøkkelbutikk i filsystemet:

prøv (FileOutputStream fos = ny FileOutputStream ("newKeyStoreFileName.jks")) {ks.store (fos, pwdArray); } 

Merk at ikke vist ovenfor er de flere sjekket unntakene som getInstance, laste, og butikk hvert kast.

4. Laste inn en Keystore

For å laste en nøkkelbutikk må vi først lage en KeyStore eksempel, som før.

Denne gangen, la oss imidlertid spesifisere formatet siden vi laster inn et eksisterende format:

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

Hvis vår JVM ikke støtter nøkkellagertypen vi passerte, eller hvis den ikke samsvarer med nøkkellagertypen på filsystemet vi åpner, får vi en KeyStoreException:

java.security.KeyStoreException: KEYSTORE_TYPE ikke funnet

Hvis passordet er feil, får vi også et UnrecoverableKeyException:

java.security.UnrecoverableKeyException: Bekreftelse av passord mislyktes

5. Lagring av oppføringer

I nøkkelbutikken kan vi lagre tre forskjellige typer oppføringer, hver oppføring under dets alias:

  • Symmetriske nøkler (referert til som Secret Keys i JCE),
  • Asymmetriske nøkler (referert til som offentlige og private nøkler i JCE), og
  • Pålitelige sertifikater

La oss ta en titt på hver enkelt.

5.1. Lagre en symmetrisk nøkkel

Det enkleste vi kan lagre i en keystore er en Symmetric Key.

For å lagre en symmetrisk nøkkel trenger vi tre ting:

  1. et alias - hans er ganske enkelt navnet vi skal bruke i fremtiden for å referere til oppføringen
  2. en nøkkel - som er pakket inn i en KeyStore.SecretKeyEntry.
  3. et passord - som er innpakket i det som kalles a Beskyttelse Param.
KeyStore.SecretKeyEntry secret = ny KeyStore.SecretKeyEntry (secretKey); KeyStore.ProtectionParameter passord = nytt KeyStore.PasswordProtection (pwdArray); ks.setEntry ("db-kryptering-hemmelig", hemmelig, passord);

Husk at passordet ikke kan være null, det kan imidlertid være tomt String.Hvis vi legger igjen passordet null for en oppføring, får vi en KeyStoreException:

java.security.KeyStoreException: ikke-null passord kreves for å opprette SecretKeyEntry

Det kan virke litt rart at vi trenger å pakke nøkkelen og passordet i omslagsklasser.

Vi pakker nøkkelen fordi setEntry er en generisk metode som også kan brukes for de andre oppføringstypene. Type oppføring tillater KeyStore API for å behandle det annerledes.

Vi pakker inn passordet fordi KeyStore API støtter tilbakeringing til GUI og CLI for å samle passordet fra sluttbrukeren. Sjekk ut KeyStore.CallbackHandlerProtection Javadoc for mer informasjon.

Vi kan også bruke denne metoden til å oppdatere en eksisterende nøkkel. Vi trenger bare å ringe det igjen med samme alias og passord og det nye hemmelig.

5.2. Lagre en privat nøkkel

Å lagre asymmetriske nøkler er litt mer komplisert siden vi trenger å håndtere sertifikatkjeder.

Også, den KeyStore API gir oss en dedikert metode kalt setKeyEntry som er mer praktisk enn det generiske setEntry metode.

Så, for å lagre en asymmetrisk nøkkel, trenger vi fire ting:

  1. et alias, samme som før
  2. en privat nøkkel. Fordi vi ikke bruker den generiske metoden, blir ikke nøkkelen pakket inn. Også for vårt tilfelle bør det være en forekomst av PrivateKey
  3. et passord for å få tilgang til oppføringen. Denne gangen er passordet obligatorisk
  4. en sertifikatkjede som sertifiserer den tilsvarende offentlige nøkkelen
X509Certificate [] certificateChain = nytt X509Certificate [2]; chain [0] = clientCert; kjede [1] = caCert; ks.setKeyEntry ("sso-signering-nøkkel", privateKey, pwdArray, certificateChain);

Nå kan mye gå galt her, selvfølgelig, som om pwdArray er null:

java.security.KeyStoreException: passordet kan ikke være null

Men det er et veldig rart unntak å være klar over, og det er hvis pwdArray er en tom matrise:

java.security.UnrecoverableKeyException: Gitt sluttblokk ikke riktig polstret

For å oppdatere kan vi bare ringe metoden igjen med samme alias og et nytt privateKey og CertificateChain.

Det kan også være verdifullt å gjøre en rask oppdatering hvordan generere en sertifikatkjede.

5.3. Lagre et klarert sertifikat

Lagring av pålitelige sertifikater er ganske enkelt. Det krever bare aliaset og sertifikatetseg selv, som er av typen Sertifikat:

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

Vanligvis er sertifikatet et som vi ikke genererte, men som kom fra en tredjepart.

På grunn av det er det viktig å merke seg det her KeyStore bekrefter faktisk ikke dette sertifikatet. Vi bør bekrefte det på egenhånd før du lagrer det.

For å oppdatere kan vi bare ringe metoden igjen med samme alias og et nytt klarert sertifikat.

6. Leseoppføringer

Nå som vi har skrevet noen bidrag, vil vi absolutt ønske å lese dem.

6.1. Lese en enkelt oppføring

Først kan vi trekke ut nøkler og sertifikater etter deres alias:

Nøkkel ssoSigningKey = ks.getKey ("sso-signeringsnøkkel", pwdArray); Sertifikat google = ks.getCertificate ("google.com");

Hvis det ikke er noen oppføring med det navnet, eller det er av en annen type, da getKey rett og slett tilbake null:

public void whenEntryIsMissingOrOfIncorrectType_thenReturnsNull () {// ... initialize keystore // ... add a entry called "widget-api-secret" Assert.assertNull (ks.getKey ("some-other-api-secret")); Assert.assertNotNull (ks.getKey ("widget-api-hemmelig")); Assert.assertNull (ks.getCertificate ("widget-api-secret")); }

Men hvis passordet til nøkkelen er feil, vi får den samme rare feilen vi snakket om tidligere:

java.security.UnrecoverableKeyException: Gitt sluttblokk ikke riktig polstret

6.2. Kontrollerer om en Keystore inneholder et alias

Siden KeyStore bare lagrer oppføringer ved hjelp av en Kart, det avslører muligheten til å sjekke om det eksisterer uten å hente oppføringen:

offentlig ugyldig nårAddingAlias_thenCanQueryWithoutSaving () {// ... initialiser nøkkellager // ... legg til en oppføring kalt "widget-api-secret"
 assertTrue (ks.containsAlias ​​("widget-api-secret")); assertFalse (ks.containsAlias ​​("noe-annet-api-hemmelig")); }

6.3. Kontrollere typen inngang

Eller, KeyStore#entryInstanceOf er litt kraftigere.

Det er som inneholderAlias, bortsett fra at det også sjekker oppføringstypen:

offentlig ugyldig nårAddingAlias_thenCanQueryByType () {// ... initialiser nøkkellager // ... legg til en hemmelig oppføring kalt "widget-api-secret"
 assertTrue (ks.containsAlias ​​("widget-api-secret")); assertFalse (ks.entryInstanceOf ("widget-api-secret", KeyType.PrivateKeyEntry.class)); }

7. Slette innlegg

KeyStore, selvfølgelig,støtter sletting av oppføringene vi har lagt til:

offentlig tomrom nårDeletingAnAlias_thenIdempotent () {// ... initialiser en nøkkelbutikk // ... legg til en oppføring kalt "widget-api-secret"
 assertEquals (ks.size (), 1);
 ks.deleteEntry ("widget-api-secret"); ks.deleteEntry ("noe annet api-hemmelig");
 assertFalse (ks.size (), 0); }

Heldigvis, Slett inngang er idempotent, så metoden reagerer det samme, enten oppføringen eksisterer eller ikke.

8. Slette en Keystore

Hvis vi vil slette nøkkelbutikken vår, er API-en ikke til hjelp for oss, men vi kan fortsatt bruke Java til å gjøre det:

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

Eller som et alternativ kan vi holde nøkkelbutikken rundt, og bare fjerne oppføringer:

Oppregningsaliaser = keyStore.aliases (); mens (aliases.hasMoreElements ()) {String alias = aliases.nextElement (); keyStore.deleteEntry (alias); }

9. Konklusjon

I denne artikkelen snakket vi om å administrere sertifikater og nøkler ved hjelp av KeyStore API. Vi diskuterte hva en nøkkelbutikk er, hvordan du oppretter, laster inn og sletter en, hvordan du lagrer en nøkkel eller et sertifikat i nøkkelbutikken og hvordan du laster og oppdaterer eksisterende oppføringer med nye verdier.

Den fulle implementeringen av eksemplet finner du på Github.

Java bunn

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET

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