Programmering

I Java stoler vi på

Stol på alle? Ikke stol på noen? Høres litt ut som X filer, men når det gjelder konfidensiell informasjon, er det like viktig å vite hvem det er du stoler på som å vite hva du stoler på dem med. Dette konseptet er like viktig for applikasjoner som det er for mennesker. Vi har tross alt gjort søknader til forvaltere av informasjonen vår og forvalterne av ressursene våre. Det er sant i hele virksomheten - applikasjoner inneholder viktig informasjon om vår virksomhet og våre kunder - og det er sant på skrivebordet. Jeg kan ikke fortelle deg hvor mange ganger jeg har blitt spurt om hvordan jeg skal skrive en applet som skanner en brukers stasjon slik at en bruker kan kommandere en annen brukers nettleser eller fange privat informasjon.

Java, som er nettverksutviklingsplattformen som det er, har måttet takle problemet med tillit på hodet. Resultatet er Java Security API og Java Cryptography Architecture.

Et kort blikk bakover

Før jeg dykker hardt inn i API-er, kode og kommentarer, vil jeg kort se på forrige måneds diskusjon. Hvis du blir med for første gang, vil du kanskje sikkerhetskopiere en måned og lese "Signert og levert: En introduksjon til sikkerhet og autentisering." Denne kolonnen gir en grundig introduksjon til alle begrepene og konseptene jeg skal bruke denne måneden.

Sikkerhet og autentisering adresserer to viktige bekymringer: det å bevise en melding ble opprettet av en bestemt enhet, og det å bevise en melding ble ikke tuklet med etter at den ble opprettet. En måte å oppfylle begge disse målene er ved bruk av digitale signaturer.

Digitale signaturer avhenger sterkt av en gren av kryptografi kjent som kryptering med offentlig nøkkel. Offentlige nøkkelalgoritmer er preget av det faktum at de stoler på et matchet nøkkelpar (en privat og en offentlig) i stedet for en enkelt nøkkel. En enhet holder sin private nøkkel hemmelig, men gjør sin offentlige nøkkel tilgjengelig.

En digital signaturalgoritme tar som inngang en melding og en enhets private nøkkel, og genererer en digital signatur. Den digitale signaturen er opprettet på en slik måte at hvem som helst kan ta enhetens offentlige nøkkel og bruke den til å verifisere at enheten faktisk signerte den aktuelle meldingen. Videre, hvis den opprinnelige meldingen er tuklet med, kan ikke signaturen lenger bekreftes. Digitale signaturer gir en ytterligere fordel: når en enhet har signert og distribuert en melding, er det umulig for opphavsmannen å nekte å ha signert meldingen (uten å påstå at hans eller hennes private nøkkel ble stjålet, uansett).

Av motorer og leverandører

Java Cryptography API definerer Java-verktøysettet for sikkerhet og autentisering. Java Cryptography Architecture (JCA) beskriver hvordan du bruker API. For å sikre den høyeste grad av fleksibilitet for både utvikleren og sluttbrukeren, tar JCA to ledende prinsipper:

  1. Arkitekturen skal støtte algoritmeuavhengighet og utvidbarhet. En utvikler må kunne skrive applikasjoner uten å knytte dem for nært til en bestemt algoritme. I tillegg, når nye algoritmer utvikles, må de enkelt integreres med eksisterende algoritmer.

  2. Arkitekturen skal støtte uavhengighet ved implementering og interoperabilitet. En utvikler må kunne skrive applikasjoner uten å knytte dem til en bestemt leverandørs implementering av en algoritme. I tillegg må implementeringer av en algoritme levert av forskjellige leverandører samhandle.

For å tilfredsstille disse to kravene, baserte utviklerne av Java Cryptography API sin design på et system av motorer og leverandører.

Motorer produserer forekomster av meldingsfordøyende generatorer, generatorer for digital signatur og nøkkelpargeneratorer. Hver forekomst brukes til å utføre sin tilsvarende funksjon.

Den kanoniske motoren i JCA er en klasse som gir en statisk metode (eller metoder) som heter getInstance (), som returnerer en forekomst av en klasse som implementerer en kryptografisk signifikant algoritme. De getInstance () metoden kommer både i ett-argument og to-argument form. I begge tilfeller er det første argumentet navnet på algoritmen. JCA gir en liste over standardnavn, men ikke alle vil bli gitt i en bestemt utgivelse. Det andre argumentet velger en leverandør.

SUN-leverandøren

Bare én leverandør - SOL - leveres i JDK 1.1. SUN gir både en implementering av NIST Digital Signature Algorithm (DSA), og en implementering av MD5 og NIST SHA-1 meldingsfordøyelsesalgoritmer.

