Programmering

Bygg sikre nettverksapplikasjoner med SSL og JSSE API

Internett er et farlig sted. Det er rett og slett for lett å snuse, spoofe og stjele ubeskyttet informasjon når den beveger seg over ledningene. I forrige måned skrev jeg den siste artikkelen i en serie om X.509-sertifikater og PKI (Public Key Infrastructure), teknologiene som sikrer mest e-handelsaktivitet på Internett. Nær slutten av artikkelen foreslo jeg å se på SSL (Secure Socket Layer) -protokollen for å lære hvordan X.509-sertifikater brukes i praksis. SSL er X.509-killer-appen - nesten alle nettlesere og mest populære web- og applikasjonsservere støtter den.

Denne måneden vil jeg utforske SSL som implementert av JSSE (Java Secure Socket Extension), og vise deg hvordan du bygger sikre nettverksapplikasjoner i Java ved hjelp av SSL og JSSE.

La oss begynne med en enkel demonstrasjon. JSSE tilbyr et SSL-verktøy for Java-applikasjoner. I tillegg til de nødvendige klassene og grensesnittene, tilbyr JSSE en praktisk kommandolinje feilsøkingsbryter som du kan bruke til se SSL-protokollen i aksjon. I tillegg til å gi nyttig informasjon for feilsøking av en motstridende applikasjon, er det å leke med verktøysettet en fin måte å få føttene våte med SSL og JSSE.

For å kjøre demonstrasjonen må du først kompilere følgende klasse:

 public class Test {public static void main (String [] arstring) {try {new java.net.URL ("//" + arstring [0] + "/"). getContent (); } fangst (Unntak unntak) {exception.printStackTrace (); }}} 

Deretter må du slå på SSL-feilsøking og kjøre applikasjonen ovenfor. Applikasjonen kobles til det sikre nettstedet du angir på kommandolinjen ved hjelp av SSL-protokollen via HTTPS. Det første alternativet laster HTTPS-protokollbehandleren. Det andre alternativet, feilsøkingsalternativet, får programmet til å skrive ut oppførselen. Her er kommandoen (erstatt med navnet på en sikker webserver):

 java -Djava.protocol.handler.pkgs = com.sun.net.ssl.internal.www.protocol -Djavax.net.debug = ssl Test 

Du må installere JSSE; se Ressurser hvis du er usikker på hvordan.

La oss nå komme i gang og snakke om SSL og JSSE.

En kort titt på SSL

Koden i innledningen viser den enkleste måten å legge til SSL i applikasjonene dine - via java.net.URL klasse. Denne tilnærmingen er nyttig, men er ikke fleksibel nok til at du kan lage et sikkert program som bruker generiske kontakter.

Før jeg viser deg hvordan du legger til den fleksibiliteten, la oss ta en rask titt på SSL-funksjonene.

Som navnet antyder, tar SSL sikte på å gi applikasjoner en sikker socketlike verktøykasse. Ideelt sett bør det være enkelt å konvertere et program som bruker vanlige stikkontakter til et program som bruker SSL.

SSL adresserer tre viktige sikkerhetsspørsmål:

  1. Det gir autentisering, noe som bidrar til å sikre legitimiteten til enhetene som er involvert i en dialog.
  2. Det gir privatliv. SSL hjelper med å garantere at en tredjepart ikke kan tyde dialogen mellom to enheter.
  3. Det opprettholder integritet. Bruken av en MAC (meldingsautentiseringskode), som ligner på en kontrollsum, bidrar til å garantere at en dialog mellom to enheter ikke endres av en tredjepart.

SSL er sterkt avhengig av både kryptering med offentlig nøkkel og hemmelig nøkkel. Den bruker kryptografi med hemmelig nøkkel for å kryptere dataene som utveksles mellom to applikasjoner. SSL gir den ideelle løsningen fordi hemmelige nøkkelalgoritmer er både sikre og raske. Offentlig nøkkel-kryptografi, som er tregere enn hemmelig nøkkel-kryptografi, er et bedre valg for autentisering og nøkkelutveksling.

Suns JSSE-referanseimplementering kommer med all den teknologien som er nødvendig for å legge til SSL i applikasjonene dine. Den inkluderer RSA (Rivest-Shamir-Adleman) kryptografistøtte - de facto-standarden for sikkerhet på Internett. Den inkluderer implementering av SSL 3.0 - gjeldende SSL-standard - og TLS (Transport Layer Security) 1.0, neste generasjon av SSL. JSSE tilbyr også en serie APIer for å opprette og bruke sikre stikkontakter.

JSSE API

Java-sikkerhetsarkitekturen bruker Fabrikk designmønster tungt. For uinnvidde bruker fabrikkdesignmønsteret spesielt fabrikk objekter for å konstruere forekomster, i stedet for å ringe sine konstruktører direkte. (Se Ressurser for fordeler og ulemper ved fabrikkklassen.)

