Az RSA Demo Java applet az RSA eljárást mutatja meg működés közben. Mivel ez a program demonstrációs célokat szolgál, ezért nem azon van a hangsúly, hogy megmutassuk, hogyan kell RSA titkosító programot írni, hanem magának az eljárásnak a látványos, interaktív bemutatása volt a cél. Ha valakinek mégis egy hatékony, gyors RSA-implementációra van szüksége, az eljárás ismeretében és az RSA Demo program birtokában maga is könnyen megírhatja az algoritmust.
Ez a program legfeljebb 10 számjegyű számokkal dolgozik. A prímek legfeljebb 5 számjegyűek lehetnek; szorzatuk, és a véletlen e szám lehet 10 jegyű. Ez lehetőséget biztosít arra, hogy leellenőrizzük: a véletlenszerűen előállított prímek valóban prímek. Más megkötés azonban nincs, minden egyéb funkció átültethető egy igazi RSA programba.
A következőkben a program használata, működése és felépítése kerül bemutatásra.
A program alapértelmezés szerint [0; 46340] intervallumban keres prímeket. Ezt az intervallumot módosíthatjuk, ha az Intervallumban pontot jelöljük ki. Ekkor meg kell adni az intervallum alsó és felső határát. Az alsó határ legalább 3 kell, hogy legyen, a felső határ 46340 lehet. A felső határ nem lehet kevesebb, mint Legalább + 80. Ennél rövidebb intervallumban ugyanis előfordulhat, hogy a program nem talál prímet.
A Prímek előállítása gombra kattintva a program véletlenszerűen generál két prímszámot. A p1 és p2 mezőkben nyomon követhető az előállítás folyamata. Érdemes különböző hosszúságú intervallumok megadásával kísérletezni: megfigyelhetjük, milyen változatos a prímek elhelyezkedése az egész számok között (Lásd még: Prímek előállítása).
Az RSA eljáráshoz szükséges véletlen számot több módon is elő lehet állítani.
Ha a Random-generátorral pontot választjuk, akkor a Math.random() függvény meghívásával a program maga állítja elő a véletlen számot. Ez a megoldás gyors, ám mivel a számítógép random-generátorát használja, ami nem véletlen számot, hanem pszeudo-random számot állít elő, ezért ez az eljárás egy valóságos RSA-alkalmazásban nem használatos.
Jobb megoldás lenne, ha valamilyen zajt vehetnénk alapul, ám a Java nyelv nem támogatja a hardverközeli megoldásokat, ezért a program a felhasználói interakció lehetőségét kínálja fel.
Ha az Egérmozgatással pontot választjuk, akkor a program a felhasználó által véletlenszerűen mozgatott egér kurzorának koordinátáiból állít elő egy véletlen számot. A képernyőn nyomon követhető a véletlen szám előállításának folyamata.
Ha a Billentyű leütésekkel pontot választjuk, a program a leütött billentyűk kódját veszi alapul a véletlen szám generálásához. Itt is nyomon követhető az előállítás folyamata.
A véletlengenerálás akkor kezdődik meg, amikor a felhasználó már előállította a prímeket, és Az "e" szám előállítása gombra kattint.
Megjegyzés
A véletlen szám felhasználói interakcióval történő előállítása csak akkor lehetséges, ha a prímek szorzata elegendően nagy. Körülbelül 1100-nál van a határ, ennél kisebb szorzat esetében csak a random-generátoros megoldás elérhető.
Ha előállítottuk a prímeket, és a véletlen szám is kész, akkor gépeljünk be valamit (például: Hello, világ!) a Rejteni kívánt szöveg mezőbe. Alatta a begépelt karakterek kódja jelenik meg szóközökkel elválasztva. Ha a Rejtés! gombra kattintunk, a program az RSA eljárást használva titkosítja a szöveget. A titkosított szöveg kódja mezőben jelennek meg az elrejtett karaktereknek megfelelő számok.
Miután elrejtettük a begépelt szöveget, a Fejtés! gombra kattintva a program felfedi a titkot: megfejti a titkosított karakterkód-sorozatot. A megfelelő mezőkben viszontláthatjuk az eredeti szöveg karaktereit leíró számsorozatot, illetve magát az eredeti szöveget is.
Ezen a táblán az RSA eljárás működéséhez szükséges paraméterek láthatók. A nyilvános számok, azaz a prímek szorzata és a véletlen e szám zöld, míg a titkos adatok, tehát a prímek, az m és a d számok piros betűkkel vannak kiírva.
A következőkben a program felépítése kerül ismertetésre. A forráskóddal együtt célszerű áttanulmányozni.
Euclid
public int GCD(long a, long b);
meghatározza a és b legnagyobb közös osztóját; ha a kisebb, mint b, akkor a két számot felcseréli
public int Invert(long e, long m);
meghatározza az e szám multiplikatív inverzét modulo m
GreatNumPow
private double log2(int x);
meghatározza a log2(x) értéket, amelyre az int típus hossza miatt van szükség: Java-ban nincs sizeof operátor
private boolean memberOf(int a[], int item);
megvizsgálja, hogy az item szám eleme-e az egészekből álló a tömbnek
private int PowerOfTwo(int e);
megállapítja, hogy hol van az e szám MSB-je, azaz melyik az a legnagyobb kettő-hatvány, amelyik kisebb, mint e
public int doGreatNumPow(int x, int e, int n);
elvégzi az xe (mod n) hatványozást
Primes
public boolean isPrime(int x);
eldönti x-ről, hogy prímszám-e
public int generatePrime();
0 és Integer.MAX_VALUE között generál egy prímet
public int generatePrime(int rangeMin, int rangeMax);
rangeMin és rangeMax között generál egy prímet
RSAdemo
public int p1; | az egyik prím |
public int p2; | a másik prím |
public int n; | a prímek szorzata |
public int m; | (p1 - 1) . (p2 - 1) értéke |
public int e; | véletlen szám |
public int d; | e multiplikatív inverze (mod m) |
public int encryptedText[]; | tömb, amely a begépelt szöveg karakterkódjainak titkosítását tárolja |
public int numChars; | a begépelt szöveg hossza |
public int rsaMaxInt; | az egész típus maximális értékének a négyzetgyöke |
public RSAdemo();
konstruktor: alaphelyzetbe állítja az osztályt
private void CalculateProducts();
előállítja az n és m szorzatokat
public String doDecryptText();
megfejti a titkosított szöveget
public String doEncryptText(String toHide);
karakterenként titkosítja a toHide stringet, a titkosított kódokat az encryptedText tömbben tárolja
public void GenerateE() throws Exception;
ha már léteznek a prímek, előállít egy véletlen számot, mely relatív prím m-mel, és értékét eltárolja e-ben; meghatározza e inverzét (mod m); értékét eltárolja d-ben; ha még nem léteznek a prímek, kivételt generál
public boolean GenerateE(int randomE);
egy korábban már létező randomE véletlen szám alapján előállít egy véletlen számot, mely relatív prím m-mel, és értékét eltárolja e-ben; meghatározza e inverzét (mod m); értékét eltárolja d-ben (nem kell a prímek létezését ellenőrizni, mivel a randomE csak úgy jöhetett létre, hogy korábban már hívtuk a GenerateE() függvényt, tehát a prímek léteznek)
public synchronized int generateOnePrime(int max, int offset, Label lPrime);
keres egy prímet az [offset; max + offset] intervallumban, és frissíti az lPrime címke értékét - ha nem prím, amit talált, akkor vár 50 msec-ot, majd folytatja a keresést
public void GeneratePrimes();
0 és Integer.MAX_VALUE között generál két prímet; értéküket eltárolja p1-ben és p2-ben
public void GeneratePrimes(int rangeMin, int rangeMax);
rangeMin és rangeMax között generál két prímet; értéküket eltárolja p1-ben és p2-ben
public int generateRandomE(int range, int m);
előállít egy olyan véletlen számot a [0; range] intervallumban, amely relatív prím m-mel
public String getAppletInfo();
az appletről ad információt
public void init();
automatikusan lefutó függvény: létrehozza a grafikus felületet, és a többi osztály egy-egy példányát
public void resetRSA();
alaphelyzetbe állítja a változókat
CancelButton
public CancelButton(RSAGUI parent);
konstruktor: létrehozza az osztály egy példányát, saját magának is elhelyezi a parent-ben (azaz az applet grafikus felületében) található Listener-eket
public void Show(int x, int y, int w, int h);
a megadott [x; y] koordinátáknál elhelyezi a w szélességű és h magasságú gombot
public void Hide();
leveszi a gombot a képernyőről
public void update(Graphics g);
frissíti (újrarajzolja) a grafikus felületet
public void mouseReleased(MouseEvent e);
eseménykezelő: ha az egérgomb felengedésekor a gomb felett tartózkodik a kurzor, akkor a gombot megnyomottnak tekinti, azaz véget vet a felhasználói interakcióval történő véletlengenerálásnak (ez esetben természetesen nincs véletlen szám előállítva)
public void mouseMoved(MouseEvent evt);
eseménykezelő: ha az egeret a gomb fölé mozgatjuk, átszínezi a gombot, egyébként visszaállítja az alapszínt
RSAGUI
private int RandomE; | a felhasználói interakcióval történő véletlengenerálás köztes értékét tárolja |
private int coeff; | egy szorzó, amely a véletlen szám előállításához használunk a folyamat felgyorsítása érdekében: mind a billentyűkód, mind az egérkoordináták a 100-as nagyságrendbe esnek, holott nekünk akár kilenc számjegyű számra is szükségünk lehet |
private int CreationMethod; | a véletlen előállításának módját tartalmazza |
public Label prime1; | címke, melyben p1 értéke jelenik meg |
public Label prime2; | címke, melyben p2 értéke jelenik meg |
public Label n; | címke, melyben n értéke jelenik meg |
public Label m; | címke, melyben m értéke jelenik meg |
public Label e; | címke, melyben e értéke jelenik meg |
public Label d; | címke, melyben d értéke jelenik meg |
public Label multiplier; | címke, melyben coeff értéke jelenik meg |
public Label to_try; | címke, melyben randomE értéke jelenik meg |
public Label key_code; | címke, melyben begépelt billentyűkód értéke jelenik meg |
public RSAGUI(RSAdemo rsademo);
konstruktor: létrehozza az osztály egy példányát, létrehozza a grafikus felület elemeit, és elhelyezi a Listener-eket
private void clearAllFields();
minden címkét üresre állít
private void clearEFields();
a véletlen számhoz kapcsolódó címkéket üresre állítja
private void createRandomNumber(int base);
a base szám alapján a coeff szorzó segítségével előállítja a randomE számot
public void setCreationMethod(Object choice);
a choice objektum alapján beállítja a véletlen előállítás módját, melyet a CreationMethod változóban tárol
private void setCryptFields();
a titkosításhoz szükséges gombokat és szövegmezőket a megfelelő állapotba állítja
public void paint(Graphics g);
megrajzolja a grafikus felületet
public void update(Graphics g);
újrarajzolja a grafikus felületet
public void actionPerformed(ActionEvent evt);
eseménykezelő: a megnyomott gomb hatására következőket hajtja végre (pontosan az egyiket):
public void itemStateChanged(ItemEvent evt);
eseménykezelő: az átváltott rádiógomb hatására következőket hajtja végre (pontosan az egyiket):
public void keyPressed(KeyEvent evt);
eseménykezelő: akkor aktív, ha a billentyűleütésekkel szeretnénk véletlen számot előállítani; ekkor a leütött billentyűkód alapján előállít egy véletlen számot, és megvizsgálja, hogy azonos nagyságrendbe esik-e m-mel
public void mouseMoved(MouseEvent evt);
eseménykezelő: akkor aktív, ha a egérmozgatással szeretnénk véletlen számot előállítani; ekkor az egérkoordináták alapján előállít egy véletlen számot, és megvizsgálja, hogy azonos nagyságrendbe esik-e m-mel
public void mouseReleased(MouseEvent e);
eseménykezelő: ha egérmozgatással szeretnénk véletlen számot előállítani, de megnyomtuk a Mégse gombot, véget vet a felhasználói interakcióval történő véletlengenerálásnak (ez esetben természetesen nincs véletlen szám előállítva)
public void textValueChanged(TextEvent evt);
eseménykezelő: a rejtéssel / fejtéssel, és az intervallumban történő prímkereséssel kapcsolatos szövegmezőket figyeli, és a következőket hajtja végre (pontosan az egyiket):