KlassemeldingDigest

Vi begynner med å se på kode som genererer en meldingsfordeling fra en melding.

MessageDigest messagedigest = MessageDigest.getInstance ("SHA");

MessageDigest messagedigest = MessageDigest.getInstance ("SHA", "SUN");

Som jeg nevnte for bare et øyeblikk siden, getInstance () metoden kommer i to smaker. Den første krever at bare algoritmen spesifiseres. Den andre krever at både algoritmen og leverandøren spesifiseres. Begge returnerer en forekomst av en klasse som implementerer SHA-algoritmen.

Deretter sender vi meldingen gjennom meldingsfordøyelsesgeneratoren.

int n = 0; byte [] rgb = ny byte [1000]; mens ((n = inputstreamMessage.read (rgb))> -1) {messagedigest.update (rgb, 0, n); }

Her antar vi at meldingen er tilgjengelig som en inngangsstrøm. Denne koden fungerer bra for store meldinger av ukjent lengde. De Oppdater() metoden godtar også en enkelt byte som et argument for meldinger med noen få byte i lengde, og en byte-matrise for meldinger av en fast eller forutsigbar størrelse.

rgb = messagedigest.digest ();

Det siste trinnet innebærer å generere meldingen fordøye seg selv. Den resulterende sammendraget er kodet i en rekke byte.

Som du kan se, skjuler JCA praktisk alle implementeringer og algoritmespesifikke detaljer på lavt nivå, slik at du kan jobbe på et høyere, mer abstrakt nivå.

Selvfølgelig er en av risikoen ved en slik abstrakt tilnærming den økte sannsynligheten for at vi ikke vil gjenkjenne feilaktig resultat som skyldes feil. Gitt rollen som kryptografi, kan dette være et betydelig problem.

Vurder "off-by-one" -feilen i oppdateringslinjen nedenfor:

int n = 0; byte [] rgb = ny byte [1000]; mens ((n = inputstreamMessage.read (rgb))> -1) {messagedigest.update (rgb, 0, n - 1); }

C-, C ++- og Java-programmerere bruker limit-minus-one-idiomet så ofte at det blir nesten automatisk å skrive det - selv når det ikke passer. Koden ovenfor kompileres, og den kjørbare filen kjører uten feil eller advarsel, men den resulterende meldingsfordøyelsen vil være feil.

Heldigvis er JCA gjennomtenkt og godt designet, noe som gjør potensielle fallgruver som den ovenfor relativt sjeldne.

Før vi går videre til nøkkelpargeneratorer, ta en titt på

MessageDigestGenerator, den komplette kildekoden for et program som genererer en meldingsfordeling.

Klasse KeyPairGenerator

For å generere en digital signatur (og kryptere data) trenger vi nøkler.

Nøkkelgenerering, i sin algoritmeuavhengige form, er ikke vesentlig vanskeligere enn å lage og bruke en meldingsfordøyelse.

KeyPairGenerator keypairgenerator = KeyPairGenerator.getInstance ("DSA");

Som i meldingsfordøyelseseksemplet ovenfor, oppretter denne koden en forekomst av en klasse som genererer DSA-kompatible nøkler. Et annet (om nødvendig) argument spesifiserer leverandøren.

Etter at en nøkkelpar-generatorforekomst er opprettet, må den initialiseres. Vi kan initialisere nøkkelpargeneratorer på en av to måter: algoritmeuavhengig eller algoritmeavhengig. Hvilken metode du bruker, avhenger av hvor mye kontroll du vil ha over det endelige resultatet.

keypairgenerator.initialize (1024, nye SecureRandom ());

Nøkler basert på forskjellige algoritmer er forskjellige i hvordan de genereres, men de har en parameter til felles - nøkkelen styrke. Styrke er et relativt begrep som omtrent tilsvarer hvor vanskelig nøkkelen vil være å "bryte". Hvis du bruker den algoritmeuavhengige initialisereren, kan du bare spesifisere styrken - noen algoritmeavhengige verdier antar rimelige standarder.

DSAKeyPairGenerator dsakeypairgenerator = (DSAKeyPairGenerator) tastaturgenerator; DSAParams dsaparams = nye DSAParams () {private BigInteger p = BigInteger (...); private BigInteger q = BigInteger (...); private BigInteger g = BigInteger (...); offentlig BigInteger getP () {retur p; } offentlig BigInteger getQ () {return q; } offentlig BigInteger getG () {return g; }}; dsakeypairgenerator.initialize (dsaparams, nye SecureRandom ());

