Programiranje

V Javi zaupamo

Zaupati vsem? Ne zaupaj nikomur? Sliši se nekako kot Datoteke X, toda ko gre za zaupne podatke, je vedeti, komu zaupate, enako pomembno kot vedeti, kaj jim zaupate. Ta koncept je tako pomemben za aplikacije kot za ljudi. Navsezadnje smo vloge vložili kot skrbnike naših informacij in skrbnike naših virov. Res je v celotnem podjetju - aplikacije vsebujejo ključne informacije o našem podjetju in naših strankah - in res na namizju. Ne morem vam povedati, kolikokrat so me vprašali, kako napisati programček, ki skenira uporabnikov pogon, tako da lahko en uporabnik ukaže brskalnik drugega uporabnika ali zajame zasebne podatke.

Java, ki je platforma za razvoj omrežij v resnici, se je morala problema zaupanja lotiti na glavo. Rezultat sta Java Security API in Java Cryptography Architecture.

Kratek pogled nazaj

Preden se brezglavo potopim v API-je, kodo in komentarje, bi rad na kratko ponovno pregledal prejšnjo mesečno razpravo. Če se nam pridružite prvič, boste morda želeli varnostno kopirati mesec dni in prebrati »Podpisano in dostavljeno: Uvod v varnost in preverjanje pristnosti«. Ta stolpec vsebuje temeljit uvod v vse izraze in koncepte, ki jih bom uporabljal ta mesec.

Varnost in preverjanje pristnosti obravnavata dve ključni pomisleki: dokazovanje sporočila je ustvarila določena entiteta in dokazovanje sporočila, ko sporočilo ni bilo poseženo po njegovem ustvarjanju. Oba cilja lahko dosežemo z uporabo digitalnih podpisov.

Digitalni podpisi so močno odvisni od veje kriptografije, znane kot kriptografija z javnim ključem. Za algoritme javnega ključa je značilno, da se zanašajo na izbrani par ključev (enega zasebnega in enega javnega) in ne na en sam ključ. Podjetje hrani svoj zasebni ključ v tajnosti, vendar da svoj javni ključ na voljo.

Algoritem digitalnega podpisa vzame za vnos sporočilo in zasebni ključ entitete ter ustvari digitalni podpis. Digitalni podpis je ustvarjen tako, da lahko vsakdo vzame javni ključ entitete in z njim preveri, ali je entiteta dejansko podpisala zadevno sporočilo. Poleg tega, če je bilo izvirno sporočilo spremenjeno, podpisa ni več mogoče preveriti. Digitalni podpisi prinašajo eno dodatno prednost: ko je subjekt podpisal in razposlal sporočilo, njegov začetnik ne more zanikati, da je podpisal sporočilo (ne da bi trdil, da je bil njegov zasebni ključ vseeno ukraden).

Od motorjev in ponudnikov

API za kriptografijo Java določa komplet orodij Java za varnost in preverjanje pristnosti. Java Cryptography Architecture (JCA) opisuje, kako uporabljati API. Da bi zagotovil najvišjo stopnjo prilagodljivosti tako za razvijalca kot za končnega uporabnika, JCA upošteva dve vodilni načeli:

  1. Arhitektura mora podpirati neodvisnost in razširljivost algoritma. Razvijalec mora biti sposoben pisati programe, ne da bi jih preveč vezal na določen algoritem. Poleg tega jih je treba z razvojem novih algoritmov enostavno integrirati z obstoječimi algoritmi.

  2. Arhitektura mora podpirati neodvisnost izvajanja in interoperabilnost. Razvijalec mora biti sposoben pisati aplikacije, ne da bi jih vezal na izvedbo algoritma določenega prodajalca. Poleg tega morajo implementacije algoritma, ki jih ponujajo različni ponudniki, medsebojno delovati.

Da bi izpolnili ti dve zahtevi, so razvijalci Java Cryptography API zasnovo zasnovali na sistemu motorjev in ponudnikov.

Motorji proizvajajo primerke generatorjev prebavnih sporočil, generatorjev digitalnega podpisa in generatorjev parov ključev. Vsak primerek se uporablja za izvajanje ustrezne funkcije.

Kanonični stroj v JCA je razred, ki zagotavlja imenovano statično metodo (ali metode) getInstance (), ki vrne primerek razreda, ki izvaja kriptografsko pomemben algoritem. The getInstance () metoda je v obliki enega argumenta in dvoargumenta. V obeh primerih je prvi argument ime algoritma. JCA ponuja seznam standardnih imen, vendar ne bodo vsa navedena v nobeni posebni izdaji. Drugi argument izbere ponudnika.

Ponudnik SUN