I JSSE begynner alt med fabrikken; det er en fabrikk for SSL-kontakter og en fabrikk for SSL-serverkontakter. Siden generiske stikkontakter og serverstikkontakter allerede er ganske grunnleggende for Java-nettverksprogrammering, antar jeg at du er kjent med de to og at du forstår deres roller og forskjeller. Hvis ikke, anbefaler jeg at du henter en god bok om Java-nettverksprogrammering.

SSLSocketFactory

Metoder i javax.net.ssl.SSLSocketFactory klasse faller inn i tre kategorier. Den første består av en enkelt statisk metode som henter standard SSL-kontaktfabrikk: statisk SocketFactory getDefault ().

Den andre kategorien består av fire metoder arvet fra javax.net.SocketFactory som speiler de fire nøkkelkonstruktørene som finnes på java.net.Socket klasse, og en metode som pakker en eksisterende kontakt med en SSL-kontakt. De returnerer hver en SSL-kontakt:

  1. Socket createSocket (strengvert, int-port)
  2. Socket createSocket (strengvert, int-port, InetAddress clientHost, int clientPort)
  3. Socket createSocket (InetAddress-vert, int-port)
  4. Socket createSocket (InetAddress-vert, int-port, InetAddress clientHost, int clientPort)
  5. Stikkontakt createSocket (Stikkontakt, strengvert, int-port, boolsk autoClose)

De to metodene i den tredje kategorien returnerer listen over SSL-krypteringsserier som er aktivert som standard, og den komplette listen over støttede SSL-krypteringspakker:

  1. Streng [] getDefaultCipherSuites ()
  2. Streng [] getSupportedCipherSuites ()

En krypteringspakke er en kombinasjon av kryptografiske algoritmer som definerer et bestemt sikkerhetsnivå for en SSL-tilkobling. En krypteringsserie definerer om forbindelsen er kryptert, om innholdsintegritet er verifisert, og hvordan autentisering skjer.

SSLServerSocketFactory

Metoder på javax.net.ssl.SSLServerSocketFactory klasse faller inn i de samme tre kategoriene som SSLSocketFactory. For det første er det den eneste statiske metoden som henter standard SSL-serveruttakfabrikk: statisk ServerSocketFactory getDefault ().

Metodene som returnerer SSL-serverkontakter, speiler konstruktørene som finnes i java.net.ServerSocket klasse:

  1. ServerSocket createServerSocket (int-port)
  2. ServerSocket createServerSocket (int port, int backlog)
  3. ServerSocket createServerSocket (int-port, int-backlog, InetAddress-adresse)

Til slutt, SSLServerSocketFactory har de to metodene som returnerer henholdsvis listen over krypter som er aktivert og listen over støttede krypter:

  1. String [] getDefaultCipherSuites ()
  2. Streng [] getSupportedCipherSuites ()

Så langt er API ganske grei.

SSLSocket

Ting blir interessante i javax.net.ssl.SSLSocket klasse. Jeg antar at du allerede er kjent med metodene som tilbys av foreldrene, the Stikkontakt klasse, så jeg vil konsentrere meg om metodene som gir SSL-relatert funksjonalitet.

I likhet med de to SSL-fabrikkklassene, henter de to første metodene oppført nedenfor henholdsvis de aktiverte og støttede SSL-krypteringssuitene. Den tredje metoden angir de aktiverte krypteringssuitene. Et program kan bruke den tredje operasjonen til å oppgradere eller nedgradere rekkevidden av akseptabel sikkerhet som applikasjonen tillater:

  1. Streng [] getEnabledCipherSuites ()
  2. Streng [] getSupportedCipherSuites ()
  3. void setEnabledCipherSuites (String [] suites)

Disse to metodene avgjør om kontakten kan opprette nye SSL-økter, som opprettholder tilkoblingsdetaljer - som den delte hemmelige nøkkelen - mellom tilkoblinger:

  1. boolsk getEnableSessionCreation ()
  2. void setEnableSessionCreation (boolsk flagg)

De neste to metodene avgjør om kontakten vil kreve klientautentisering. Metodene gir bare mening når de påkalles på servermodusuttak. Husk at i henhold til SSL-spesifikasjonen er klientautentisering valgfri. For eksempel krever de fleste webapplikasjoner ikke det:

  1. boolsk getNeedClientAuth ()
  2. void setNeedClientAuth (boolsk behov)

Metodene nedenfor endrer kontakten fra klientmodus til servermodus. Dette påvirker hvem som initierer SSL-håndtrykk og hvem som autentiserer først:

  1. boolsk getUseClientMode ()
  2. void setUseClientMode (boolsk modus)

Metode ugyldig startHandshake () tvinger et SSL-håndtrykk. Det er mulig, men ikke vanlig, å tvinge en ny håndtrykkoperasjon i en eksisterende forbindelse.

Metode SSLSession getSession () henter SSL-økten. Du trenger sjelden å få tilgang til SSL-økten direkte.

De to metodene som er oppført nedenfor, legger til og fjerner et SSL-håndtrykklytterobjekt. Håndtrykklytterobjektet varsles hver gang en SSL-håndtrykkoperasjon er fullført på kontakten.

  1. void addHandshakeCompletedListener (HandshakeCompletedListener lytter)
  2. void removeHandshakeCompletedListener (HandshakeCompletedListener lytter)