Selv om standardinnstillingene vanligvis er gode nok, er det tilgjengelig hvis du trenger mer kontroll. La oss anta at du brukte motoren til å lage en generator med DSA-kompatible nøkler, som i koden ovenfor. Bak kulissene lastet motoren opp og instanserte en forekomst av en klasse som implementerer DSAKeyPairGenerator grensesnitt. Hvis vi kaster den generiske nøkkelpargeneratoren vi fikk til DSAKeyPairGenerator, får vi da tilgang til den algoritmeavhengige metoden for initialisering.

For å initialisere en DSA-nøkkelpargenerator trenger vi tre verdier: prime P, subprime Q, og basen G. Disse verdiene blir fanget i en indre klasseinstans som sendes til initialisere () metode.

De SecureRandom klasse gir en sikker kilde til tilfeldige tall som brukes i nøkkelpargenerering.

return keypairgenerator.generateKeyPair ();

Det siste trinnet innebærer å generere selve nøkkelparet.

Før vi går videre til digitale signaturer, ta en titt på KeyTools, den komplette kildekoden for et program som genererer et nøkkelpar.

Klassesignatur

Opprettelse og bruk av en forekomst av Signatur klasse er ikke vesentlig forskjellig fra noen av de to foregående eksemplene. Forskjellene ligger i hvordan forekomsten brukes - enten for å signere eller for å bekrefte en melding.

Signatur signatur = Signature.getInstance ("DSA");

Akkurat som før bruker vi motoren for å få en forekomst av riktig type. Hva vi gjør videre, avhenger av om vi signerer eller bekrefter en melding.

signatur.initSign (privateekey);

For å signere en melding, må vi først initialisere signaturforekomsten med den private nøkkelen til enheten som signerer meldingen.

signatur.initVerify (offentlig nøkkel);

For å bekrefte en melding, må vi initialisere signaturforekomsten med den offentlige nøkkelen til enheten som hevder at den signerte meldingen.

int n = 0; byte [] rgb = ny byte [1000]; mens ((n = inputstreamMessage.read (rgb))> -1) {signatur.oppdatering (rgb, 0, n); }

Neste, uansett om vi signerer eller bekrefter eller ikke, må vi sende meldingen gjennom signaturgeneratoren. Du vil legge merke til hvor lik prosessen med det tidligere eksemplet på å generere en meldingsfordøyelse.

Det siste trinnet består i å generere signaturen eller verifisere en signatur.

rgb = signatur.sign ();

Hvis vi signerer en melding, blir skilt() metoden returnerer signaturen.

signatur.verify (rgbSignature);

Hvis vi verifiserer signaturen som tidligere er generert fra en melding, må vi bruke bekrefte() metode. Det tar som en parameter den tidligere genererte signaturen og avgjør om den fremdeles er gyldig.

Før vi avslutter ting, ta en titt på Sign.java, den komplette kildekoden for et program som signerer en melding, og Verify.java, den komplette kildekoden for et program som bekrefter en melding.

Konklusjon

Hvis du bevæpner deg med verktøyene og teknikkene jeg har presentert denne måneden, er du mer enn klar til å sikre applikasjonene dine. Java Cryptography API gjør prosessen nesten uanstrengt. Utgivelse 1.2 av Java Developers Kit lover enda mer. Følg med.

Neste måned drar jeg tilbake til mellomvareområdet. Jeg skal ta litt RMI, noen tråder og en haug med kode, og vise deg hvordan du bygger din egen meldingsorienterte mellomvare.

Todd Sundsted har skrevet programmer siden datamaskiner ble tilgjengelig i praktiske stasjonære modeller. Selv om han opprinnelig var interessert i å bygge distribuerte objektapplikasjoner i C ++, gikk Todd videre til Java-programmeringsspråket da det ble det åpenbare valget for den slags ting. I tillegg til å skrive, er Todd president for Etcee som tilbyr opplæring, veiledning, rådgivning og programvareutviklingstjenester.

Lær mer om dette emnet

  • Last ned den fullstendige kildekoden //www.javaworld.com/jw-01-1999/howto/jw-01-howto.zip
  • Oversikt over Java Security API //www.javasoft.com/products/jdk/1.1/docs/guide/security/JavaSecurityOverview.html
  • Java Cryptography Architecture //www.javasoft.com/products/jdk/1.1/docs/guide/security/CryptoSpec.html
  • Suns Java-sikkerhetsside //java.sun.com/security/index.html
  • Vanlige spørsmål om RSA om kryptografi //www.rsa.com/rsalabs/faq/
  • Kryptografisk policy og informasjon //www.crypto.com/
  • Les Todds forrige How-To Java-kolonner //www.javaworld.com/topicalindex/jw-ti-howto.html

Denne historien, "In Java we trust" ble opprinnelig utgitt av JavaWorld.

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