Samo en ponudnik - Sonce - je na voljo v JDK 1.1. SUN ponuja tako izvajanje algoritma digitalnega podpisa NIST (DSA) kot tudi izvedbo algoritmov za zbiranje sporočil MD5 in NIST SHA-1.

Razred MessageDigest

Začeli bomo s pregledovanjem kode, ki iz sporočila ustvari povzetke sporočil.

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

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

Kot sem omenil malo prej, getInstance () metoda je v dveh okusih. Za prvo je treba določiti samo algoritem. Za drugo je treba navesti algoritem in ponudnika. Oba vrneta primerek razreda, ki izvaja algoritem SHA.

Nato sporočilo posredujemo skozi generator povzetka sporočil.

int n = 0; bajt [] rgb = nov bajt [1000]; while ((n = inputstreamMessage.read (rgb))> -1) {messagedigest.update (rgb, 0, n); }

Tu domnevamo, da je sporočilo na voljo kot vhodni tok. Ta koda dobro deluje za velika sporočila neznane dolžine. The nadgradnja() metoda sprejme tudi en bajt kot argument za sporočila z dolžino nekaj bajtov in matriko bajtov za sporočila fiksne ali predvidljive velikosti.

rgb = messagedigest.digest ();

Zadnji korak vključuje ustvarjanje samega povzetka sporočila. Nastali izvleček je kodiran v nizu bajtov.

Kot lahko vidite, JCA prikladno skriva vse podrobnosti izvedbe na nizki ravni in podrobnosti, specifične za algoritem, kar vam omogoča delo na višji, bolj abstraktni ravni.

Seveda je eno od tveganj takšnega abstraktnega pristopa večja verjetnost, da ne bomo prepoznali napačnih rezultatov, ki so posledica napak. Glede na vlogo kriptografije je to lahko velik problem.

Razmislite o napaki "off-by-one" v spodnji vrstici posodobitve:

int n = 0; bajt [] rgb = nov bajt [1000]; while ((n = inputstreamMessage.read (rgb))> -1) {messagedigest.update (rgb, 0, n - 1); }

Programerji C, C ++ in Java tako pogosto uporabljajo idiom limit-minus-one, da njegovo tipkanje postane skoraj samodejno - tudi kadar to ni primerno. Zgornja koda se bo zbrala in izvedljiva datoteka se bo izvajala brez napak ali opozoril, vendar bo rezultat povzetka sporočil napačen.

Na srečo je JCA dobro premišljen in dobro zasnovan, zato so potencialne pasti, kot je zgoraj, razmeroma redke.

Preden preidemo na generatorje parov ključev, si oglejte

MessageDigestGenerator, celotna izvorna koda za program, ki generira povzetke sporočil.

Razred KeyPairGenerator

Za ustvarjanje digitalnega podpisa (in šifriranje podatkov) potrebujemo ključe.

Ustvarjanje ključev v svoji obliki, neodvisni od algoritma, ni bistveno težje kot ustvarjanje in uporaba povzetka sporočil.

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

Kot v zgornjem primeru povzetka sporočil, tudi ta koda ustvari primerek razreda, ki generira ključe, združljive z DSA. Drugi (po potrebi) argument določa ponudnika.

Ko je ustvarjen primerek generatorja parov ključev, ga je treba inicializirati. Generatorje parov ključev lahko inicializiramo na dva načina: neodvisen od algoritma ali odvisen od algoritma. Katero metodo boste uporabili, je odvisno od obsega nadzora nad končnim rezultatom.

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

Ključi, ki temeljijo na različnih algoritmih, se razlikujejo po načinu ustvarjanja, vendar jim je skupen en parameter - ključi moč. Moč je relativni izraz, ki približno ustreza temu, kako težko bo ključ "zlomljen". Če uporabite inicializator, neodvisen od algoritma, lahko določite samo moč - vse vrednosti, ki so odvisne od algoritma, imajo razumne privzete vrednosti.

DSAKeyPairGenerator dsakeypairgenerator = (DSAKeyPairGenerator) keypairgenerator; DSAParams dsaparams = new DSAParams () {private BigInteger p = BigInteger (...); zasebno BigInteger q = BigInteger (...); zasebno BigInteger g = BigInteger (...); javni BigInteger getP () {return p; } javni BigInteger getQ () {return q; } javni BigInteger getG () {return g; }}; dsakeypairgenerator.initialize (dsaparams, novo SecureRandom ());

Privzete vrednosti so običajno dovolj dobre, če pa potrebujete več nadzora, je na voljo. Predpostavimo, da ste z motorjem ustvarili generator ključev, združljivih z DSA, kot v zgornji kodi. V zakulisju je motor naložil in ustvaril primerek razreda, ki izvaja DSAKeyPairGenerator vmesnik. Če predlagamo generični generator parov ključev, ki smo ga prejeli DSAKeyPairGenerator, nato dobimo dostop do algoritma odvisne metode inicializacije.