SSLServerSocket

De javax.net.ssl.SSLServerSocket klassen ligner på javax.net.ssl.SSLSocket klasse; det krever ikke mye individuell oppmerksomhet. Faktisk sett med metoder på javax.net.ssl.SSLServerSocket klasse er en delmengde av metodene på javax.net.ssl.SSLSocket klasse.

De to første metodene som er oppført nedenfor, henter de aktiverte og støttede SSL-krypteringssuitene. Den tredje metoden angir den aktiverte krypteringssuiten:

  1. Streng [] getEnabledCipherSuites ()
  2. Streng [] getSupportedCipherSuites ()
  3. void setEnabledCipherSuites (String [] suites)

Disse to metodene styrer om serverkontakten kan opprette nye SSL-økter eller ikke:

  1. boolsk getEnableSessionCreation ()
  2. void setEnableSessionCreation (boolsk flagg)

Følgende metoder avgjør om de aksepterte kontaktene krever klientgodkjenning:

  1. boolsk getNeedClientAuth ()
  2. void setNeedClientAuth (boolsk flagg)

Metodene nedenfor endrer den aksepterte kontakten fra klientmodus til servermodus:

  1. boolsk getUseClientMode ()
  2. ugyldig setUseClientMode (boolsk flagg)

Et enkelt eksempel

For å gjøre denne verktøysettopplæringen tydeligere, har jeg tatt med kildekoden for en enkel server og en kompatibel klient nedenfor. Det er en sikker variasjon på den typiske ekkoapplikasjonen som mange innledende nettverkstekster gir.

Serveren, vist nedenfor, bruker JSSE til å opprette en sikker serverkontakt. Den lytter på serverkontakten for tilkoblinger fra sikre klienter. Når du kjører serveren, må du spesifisere nøkkelbutikken som skal brukes. Nøkkelbutikken inneholder serverens sertifikat. Jeg har opprettet en enkel nøkkellager som inneholder et enkelt sertifikat. (Se Ressurser for å laste ned sertifikatet.)

importere java.io.InputStream; importere java.io.InputStreamReader; importere java.io.BufferedReader; importere java.io.IOException; importere javax.net.ssl.SSLSocket; importere javax.net.ssl.SSLServerSocket; importere javax.net.ssl.SSLServerSocketFactory; offentlig klasse EchoServer {public static void main (String [] arstring) {try {SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault (); SSLServerSocket sslserversocket = (SSLServerSocket) sslserversocketfactory.createServerSocket (9999); SSLSocket sslsocket = (SSLSocket) sslserversocket.accept (); InputStream inputstream = sslsocket.getInputStream (); InputStreamReader inputstreamreader = ny InputStreamReader (inputstream); BufferedReader bufferedreader = new BufferedReader (inputstreamreader); Strengstreng = null; mens ((streng = bufferedreader.readLine ())! = null) {System.out.println (streng); System.out.flush (); }} fange (Unntak unntak) {exception.printStackTrace (); }}} 

Bruk følgende kommando for å starte serveren (foobar er både navnet på keystore-filen og passordet):

 java -Djavax.net.ssl.keyStore = foobar -Djavax.net.ssl.keyStorePassword = foobar EchoServer 

Klienten, vist nedenfor, bruker JSSE for å koble seg sikkert til serveren. Når du kjører klienten, må du spesifisere tillitsbutikken som skal brukes, som inneholder listen over pålitelige sertifikater. Jeg har opprettet en enkel tillitsbutikk som inneholder ett enkelt sertifikat. (Se Ressurser for å laste ned sertifikatet.)

importere java.io.InputStream; importere java.io.OutputStream; importere java.io.InputStreamReader; importere java.io.OutputStreamWriter; importere java.io.BufferedReader; importere java.io.BufferedWriter; importere java.io.IOException; importere javax.net.ssl.SSLSocket; importere javax.net.ssl.SSLSocketFactory; offentlig klasse EchoClient {public static void main (String [] arstring) {try {SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault (); SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket ("localhost", 9999); InputStream inputstream = System.in; InputStreamReader inputstreamreader = ny InputStreamReader (inputstream); BufferedReader bufferedreader = ny BufferedReader (inputstreamreader); OutputStream outputstream = sslsocket.getOutputStream (); OutputStreamWriter outputstreamwriter = ny OutputStreamWriter (outputstream); BufferedWriter bufferedwriter = ny BufferedWriter (outputstreamwriter); Strengstreng = null; mens ((string = bufferedreader.readLine ())! = null) {bufferedwriter.write (string + '\ n'); bufferedwriter.flush (); }} fange (Unntak unntak) {exception.printStackTrace (); }}} 

Bruk følgende kommando for å starte klienten (foobar er både navnet på truststore-filen og passordet):

 java -Djavax.net.ssl.trustStore = foobar -Djavax.net.ssl.trustStorePassword = foobar EchoClient 
$config[zx-auto] not found$config[zx-overlay] not found