A program célja

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 használata

Prímek előállítása Véletlen szám előállítása Rejtés Paraméterek Fejtés

Prímek előállítása

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).

Véletlen szám 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ő.

Rejtés

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.

Fejtés

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.

Paraméterek

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.

Technikai dokumentáció

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):