Za inicializacijo generatorja parov ključev DSA potrebujemo tri vrednosti: prime P, subprime Q, in osnovo G. Te vrednosti so zajete v primerku notranjega razreda, ki se posreduje inicializiraj () metoda.

The SecureRandom class zagotavlja varen vir naključnih števil, ki se uporabljajo pri generiranju parov ključev.

vrni keypairgenerator.generateKeyPair ();

Zadnji korak vključuje ustvarjanje samega para ključev.

Preden preidemo na digitalne podpise, si oglejte KeyTools, popolno izvorno kodo programa, ki ustvari par ključev.

Podpis razreda

Ustvarjanje in uporaba primerka Podpis razred se bistveno ne razlikuje od nobenega od prejšnjih primerov. Razlike so v tem, kako se primerek uporablja - bodisi za podpisovanje bodisi za preverjanje sporočila.

Podpis podpisa = Signature.getInstance ("DSA");

Tako kot prej uporabljamo motor, da dobimo primerek ustrezne vrste. Kaj bomo storili naprej, je odvisno od tega, ali podpisujemo ali preverjamo sporočilo.

signature.initSign (privatekey);

Če želite podpisati sporočilo, moramo primerek podpisa najprej inicializirati z zasebnim ključem entitete, ki podpisuje sporočilo.

signature.initVerify (publickey);

Če želimo preveriti sporočilo, moramo primerek podpisa inicializirati z javnim ključem subjekta, ki trdi, da je podpisal sporočilo.

int n = 0; bajt [] rgb = nov bajt [1000]; while ((n = inputstreamMessage.read (rgb))> -1) {signature.update (rgb, 0, n); }

Nato moramo, ne glede na to, ali se podpisujemo ali preverjamo, sporočilo prenesti skozi generator podpisov. Opazili boste, kako podoben je postopek kot prejšnji primer ustvarjanja povzetka sporočila.

Zadnji korak je sestavljen iz ustvarjanja podpisa ali preverjanja podpisa.

rgb = signature.sign ();

Če podpisujemo sporočilo, se znak () vrne podpis.

signature.verify (rgbSignature);

Če preverjamo podpis, ki je bil prej ustvarjen iz sporočila, moramo uporabiti preveri () metoda. Kot parameter vzame predhodno ustvarjeni podpis in določi, ali je še vedno veljaven ali ne.

Preden stvari zaključimo, si oglejte Sign.java, popolno izvorno kodo programa, ki podpiše sporočilo, in Verify.java, popolno izvorno kodo programa, ki preverja sporočilo.

Zaključek

Če se oborožite z orodji in tehnikami, ki sem jih predstavil ta mesec, boste več kot pripravljeni zaščititi svoje aplikacije. API za kriptografijo Java omogoča postopek skoraj brez napora. Izdaja 1.2 kompleta za razvijalce Java obljublja še več. Ostani na vezi.

Naslednji mesec se vrnem na ozemlje vmesne programske opreme. Vzel bom malo RMI, nekaj navojev in kup kode ter vam pokazal, kako zgraditi svojo lastno vmesniško programsko opremo, usmerjeno v sporočila.

Todd Sundsted piše programe, odkar so računalniki na voljo v priročnih namiznih modelih. Čeprav se je Todd prvotno zanimal za izdelavo porazdeljenih objektnih aplikacij v jeziku C ++, je Todd prešel na programski jezik Java, ko je postal očitna izbira za takšno stvar. Poleg pisanja je Todd predsednik podjetja Etcee, ki ponuja storitve usposabljanja, mentorstva, svetovanja in razvoja programske opreme.

Preberite več o tej temi

  • Prenesite celotno izvorno kodo //www.javaworld.com/jw-01-1999/howto/jw-01-howto.zip
  • Pregled Java Security API //www.javasoft.com/products/jdk/1.1/docs/guide/security/JavaSecurityOverview.html
  • Javna kriptografska arhitektura //www.javasoft.com/products/jdk/1.1/docs/guide/security/CryptoSpec.html
  • Sun's Java Security Page //java.sun.com/security/index.html
  • Pogosta vprašanja o kriptografiji RSA //www.rsa.com/rsalabs/faq/
  • Kriptografska politika in informacije //www.crypto.com/
  • Preberite prejšnje Toddove stolpce Java-How-To //www.javaworld.com/topicalindex/jw-ti-howto.html

To zgodbo "V Javi zaupamo" je prvotno objavil JavaWorld.

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