36
Università degli Studi di Salerno Facoltà di Scienze Matematiche, Fisiche e Naturali Corso di laurea Magistrale in Informatica Corso di SISTEMI OPERATIVI II Fattorizzazione di numeri interi con Java RMI Studenti: Valerio Cinque 0522500098 Francesco Testorio 0522500075 Domenico Viscito 0522500024 Docente: Prof. G. Cattaneo Anno Accademico 2010/2011

Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Embed Size (px)

Citation preview

Page 1: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Università degli Studi di Salerno

Facoltà di Scienze Matematiche, Fisiche e Naturali

Corso di laurea Magistrale in Informatica

Corso di SISTEMI OPERATIVI II

Fattorizzazione di numeri interi con Java RMI

Studenti:

Valerio Cinque 0522500098

Francesco Testorio 0522500075

Domenico Viscito 0522500024

Docente:

Prof. G. Cattaneo

Anno Accademico 2010/2011

Page 2: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

INDICE

1. INTRODUZIONE .................................................................................................................................................. 2

1.1 CRITTOGRAFIA RSA ............................................................................................................................................... 3

2. ALGORITMI DI FATTORIZZAZIONE ...................................................................................................................... 7

2.1 IL CRIVELLO QUADRATICO ....................................................................................................................................... 8

3. JAVA RMI ..........................................................................................................................................................10

3.1 ARCHITETTURA DI RMI ......................................................................................................................................... 11

3.2 RMI: IL PROCESSO DI CREAZIONE ............................................................................................................................ 12

3.3 IMPLEMENTARE UN COMPUTE SERVER .................................................................................................................... 13

3.4 IMPLEMENTAZIONE DEL CRIVELLO QUADRATICO IN JAVA RMI ................................................................................... 15

3.5 ESEMPIO DI ESECUZIONE DEL CRIVELLO QUADRATICO ................................................................................................. 16

4 TEST FATTORIZZAZIONE CON IL CRIVELLO QUADRATICO IN JAVA RMI ..............................................................22

4.1 CONFIGURAZIONE AMBIENTE ................................................................................................................................. 22

4.2 SCELTA DEGLI INTERI DA FATTORIZZARE .................................................................................................................... 27

4.3 “GRANULARITÀ DIMENSIONE SIEVE” ....................................................................................................................... 28

4.4 SCALABILITÀ........................................................................................................................................................ 30

4.5 NUMERO DI BIT DEGLI INTERI DA FATTORIZZARE ........................................................................................................ 32

5 CONCLUSIONI ....................................................................................................................................................35

Page 3: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

1. Introduzione

Un numero primo è un intero, maggiore a uno, che è divisibile soltanto per uno e per se stesso,

per esempio 2, 3, 5, 7, 11, 13, . . . sono numeri primi. Ogni intero positivo si può scomporre, in

modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri primi.

Per esempio:

30 = 2 * 3 * 5;

60 = 2 * 2 * 3 * 5;

6 = 3 * 2;

3300 = 22 * 31 *52 * 111;

10001 = 73 * 137.

Nei giorni nostri, con l’intensificarsi dei calcolatori elettronici e della loro potenza computazionale,

si cercano metodi efficienti per trovare la scomposizione in fattori di un dato intero. Questo

problema è d’interesse sia pratico sia teorico.

Questo problema si divide in due parti:

Decidere se un dato numero è primo o no: problema dei test di primalità. Questo test è

una procedura algoritmica che, dato un numero naturale 𝑛 in input, restituisce PRIME se 𝑛

è un numero primo, COMPOSITE se 𝑛 è un numero composto.

Determinare esplicitamente una scomposizione in fattori (non banali) di un numero

composto: problema della fattorizzazione. In particolare, fattorizzare o "ridurre in fattori"

un numero 𝑛, significa trovare un insieme di numeri {𝑎0, 𝑎1, 𝑎2, … , 𝑎𝑘} tali che il loro

prodotto sia il numero originario (𝑛 = 𝑎0 ∗ 𝑎1 ∗ 𝑎2 ∗ … ∗ 𝑎𝑘).

Questi due problemi, anche se chiaramente legati l’uno all’altro, sono di natura differente. Allo

stato attuale, il problema del test di primalità è relativamente facile (algoritmo polinomiale nella

dimensione dell’input), mentre il secondo sembra essere piuttosto difficile.

La difficoltà nel fattorizzare numeri molto grandi è alla base di alcuni sistemi crittografici moderni,

per esempio RSA, che sono utilizzati per garantire la privacy nella trasmissione di documenti

riservati, la segretezza delle e-mail (per esempio, PGP), la sicurezza nel commercio elettronico,

ecc.

Page 4: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Trovare i fattori di un numero intero grande è un’impresa assai ardua, e può essere impossibile

date le risorse disponibili. Come detto, non si conoscono metodi polinomiali per la fattorizzazione,

come invece accade per i test di primalità.

1.1 Crittografia RSA

La crittografia si occupa delle "scritture nascoste", in altre parole dei metodi per rendere un

messaggio "offuscato" in modo da non essere comprensibile a persone non autorizzate a leggerlo.

La crittografia tratta della lettura di messaggi dati in forma cifrata, cosicché solo i destinatari siano

in grado di decifrarli e di leggerli. Si tratta di una materia molto antica, che si sviluppa

specialmente in tempo di guerra.

In crittografia l'acronimo RSA indica un algoritmo di crittografia asimmetrica, utilizzabile per cifrare

o firmare informazioni. Un sistema di crittografia asimmetrico si basa sull'esistenza di due chiavi

distinte, che sono usate per cifrare e decifrare. Se una chiave è usata per la cifratura, l’altra deve

necessariamente essere utilizzata per la decifratura. La questione fondamentale è che, nonostante

le due chiavi siano fra loro dipendenti, non sia possibile risalire dall'una all'altra, in modo che se

anche si è a conoscenza di una delle due chiavi, non si possa risalire all'altra, garantendo in questo

modo l'integrità della crittografia.

Per realizzare con il cifrario asimmetrico un sistema crittografico pubblico, è importante che un

utente si crei autonomamente entrambe le chiavi, denominate "diretta" e "inversa", e ne renda

pubblica una soltanto. Così facendo si viene a creare una sorta di "elenco telefonico" a

disposizione di tutti gli utenti, che raggruppa tutte le chiavi dirette, mentre quelle inverse saranno

tenute segrete dagli utenti che le hanno create e da questi utilizzate solo quando ricevono un

messaggio cifrato con la rispettiva chiave pubblica dell’ "elenco" da parte di un certo mittente,

ottenendo in questo modo i presupposti necessari alla sicurezza del sistema.

I ricercatori del MIT, Ronald Rivest, Adi Shamir e Leonard Adleman, nel 1978 hanno saputo

implementare tale logica utilizzando particolari proprietà formali dei numeri primi con alcune

centinaia di cifre. L'algoritmo da loro inventato, denominato RSA, acronimo indicante le iniziali dei

loro cognomi, non è sicuro da un punto di vista matematico teorico, perché esiste la possibilità che

tramite la conoscenza della chiave pubblica si possa decifrare un messaggio. L’enorme dispendio

in termini di tempo necessario per risolvere dei calcoli, fa di quest’algoritmo un sistema

abbastanza affidabile, perché c’è bisogno di eseguire una fattorizzazione di un numero intero

molto grande al fine di decifrare il messaggio.

Page 5: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Come detto, RSA è basato sull'elevata complessità computazionale della fattorizzazione in numeri

primi. Il suo funzionamento base è il seguente:

Si scelgono a caso due numeri primi, 𝒑 e 𝒒, l'uno indipendentemente dall'altro, abbastanza

grandi da garantire la sicurezza dell'algoritmo.

Si calcola il loro prodotto 𝒏 = 𝒑 ∗ 𝒒, chiamato modulo, perché tutta l'aritmetica seguente

è modulo 𝑛.

Si sceglie poi un numero 𝒆 chiamato esponente pubblico, coprimo e più piccolo di

(𝒑 − 𝟏) ∗ (𝒒 − 𝟏).

In matematica, gli interi 𝑎 e 𝑏 si dicono coprimi o primi tra loro se e solo se essi non hanno

nessun divisore comune eccetto 1 e −1, o, equivalentemente, se il loro massimo comun

divisore è 1. Per esempio, 6 e 35 sono coprimi, ma 6 e 27 non lo sono perché entrambi

sono divisibili per 3; 1 è coprimo con ogni numero intero; 0 è coprimo solo ad 1 e −1.

Infine, si calcola il numero 𝒅, chiamato esponente privato:

𝒆 ∗ 𝒅 ≡ 𝟏 (𝒎𝒐𝒅((𝒑 − 𝟏) ∗ (𝒒 − 𝟏)))

La chiave pubblica è la coppia (𝒏, 𝒆), mentre la chiave privata è (𝒏, 𝒅). I fattori 𝑝 e 𝑞 possono

essere distrutti, anche se spesso sono memorizzati all’interno della chiave privata.

La forza dell’algoritmo sta nel fatto che per calcolare 𝒅 da 𝒆 o viceversa, non basta la conoscenza

di 𝒏, ma serve il valore (𝒑 − 𝟏) ∗ (𝒒 − 𝟏), infatti fattorizzare, cioè scomporre l’intero nei suoi

divisori, è un’operazione molto lenta, ma soprattutto l’operazione di modulo non è invertibile,

dunque anche conoscendo 𝒏 non si può risalire al prodotto modulo 𝒏 di 𝒑 e 𝒒.

Un messaggio originario 𝒎 è cifrato attraverso l’operazione 𝒎𝒆 (𝒎𝒐𝒅 𝒏), la quale restituisce il

messaggio cifrato 𝒄. Quest’ultimo è decifrato con l’operazione 𝒄𝒅 = 𝒎𝒆∗𝒅 = 𝒎𝟏 (𝒎𝒐𝒅 𝒏).

Il procedimento funziona solo se la chiave 𝒆 utilizzata per cifrare e la chiave 𝒅 utilizzata per

decifrare sono legate tra loro dalla relazione in precedenza indicata, cioè 𝒆 ∗ 𝒅 ≡ 𝟏 (𝒎𝒐𝒅((𝒑 −

𝟏) ∗ (𝒒 − 𝟏))), e quindi quando un messaggio viene cifrato con una delle due chiavi può essere

decifrato solo utilizzando l'altra.

Page 6: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Tuttavia proprio qui si vede la debolezza dell'algoritmo: si basa sull'assunzione mai dimostrata

(RSA assumption) che il problema di calcolare √𝒄 𝒆

𝒎𝒐𝒅 𝒏 con 𝒏 numero composto di cui non si

conoscono i fattori, sia non trattabile da punto di vista computazionale.

Invece, per quanto riguarda la firma digitale, il messaggio è crittografato con la chiave privata, in

modo che chiunque possa, utilizzando la chiave pubblica (conosciuta da tutti), decifrarlo e, oltre a

poterlo leggere in chiaro, essere certo che il messaggio è stato inviato dal possessore della chiave

privata corrispondente a quella pubblica utilizzata per leggerlo.

Per motivi di efficienza e comodità, il messaggio normalmente è inviato in chiaro con allegata la

firma digitale di un hash del messaggio stesso. In questo modo il ricevente può direttamente

leggere il messaggio (che è in chiaro) e può comunque utilizzare la chiave pubblica per verificare

che l'hash ricevuto sia uguale a quello calcolato localmente sul messaggio ricevuto. Se i due hash

coincidono, allora anche il messaggio completo corrisponde, questo è vero solo se l'hash utilizzato

è sicuro dal punto di vista della crittografia.

La seguente tabella mostra alcuni esempi di RSA Factoring Challenge, ossia le sfide volte a

fattorizzare dei numeri RSA.

Page 7: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Numero RSA

Cifre decimali

Cifre binarie

Premio offerto

Data fattorizzazione

Fattorizzato da

RSA-100 100 330

Aprile 1991 Arjen K. Lenstra

RSA-110 110 364

Aprile 1992 Arjen K. Lenstra e M.S. Manasse

RSA-120 120 397

Giugno 1993 T. Denny et al.

RSA-129 129 426 $100 USD Aprile 1994 Arjen K. Lenstra et al.

RSA-130 130 430

10 aprile 1996 Arjen K. Lenstra et al.

RSA-140 140 463

2 febbraio 1999 Herman J. J. te Riele et al.

RSA-150 150 496

16 aprile 2004 Kazumaro Aoki et al.

RSA-155 155 512

22 agosto 1999 Herman J. J. te Riele et al.

RSA-160 160 530

1º aprile 2003 Jens Franke et al., Università di Bonn

RSA-170 170 563

29 dicembre 2009

D. Bonenberger and M. Krone

RSA-576 174 576 $10,000 USD 3 dicembre 2003 Jens Franke et al., Università di Bonn

RSA-180 180 596

8 maggio 2010 S. A. Danilov and I. A. Popovyan, Università statale di Mosca

RSA-190 190 629

non ancora fattorizzato

RSA-640 193 640 $20,000 USD Novembre 2005 Jens Franke et al., Università di Bonn

RSA-200 200 663

9 maggio 2005 Jens Franke et al., Università di Bonn

RSA-210 210 696

non ancora fattorizzato

RSA-704 212 704 $30,000 USD non ancora fattorizzato, premio ritirato

RSA-220 220 729

non ancora fattorizzato

RSA-230 230 762

non ancora fattorizzato

RSA-232 232 768

non ancora fattorizzato

RSA-768 232 768 $50,000 USD 12 dicembre 2009

Thorsten Kleinjung et al.

Nella tabella RSA Factoring Challenge (http://it.wikipedia.org/wiki/RSA_Factoring_Challenge).

Page 8: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

2. Algoritmi di fattorizzazione

Nel corso della storia sono stati ideati molti algoritmi per rendere la fattorizzazione un problema

risolvibile sempre più veloce dal punto di vista computazionale, però, tuttora rimane un problema

complesso.

Tra i metodi più popolari ricordiamo:

Metodo forza bruta: si divide l’intero da fattorizzare 𝑛 per tutti i numeri che gli sono

minori. Il costo operativo nel caso peggiore è 𝑂(𝑛).

Metodo forza bruta migliorato: si considerano solo i numeri primi minori o uguali alla

radice quadrata del numero 𝑛. Si prova a dividere il numero 𝑛 per il minore di questi, se

non risulta divisibile si procede con il successivo e così via. Si procede allo stesso modo con

il risultato ottenuto e si ripetono le stesse operazioni fino a quando si ottiene quoziente 1.

Se tutti i numeri primi minori della radice quadrata di 𝑛 sono stati provati e nessuno di loro

è un divisore, 𝑛 stesso è un numero primo. Il costo operativo nel caso peggiore è 𝑂(√𝑛).

Metodo delle curve ellittiche (ECM): uno dei più noti è quello di Lenstra, che si basa su idee

già contenute nel "(p-1)-method" di Pollard. Insieme all'algoritmo di Pollard-Strassen e al

Crivello dei campi di numeri generale è a tutt'oggi uno dei più veloci metodi totalmente

deterministici.

Metodi probabilistici: tra di essi ci sono gli algoritmi di Schnorr-Lenstra e di Lenstra-

Pomerance.

Crivello Quadratico: é un moderno algoritmo di fattorizzazione d’interi ed è il secondo

metodo più veloce conosciuto, dopo il General Number Field Sieve. E’ il più veloce per interi

sotto le 100 cifre decimali circa, ed è più semplice del number field sieve. Dato un intero 𝑛

da fattorizzare, l’algoritmo restituisce due fattori, non necessariamente primi. Questo

metodo si adatta molto bene alla fattorizzazione degli interi di RSA, poiché questi numeri

sono il prodotto di due primi. Infatti, molte RSA Factoring Challenge hanno adoperato

proprio questo metodo ottenendo buoni risultati.

Page 9: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

2.1 Il Crivello Quadratico

Il Crivello Quadratico (CQ) è un algoritmo di fattorizzazione creato da Carl Pomerance, un

matematico statunitense, studioso di teoria dei numeri. Quest’algoritmo è particolarmente

famoso perché nel 1994 ha fattorizzato il numero RSA-129, composto da 129 cifre in base dieci.

RSA-129 = 11438162575788886766923577997614661201021829672124236256256184293

5706935245733897830597123563958705058989075147599290026879543541

RSA-129 = 3490529510847650949147849619903898133417764638493387843990820577

× 32769132993266709549961988190834461413177642967992942539798288533

La sfida per la fattorizzazione includeva un messaggio da decifrare con RSA-129. Una volta

decriptato, usando il crivello quadrico, il messaggio recuperato fu:

"The Magic Words are Squeamish Ossifrage"

(Le parole magiche sono un avvoltoio schizzinoso).

L'algoritmo tradizionale consta principalmente di otto passi:

1) Viene dato in input il numero naturale intero dispari 𝑛 > 1. Se l’intero è pari, allora uno dei

fattori è sempre 2.

2) Si sceglie un naturale 𝑘 > 0.

3) Si esaminano tutti i numeri primi 𝑝 ≤ 𝑘 utilizzando il criterio di Eulero (𝑛

𝑝) e sfruttando il

simbolo di Legendre si eliminano i primi dispari tali che (𝑛

𝑝) ≠ 1. Da questo procedimento

si ottiene così la base di fattori 𝐵 = 𝑝1, 𝑝2, … , 𝑝𝑡 con 𝑝𝑖 numero primo.

4) Facendo assumere a 𝑟 valori interi successivi a ⌊𝑛⌋, si trovano almeno 𝑡 + 1 valori

𝑦 = 𝑟2 − 𝑛 che abbiano tutti i loro fattori primi in 𝐵. Ogni valore 𝑦 è detto sieve.

Page 10: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

5) Per ognuno dei valori 𝑦1, 𝑦2, … , 𝑦𝑡+1 si calcola il vettore 𝕫2𝑡 ∶ 𝑣2(𝑦𝑖) = (𝑒1, 𝑒2, … , 𝑒𝑡) dove

𝑒𝑖 è la riduzione modulo 2 dell’esponente di 𝑝𝑖 nella fattorizzazione di 𝑦𝑖.

6) Con il metodo di eliminazione di Gauss si determinano alcuni dei vettori 𝑣2(𝑦𝑖) che producono la somma uguale al vettore nullo.

In matematica, il metodo di eliminazione di Gauss è un algoritmo usato in algebra lineare per determinare le soluzioni di un sistema di equazioni lineari, per calcolare il rango o l'inversa di una matrice. L'algoritmo, attraverso l'applicazione di operazioni elementari dette mosse di Gauss, riduce la matrice in una forma detta “a scalini”. La matrice così ridotta permette il calcolo del rango della matrice (che sarà pari al numero di scalini/pivot) e la risoluzione del sistema lineare a essa associato.

7) Si pone 𝑥 uguale al prodotto degli 𝑟𝑖 corrispondenti agli 𝑦𝑖 trovati nel passo 6) e si pone 𝑦

uguale al prodotto delle potenze di 𝑝1, 𝑝2, … , 𝑝𝑡 con esponenti uguali alla semisomma

degli esponenti della fattorizzazione degli stessi 𝑦𝑖.

8) Si calcola 𝑑 = 𝑔𝑐𝑑(𝑥 − 𝑦, 𝑛) e se 1 < 𝑑 < 𝑛 allora 𝑑 è divisore non banale di 𝑛, altrimenti

si torna al passo 2) con una scelta di 𝑘 più grande. Il massimo comune divisore (M.C.D. o

𝑔𝑐𝑑) di due numeri interi, che non siano entrambi uguali a zero, è il numero naturale più

grande per il quale possono entrambi essere divisi.

Il tempo di esecuzione (running time) del Crivello Quadratico dipende solo dalla dimensione di 𝑛, il

numero da fattorizzare, e non da speciali strutture o proprietà dell’algoritmo.

𝑂(𝑛) = 𝑒√ln(𝑛)∗ln(ln(𝑛))

Come ci aspettavamo il running time è esponenziale nella dimensione dell’input.

Page 11: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

3. Java RMI

Abbiamo implementato l’algoritmo del Crivello Quadratico (CQ) utilizzando RMI, cioè il modello ad

oggetti distribuito offerto da Java.

Il modello Java RMI si integra all’interno della semantica del linguaggio ed in pratica, non è altro

che un'estensione "ad oggetti" di Remote Procedure Call e fornisce la visione astratta di una

chiamata di procedura remota verso altri processi.

Gli scopi di RMI sono:

Supportare in maniera trasparente invocazioni remote di metodi su oggetti su differenti

JVM;

Integrare in maniera naturale il modello distribuito all'interno di Java mantenendo le

caratteristiche del linguaggio;

Rendere evidenti le differenze tra il modello distribuito e quello locale;

Rendere facile (compatibilmente con gli altri scopi) la realizzazione di applicativi distribuiti

in Java;

Mantenere la sicurezza offerta da Java con i security manager e i class loader.

Generalmente le applicazioni sviluppate con questo modello sono composte da server e client. Il

server crea un certo numero di oggetti, li rende accessibili da remoto ed attende le invocazioni dei

client sugli oggetti; mentre il client: preleva il riferimento ad uno o più oggetti remoti ed invoca i

loro metodi.

RMI fornisce il meccanismo attraverso il quale server e client comunicano, quindi un'applicazione

distribuita deve poter:

Localizzare oggetti remoti (attraverso un registro);

Comunicare con oggetti remoti (nascondendo, per quanto possibile, i dettagli

dell'invocazione remota);

Caricare dinamicamente classi dalla rete.

Un semplice schema di funzionamento per RMI è quello mostrato in figura:

Page 12: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Figura 3.1 - Schema di funzionamento per RMI

In quest'ambito il server registra l'oggetto con un nome sul registry(1), il client ricerca ed ottiene il

riferimento remoto dell'oggetto(2) ed invoca il suo metodo remoto(3). I passi 4 e 5 mostrano il

caricamento dinamico delle classi.

3.1 Architettura di RMI

La figura sottostante mostra la struttura di un’applicazione RMI che è organizzata in strati orizzontali sovrapposti

Figura 3.2 - Architettura di RMI

Lo strato più alto è costituito da applicazioni (client e server) eseguite da JVM differenti. Lo stub e

lo skeleton forniscono la rappresentazione dell’oggetto remoto: lo stub gestisce la simulazione

locale sul client e agendo come proxy consente la comunicazione con l’oggetto remoto; lo

skeleton ne consente l’esecuzione sul server. Il client esegue i metodi dell’oggetto remoto in modo

Page 13: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

del tutto analogo alla chiamata locale, senza preoccuparsi dei dettagli della comunicazione. Il

Remote Reference Layer (RRL) ha il compito di instaurare un connessione virtuale fra il client e il

server (esegue operazioni di codifica e decodifica dei dati). Questo adotta un protocollo generico e

indipendente dal tipo di stub o skeleton utilizzato. Il Transport Layer esegue la connessione vera e

propria tra le macchine utilizzando le funzionalità standard di networking di Java, ovvero i socket

(protocollo TCP/IP).

3.2 RMI: il processo di creazione

Il processo di creazione può essere suddiviso nei seguenti passi:

1. Il server dichiara i servizi offerti attraverso un interfaccia java remota che estende

java.rmi.Remote. Ogni metodo ti tale interfaccia deve lanciare l’eccezione

java.rmi.RemoteException.

2. Il server implementa l’interfaccia remota del punto 1; in più gli oggetti devono derivare de

java.rmi.UnicastRemoteObject.

3. La classe server viene compilata generando il .class.

4. Usando rmic (stub compiler) sulla classe server, viene generato un client stub e un server

stub (skeleton): lo stub invia le chiamate remote verso il server effettuando il marshalling

dei parametri; lo skeleton, speculare allo stub, riceve le chiamate remote, effettua

l’unmarshalling e chiama effettivamente i metodi dell’oggetto.

5. Per rendere disponibili gli oggetti distribuiti e il loro recupero, java mette a disposizione un

servizio di Naming attraverso l’applicazione rmiregistry.

6. Il server viene mandato in esecuzione e crea gli oggetti che devo essere acceduti da

remoto.

7. Ogni oggetto da accedere da remoto deve essere registrato sul registry lanciato al punto 5.

Per far ciò si usano i metodi di java.rmi.Naming che consentono di effettuare il binding di

nomi ad oggetti.

8. Una volta implementato il client, questi usa i metodi di java.rmi.Naming per localizzare un

oggetto remoto. L’invocazione dei metodi usa lo stub come intermediario.

9. Il client viene compilato ed eseguito e lo stub garantisce l’accesso agli oggetti remoti.

Page 14: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Figura 3.3 – Processo di creazione per RMI

3.3 Implementare un Compute Server

In questa paragrafo mostreremo come implementare un compute server perché questa implementazione è stata utilizzata per affrontare il problema. Un compute server è un oggetto remoto che consente ad un server di ricevere dei task dai client, eseguirli e restituire il risultato. Il task viene definito dal client ma viene eseguito sulla macchina del server. Esso può variare indipendentemente dal server, l’importante è che rispetti una determinata interfaccia. Possiamo riassumere i compiti del compute server in 3 semplici passi:

1. Il compute server scarica dal client il codice del task 2. Lo esegue all’interno della propria Java virtual machine 3. Restituisce al client il risultato

Per implementare un compute server servono due interfacce:

L’interfaccia Compute, che consenta ai client di inviare task al compute server L’interfaccia Task, che consenta al compute server di eseguire le varie operazioni.

Page 15: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Per capire meglio le interfacce di seguito sono stati riportati le loro implementazioni. Iniziamo dall’interfaccia Compute:

Questa interfaccia definisce i metodi che possono essere chiamati da altre virtual machine. Gli

oggetti che implementano questa interfaccia diventano oggetti remoti.

Interfaccia Task:

Questa interfaccia è usata come argomento nel metodo executeTask dell’interfaccia Compute e

fornisce al Compute Server il meccanismo per eseguire il task. Non è un interfaccia remota, quindi

non è associata ad oggetti remoti. Ovviamente l’interfaccia estende Serializable in quanto

necessita della trasformazione automatica di oggetti e strutture in sequenze di byte manipolabili.

Definite queste interfacce l’implementazione del server risulta essere molto semplice infatti

implementa l’interfaccia compute e comprende il metodo main per l’esecuzione.

L’implementazione del task da far eseguire (Task.java) è la classe che contiene il metodo da far

eseguire al server. Ora il client che ha a disposizione questa classe può farla eseguire al server. È

necessario istruire il server attraverso una policy (-Djava.security.policy = policy).

public class Server extends UnicastRemoteObject implements Compute {

public Server () throws RemoteException {

super ();

}

public Object executeTask ( Task t ) {

return t.execute ();

}

}

package compute;

import java.io.Serializable;

public interface Task extends Serializable {

Object execute ();

}

package compute;

import java.rmi.Remote;

import java.rmi.RemoteException;

public interface Compute extends Remote {

Object executeTask ( Task t ) throws RemoteException;

}

Page 16: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Figura 3.4 – Argomenti della VM del Server

3.4 Implementazione del Crivello Quadratico in JAVA RMI

Il progetto è costituito da due classi java principali: Client e CQReducer.

Client: è la classe principale del progetto e contiene il metodo main e costituisce la fase di inizializzazione e di divisione del lavoro. In particolare, si inserisce il numero da fattorizzare e viene generato il file d’input contenente i Sieve e tramite il metodo avviaThread() viene diviso il lavoro tra tutti i servizi di fattorizzazione disponibili nella rete;

CQReducer: dopo aver collezionato in una lista tutti gli elementi smooth calcolati dai thread, la classe CQReducer realizza con tali valori un sistema lineare modulo 2. Il suo obiettivo è risolvere il sistema adoperando tecniche come l’eliminazione di Gauss e la sostituzione all’indietro. Il risultato ci permette di trovare i fattori dell’intero dato in input.

Per l’implementazione abbiamo utilizzato i thread di Java per rendere la chiamata al metodo run() del thread asincrona: quando mandiamo in esecuzione la computazione su un Server, il thread a cui è associato aspetta il risultato, lasciando così libero il client di avviare la computazione su altri Server.

Page 17: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

3.5 Esempio di esecuzione del Crivello Quadratico

Il numero che vogliamo fattorizzare utilizzando l’algoritmo del crivello quadratico è il seguente

𝑵 = 𝟖𝟕𝟒𝟔𝟑.

Come prima operazione bisogna identificare il limite dei fattori di base (numeri primi p) da

utilizzare per la fattorizzazione del numero, questo avviene utilizzando il metodo

getLimiteFattoriBase. Il metodo indicato calcola il numero ottimale dei fattori di base per

fattorizzare il numero dato in input utilizzando la seguente formula: (𝑒(√ln 𝑁∗ln ln 𝑁))√2/4. Nel

seguente esempio il limite dei fattori di base da utilizzare per la fattorizzazione del numero 𝟖𝟕𝟒𝟔𝟑

è 𝟕, cioè questo significa che dobbiamo utilizzare i primi sette fattori di base che attraverso il

criterio Eulero:

(𝑁

𝑝) ≡ 𝑁

(𝑝−1

2)(mod p)

Soddisfano il simbolo di Legendre, ossia (𝑁

𝑝) ≡ 1 𝑚𝑜𝑑 𝑝.

Partendo dal numero primo 𝑝 = 2 applichiamo il criterio di Eulero e consideriamo solo i primi

sette valori che soddisfano il simbolo di Legendre (dove 𝑁 è l’intero e 𝒑 un numero primo), cioè

che restituiscono in modulo il valore 1. La seguente operazione è eseguita dal metodo statico

legendre:

I nostri fattori di base sono i seguenti 𝐵 = {2,3,13,17,19,29,41}, dove |𝐵| = 7.

La fase successiva consiste nell’eseguire la fase di sieving, cioè del calcolo dei sieve. Prima di

calcolare i sieve però bisogna identificare il numero di sieve necessari per la fattorizzazione del

nostro numero, questo avviene utilizzando il metodo getSize_fullSieveInterval.Il metodo calcola il

numero di sieve utilizzando la seguente formula: 𝑛𝑢𝑚𝑒𝑟𝑜𝐹𝑎𝑡𝑡𝑜𝑟𝑖𝐵𝑎𝑠𝑒3. Il numero di sieve

necessari per fattorizzare 𝟖𝟕𝟒𝟔𝟑 è 343.

Ogni sieve è realizzata utilizzando la seguente formula:

𝑝 2 3 5 7 11 13 17 19 23 29 31 37 41

𝑁

𝑝 1 1 -1 -1 -1 1 1 1 -1 1 -1 -1 1

Page 18: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

𝑍(𝑋) = (𝑋 + ⌊√𝑁⌋)

𝑌(𝑋) = (𝑍(𝑋))2 − 𝑁

Per minimizzare i valori consideriamo la seguente formula:

𝑍(𝑋) = (𝑋 + [⌊√𝑁⌋ − (𝑛𝑢𝑚𝑆𝑖𝑒𝑣𝑒2⁄ )])

𝑌(𝑋) = (𝑍(𝑋))2 − 𝑁 = (𝑋 + 124)2 − 87463

Realizziamo il nostro vettore di sieve formato dalle coppie [𝑍(𝑋), 𝑌(𝑋)] formato dalle sieve

computate per 0 ≤ 𝑋 < 343

V = { [Z(0),Y(0)] ; [Z(1), Y(1)] ; [Z(2),Y(2)] ……… [Z(342),Y(342)]} = {[124, -72087] ; [125, -

71838]; [126, -71587]; ……… [466, 129693] }

L’operazione presentata è eseguita dal metodo writeSieveFileInput2 che genera il file delle Sieve in

cui per ogni riga viene specificato un intervallo la cui dimensione viene settata variando il

parametro “Dimensione Sieve”.

Una volta realizzato l’array di Sieve di ogni intervallo con il metodo createSieve, per ogni fattore di

base eseguiamo l’analisi su di esso in modo tale da individuare valori B-smooth. Questo avviene

utilizzando l’algoritmo di Shanks-Tonelli implementato dal metodo execute dell’oggetto Factorize

incorporato in un thread.

Ogni macchina Server lavorerà su un sottoinsieme dell’array di sieve generato.

Partendo dal primo fattore di base determinato nella fase iniziale, nel nostro esempio 2,

utilizzando il metodo getFirstIndexFactor per individuare il primo sieve che è un divisore di 2,

utilizziamo la seguente formula:

(𝑋 + 124)2 − 87463 ≡ 0 𝑚𝑜𝑑 2

Partendo dal valore seguente, in questo caso -71838 il quale si trova nella seconda posizione

dell’array, individuiamo il massimo esponente di 2 per cui esso è divisibile:

−71838 mod 2 = 0

−71838 𝑚𝑜𝑑 4 = 2

Page 19: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Quindi, il massimo esponente di 2 per -71838 è 1. Memorizziamo l’esponente e sostituiamo il

vecchio valore con il nuovo (cioè quello restituito dalla divisione del sieve che stiamo analizzando

con il massimo esponente di 2 per cui esso è divisibile).

V = { [Z(0),Y(0)] ; [Z(1), Y(1)] ; [Z(2),Y(2)]; ……… [Z(342),Y(342)]} = {[124, -72087]; [125,

-35919]; [126, -71587]; ……… [466, 129693] }

Il prossimo valore che andremo ad analizzare nella lista di sieve è dato dall’indice iniziale con un

incremento di due (l’incremento è dato dal valore del fattore di base) fino ad arrivare alla fine

dell’array, cioè il prossimo valore che analizzeremo è quello nella quarta posizione dell’array.

La precedente operazione è eseguita per tutti i fattori di base determinati nella fase iniziale. Il

risultato finale è il seguente:

[124, -24029]=>(3^1) x-24029 = -72087

[125, -307] => (2^1 x 3 ^ 2 x 13^1) x -307

[126, -4211] => (17^1) x-4211

[127, -1321] => (2^1 x 3 ^ 3)x -1321

[128, -43] => (3^1 x 19^1 x 29^1)x-43

[129, -2083] => (2^1 x 17^1)x-2083

[130, -23521] => (3^1)x-23521

[131, -11717] => (2^1 x 3^1)x-11717

[132, -70039] => -70039 (primo)

[133, -401] => (2^1 x 3^1 x 29^1)x-401

[134, -7723] => (3 ^ 2)x-7723

[135, -2663] => (2^1 x 13^1)x-2663

[136, -7663] => (3^2)x-7663

[137, -11449] => (2^1 x 3^1)x-11449

[138, -277] => (13^1 x 19^1)x-277

[139, -277] => (2^1 x 3^1 x 41^1)x-277

[140, -22621] => (3^1)x-22621

[141, -33791] => (2^1)x-33791

[142, -22433] => (3^1)x-22433

[143, -73] => (2^1 x 3 ^ 3 x 17^1)x-73

Page 20: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

[144, -66727] => -66727 (divisibile per nessun fattore di base)

[145, -3691] => (2^1 x 3 ^ 2)x-3691

[146, -1297] => (3^1 x 17^1)x-1297

[147, -1733] => (2^1 x 19^1)x-1733

[148,-1] => (3^1 x 13^1 x 41 ^ 2)x-1

……….

……….

……….

Gli output generati da ogni macchina Server, sono le coppie originarie analizzate tale che il

secondo valore della coppia al termine della procedura descritta è 1 o -1.

Una volta terminata la seguente operazione avviene la fase di risoluzione del sistema. Il suo

obiettivo consiste nel risolvere il seguente sistema, cioè nel trovare il numero di colonne

linearmente indipendenti:

[0 0 1 1 1 1

0 11 01 1

] ∙ 𝑆 ≡ [0 0 0 0] (𝑚𝑜𝑑 2)

La prima operazione è quella di realizzare la matrice attraverso le sieve che sono divisibili per i

fattori di base, cioè sono le sieve che nell’operazione precedente sono state sostituite con il valore

-1 oppure con 1. Si mostra sottolista dei sieve che soddisfano il criterio evidenziato:

[148,-1] => -1* (3^1 x 13^1 x 41 ^ 2)

[157,-1] => -1*(2^1 x 3^1 x 19 ^ 2 x 29^1)

[242,-1] => -1* (3 ^ 2 x 13 ^ 2 x 19^1)

[262,-1] => -1* (3 ^ 3 x 17^1 x 41^1)

[265,-1] => -1* (2^1 x 3^1 x 13 ^ 2 x 17^1)

[271,-1] => -1* (2^1 x 3 ^ 2 x 19^1 x 41^1)

[278,-1] => -1* (3 ^ 3 x 13^1 x 29^1)

[296, 1] => (3 ^ 2 x 17^1)

[299, 1] => (2^1 x 3^1 x 17^1 x 19^1)

[307, 1] => (2^1 x 3 ^ 2 x 13^1 x 29^1)

Page 21: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

[316, 1] => (3 ^ 6 x 17^1)

[347, 1] => (2^1 x 3^1 x 17 ^ 2 x 19^1)

[385, 1] => (2^1 x 3^1 x 13^1 x 19^1 x 41^1)

[394, 1] => (3^1 x 19^1 x 29^1 x 41^1)

[413, 1] => (2^1 x 3 ^ 7 x 19^1)

Con i seguenti valori realizziamo la matrice dove le righe consisteranno nei fattori di base

{2,3,13,17,19,29,41} ed le colonne gli interi che sono associati alle sieve con valore -1 e 1

{148,157,242,262,265,271,278,296,299,307,316,347,385,394,413}. Infine, i valori saranno gli

esponenti dei fattori di base per ogni numero in modulo 2:

148 157 242 262 265 271 278 296 299 307 316 347 385 394 413

2 0 1 0 0 1 1 0 0 1 1 0 1 1 0 1

3 1 1 0 1 1 0 1 0 1 0 0 1 1 1 1

13 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0

17 0 0 0 1 1 0 0 1 1 0 1 0 0 0 0

19 0 0 1 0 0 1 0 0 1 0 0 1 1 1 1

29 0 1 0 0 0 0 1 0 0 1 0 0 0 1 0

41 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 L’operazione indicata viene effettuata dal metodo realizzazioneMatriceSistema presente nella

classe CQReducer. Per esempio la realizzazione della prima colonna è data scomponendo il valore

assoluto del sieve (1482 − 87463) nei sui fattori: 2^0 x 3^1 x 13^1 x 17^0 x 19^0 x 29^0 x 41^2.

Quindi, inseriamo per ogni fattore il suo esponente nella casella opportuna in modulo 2. Inseriamo

1 nella casella associata a 3 e 13, mentre nelle altre 0.

In seguito, uniamo alla matrice il vettore dei termini noti:

b’ = [ 0 0 0 0 0 0 0] ( ‘ = trasposto )

Risolviamo il sistema con il metodo solve della classe BinaryLinearSystem. Il sistema può restituire

più di una soluzione, dove alcune potrebbero esser non esatte per il nostro scopo.

All’interno del metodo solve è presente l’invocazione del metodo

trasforma_in_TrangolareSuperiore, il quale trasforma la matrice in triangolare superiore

utilizzando il metodo dell’eliminazione di Gauss. Dopo aver eseguito il metodo indicato,

applichiamo la tecnica della sostituzione all’indietro per ottenere la soluzione del sistema. La

soluzione consiste nel vettore S nel quale i valori posti a 1 indicano le colonne linearmente

indipendenti:

Page 22: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

S’ = [ 0 0 0 0 1 0 1 1 0 1 0 0 0 0 0]

In questo caso le colonne linearmente indipendenti hanno indice: 5, 7, 8, 10. Dobbiamo

considerare i valori nelle intestazioni di queste colonne: 265, 278, 296, 307.

Una volta ottenuto il vettore S applichiamo la tecnica del massimo comune divisore MCD (GCD)

gcd(X-Y, N) ed gcd(X+Y, N) e verifichiamo se uno dei due restituisce un divisore. Dove:

1) 𝑁 indica il numero da fattorizzare (𝑁 = 87463).

2) 𝑋 è calcolato utilizzando la seguente formula: moltiplichiamo le colonne che sono

linearmente indipendenti: 𝑋 = 265 𝑥 278 𝑥 296 𝑥 307 = 6694540240.

3) 𝑌 è calcolato utilizzando la seguente formula:

𝑌 = √(2652 − 87463) ∗ (2782 − 87463) ∗ (2962 − 87463) ∗ (3072 − 87463) =

13497354.

gcd(𝑋 − 𝑌, 𝑁) = 𝑔𝑐𝑑((6694540240 − 13497354), 87463) = 𝟏𝟒𝟗

Per trovare l’altro fattore applichiamo la divisione: 87463/149 = 𝟓𝟖𝟕.

Quindi i fattori per 87463 sono 149 e 587. Infatti, 149 ∗ 587 = 87463.

Figura 3.5 In figura viene mostrato la console del client con i risultati della fattorizzazione del numero 87463

Page 23: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

4 Test Fattorizzazione con il Crivello Quadratico in JAVA RMI

4.1 Configurazione ambiente

L’algoritmo è stato testato nel laboratorio didattico P13 della Facoltà di Scienze MM.FF.NN.

dell’Università degli studi di Salerno. Il gruppo ha utilizzato quindici personal computer in cui è

installato il sistema operativo Windows XP SP3.

In particolare, l’ambiente di lavoro è formato da quattordici host Server (che mettono a

disposizione il servizio di fattorizzazione) e un host Client (che richiede la fattorizzazione di un

numero). La configurazione software include la versione 1.7 della Java Virtual Machine (jdk 1.7).

Il sistema distribuito è stato realizzato utilizzando un’ architettura Client-Server.

Il nostro sistema è simile ad un sistema distribuito collaborativo. L’idea di base è che quando un

Client chiede di fattorizzare un numero, accede a diversi registry (rmiregistry) che contengono i

riferimenti ai servizi di fattorizzazione offerti dai diversi host. Fatto ciò, inizia a distribuire la

computazione ai vari server ottenendo come risultato la lista di sieve. Successivamente costruisce

la matrice con i fattori di base come righe e i sieve risultanti come colonne e tramite il metodo di

eliminazione di Gauss, risolve il sistema e calcola i fattori del numero in input.

La configurazione dei personal computer utilizzati è elencata nella seguente tabella:

DELL OPTILEX 360

Memoria RAM 2,0 GB

Sistema Operativo

Windows XP (5.1) Service Pack 3, x86 32bit

Processore

Intel(R) Pentium(R) Dual CPU E2200 @ 2.20 GHz

Spazio Disco 117 GB

Spazio Disco disponibile 57,6 GB

Page 24: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

La seguente tabella mostra i dati tecnici del processore utilizzato. Come si nota si tratta di una

macchina Intel Dual Core.

Intel(R) Pentium(R) Dual CPU E2200 @

2.20 GHz

Launch Date Q4'07

Processor Number E2200

# of Cores 2

# of Threads 2

Clock Speed 2.2 GHz

L2 Cache 1 MB

Bus/Core Ratio 11

FSB Speed 800 MHz

FSB Parity No

Instruction Set 64-bit

Embedded Options Available No

Supplemental SKU No

Lithography 65 nm

Max TDP 65 W

VID Voltage Range 0.8500V-

1.5V

Page 25: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

La seguente immagine mostra l’ambiente in cui sono stati eseguiti i test della fattorizzazione.

Figura 4.1 In figura si mostra l’ambiente di testing.

La configurazione software includeva la seguente versione della Java Virtual Machine (JVM):

java version 1.7.0 (Build1320-110325); platform110131-9c8b3bfb3a1e Jdk 1.7.0

Caratteristiche Macchine

Memoria: 2,0 GB

Windows XP SP3

Processore 0: Intel(R) Pentium(R) Dual CPU E2200® 2.20 GHz

Processore 1: Intel(R) Pentium(R) Dual CPU E2200® 2.20 GHz

Client Server 1 Server 2 Server 3 Server 4 Server 5

Server 6 Server 7 Server 8 Server 9 Server 10 Server 11

Server 14 Server 13 Server 12

Page 26: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Per l’esecuzione del programma abbiamo utilizzato degli script Batch di Windows per avviare le

varie classi del progetto.

All’inizio vengono predisposte tutte le macchine Server avviando su ognuna di loro l’rmiregistry e

visto che ogni processore è un dual core, vengono avviati due servizi di fattorizzazione ognuno dei

quali verrà invocato da un thread, così da far lavorare in parallelo due thread su un solo

processore.

Dopo aver fatto ciò, viene specificato il numero da fattorizzare ed eventualmente si configura il

parametro “Dimensione Sieve”. Questo parametro ci permette di specificare la dimensione degli

intervalli dei Sieve che verranno memorizzati nel file generato dal Client. Considerando le

eventuali limitazioni di storage nel laboratorio, abbiamo deciso di non memorizzare nel file tutti i

sieve, ma solo gli intervalli.

Un esempio di file d’input con “Dimensione Sieve = 10” è il seguente:

1,10

11,20

21,30

91,97

Dopo aver specificato la configurazione, mandiamo in esecuzione lo script sulla macchina Client,

passandogli come parametro a linea di comando gli indirizzi IP locali delle macchine Server.

Il Client genera il file di input, accede ai registry di ogni macchina e controlla quanti servizi di

fattorizzazione sono disponibili in totale. Questo valore permetterà al Client di dividere il lavoro

per quanti sono i servizi di fattorizzazione a disposizione.

Dopo aver fatto ciò, inizia la fase di divisione del lavoro. In questa fase, il client genera tanti thread

quanti sono i servizi di fattorizzazione a disposizione. Ad ogni thread viene passato come

parametro un oggetto Factorize che effettua il calcolo vero e proprio e un riferimento al server

dove deve essere eseguito. Il client aspetta che tutti i thread finiscono il lavoro e nel frattempo

colleziona tutti i risultati parziali fino ad ottenere la lista finale dei sieve.

La fase successiva è quella della costruzione della matrice con sieve e fattori di base e la

risoluzione del sistema tramite il metodo di eliminazione di Gauss. In questa fase, il client non ha

bisogno dell’aiuto dei server per risolvere il sistema che fornisce in output due soluzioni che

rappresentano i fattori del numero in input. Ovviamente il client controlla che effettivamente le

due soluzioni sono compatibili con il numero in input.

Page 27: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Figura 4.2. Monitor di sistema del Client.

In tutti i test esprimeremo i tempi nel seguente formato: hh:mm:ss,000. Dove hh indica le ore, mm

denota i minuti, ss specifica i secondi e 000 i millisecondi.

Page 28: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

4.2 Scelta degli interi da fattorizzare

Conoscendo che l’algoritmo di crittografia RSA adopera due numeri primi per generare l’intero n,

utilizzato come parte della chiave pubblica, abbiamo scelto gli interi da fattorizzare in base a

questo criterio. In particolare, abbiamo scelto due primi e la loro moltiplicazione ci ha dato l’intero

da fattorizzare.

Quindi, dato un intero n, generato dal prodotto di due primi, il nostro algoritmo fattorizza tale

valore restituendo questi due fattori.

Sono stati scelti vari interi da fattorizzare, selezionati in base al numero di bit: da 64 a 138 bit.

# bit # digits INTERO da Fattorizzare Fattore 1 Fattore 2 Numero fattori di

base

Numero di Sieve

64 bit 20 12978441629915362747 211375232977 61400011 99 970299

72 bit 22 3544259196660620885771 491420827 7212269000273 140 2744000

80 bit 24 865634683480088490430201 8012217949249 108039333049 196 7529536

88 bit 27 163434269570785973006628247 2589512984167 63113902332241 271 19902511

96 bit 29 49082158359180173177609455963

209388827686667

234406768027889

369 50243409

104 bit 32 12056080574346909871031956078133

3389336765801243

3557061870037231

498 123505992

112 bit 34 3276005466534609097786725547758259

69752773008752833

46965953111620723

665 294079625

120 bit 36 817831495931075108264674316273886383

811708764410921989

1007543015165786147

880 681472000

128 bit 39 287347878252036582961936873038788889787

15612823232949851171

18404607159428252297

1157 1548816893

138 bit 42 252031752962240174850105249379065463849553

378011036096614700929

666731203312868725457

1611 4181062131

Come si nota dalla tabella, aumentando il numero di bit accrescono i fattori di base e il numero di

sieve da analizzare.

Quando l’algoritmo trova la fattorizzazione, esso controlla se quest’ultima è corretta, nel caso

contrario restituisce un messaggio di errore. In tutti i test compiuti abbiamo sempre riscontrato

una fattorizzazione corretta.

Page 29: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

4.3 “Granularità dimensione Sieve”

Il primo test che abbiamo compiuto riguarda la “dimensione Sieve”, cioè abbiamo modificato il

parametro all'interno del programma che indica la dimensione dell’intervallo di sieve presenti in

ogni riga del file d’input generato dal Client. Il test è utile per comprendere orientativamente il

valore migliore per il parametro discusso. Il nostro scopo è registrare il valore di tale parametro

che minimizza il tempo totale reale di esecuzione della fattorizzazione.

In particolare, abbiamo scelto l’intero a 88 bit (163434269570785973006628247), e il numero di

host Server = 14;

La seguente tabella mostra l’esito di questo esperimento. Dimensione Sieve è il parametro

variabile; mentre Real Time indica il tempo totale di esecuzione della fattorizzazione (misurato con

i metodi java StartTime e EndTime); Tempo Divisione Lavoro e Calcolo è il tempo impiegato dal

Client per inviare i task ai Server, collezionare i risultati parziali ottenuti e risolvere il sistema;

Tempo Generazione file di input è il tempo impiegato per la generazione e la scrittura del file di

input.

Numero esperimento Dimensione Sieve Real Time Tempo Divisione Lavoro

e Calcolo Tempo Generazione

file di input

1 5 01:20:28,152 01:18:29,230 00:01:58,250

2 10 00:42:42,235 00:41:41,987 00:00:59,577

3 50 00:12:09,464 00:11:57,323 00:00:11,500

4 100 00:08:17,278 00:08:10,840 00:00:05,797

5 150 00:07:01,013 00:06:56,279 00:00:04,078

6 200 00:06:25,170 00:06:21,576 00:00:02,938

7 250 00:06:02,419 00:05:59,326 00:00:02,437

8 500 00:05:14,326 00:05:12,326 00:00:01,328

9 1000 00:04:41,263 00:04:39,905 00:00:00,640

10 10000 00:03:21,484 00:03:20,249 00:00:00,109

11 20000 00:03:13,248 00:03:11,498 00:00:00,063

12 30000 00:03:36,253 00:03:34,143 00:00:00,047

13 40000 00:08:45,659 00:08:43,018 00:00:00,046

14 100000 Error: Java heap space 00:00:00,032

15 200000 Error: Java heap space 00:00:00,015

Dalla tabella si nota che gli ultimi due esperimenti non sono andati a buon fine, perché ogni riga da

costruire era molto grande, quindi ha determinato un eccessivo utilizzo dell’heap space di java.

Page 30: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Figura 4.3 Nel grafico si mostra il tempo totale della fattorizzazione a variare del parametro “Dimensione Sieve”.

Dall’esperimento presentato si evince che il tempo totale, in questo caso, si minimizza quando il

parametro in esame è settato a 20000. Aumentando il valore di tale parametro, oltre il valore

20000, il tempo totale degenera a causa di più dati da trasferire e gestire.

Page 31: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

4.4 Scalabilità

In questo esperimento mostreremo come aumentando il numero di host (Server) il tempo totale

di esecuzione diminuisce. In particolare abbiamo preso due interi, uno a 96 bit e l’altro a 104 bit.

Abbiamo scelto tali numeri, poichè aumentando il numero di bit e riducendo il numero di host, il

tempo totale diventava inaccettabile per l’esecuzione complessiva dei test.

In questo esperimento abbiamo utilizzato i seguenti parametri fissati:

Dimensione Sieve = 20000;

Numero massimo di host Server = 14;

La seguente tabella mostra i tempi di esecuzione della fattorizzazione dell’intero a 96 bit

(49082158359180173177609455963). In particolare, si mostra il tempo reale totale di esecuzione,

il tempo di generazione e scrittura del file d’input originato dal Client (tempo misurato in java con

la funzione System.getTimeInMillis()) e il tempo di Divisione Lavoro e Calcolo ottenuto anch’esso

attraverso la precedente funzione java.

Numero Host

Server

Numero Processi Server

Real Time Tempo Divisione Lavoro e Calcolo

Tempo Generazione File di input

1 2 00:17:59,196 00:17:58,415 00:00:00,078

2 4 00:12:43,276 00:12:42,432 00:00:00,062

4 8 00:10:10,137 00:10:09,089 00:00:00,063

8 16 00:08:50,075 00:08:48,668 00:00:00,078

11 22 00:08:37,231 00:08:35,544 00:00:00,110

14 28 00:08:14,147 00:08:12,193 00:00:00,078

Page 32: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

La seguente tabella mostra i tempi di esecuzione della fattorizzazione dell’intero a 104 bit

(12056080574346909871031956078133). In particolare, si mostra il tempo reale totale di

esecuzione, il tempo di generazione e scrittura del file d’input originato dal Client (tempo misurato

in java con la funzione System.getTimeInMillis()) e il tempo di Divisione Lavoro e Calcolo ottenuto

anch’esso attraverso la precedente funzione java.

Numero Host

Server

Numero Processi Server

Real Time Tempo

Divisione Lavoro e Calcolo

Tempo Generazione File di input

1 2 00:58:42,003 00:58:40,722 00:00:00,218

2 4 00:38:34,823 00:38:33,465 00:00:00,218

4 8 00:29:20,379 00:29:18,848 00:00:00,219

8 16 00:24:27,469 00:24:25,673 00:00:00,219

11 22 00:23:02,788 00:23:00,709 00:00:00,141

14 28 00:21:50,496 00:21:48,199 00:00:00,156

Figura 4.4 In figura, si mostra il Real Time della fattorizzazione dei due interi in esame al variare del numero di host Server.

Page 33: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Come si nota, sia dal grafico sia dalle tabelle, il tempo totale (Real Time) di esecuzione decresce

all’aumentare del numero di macchine a disposizione. Questa tendenza è maggiormente visibile

quando dimezziamo il numero di macchine e utilizziamo un numero con più bit, poiché il file

d’input è più grande a causa dell’elevato numero di sieve.

Precisiamo che aumentando il numero di bit dell’intero fa fattorizzare, il numero di sieve da

analizzare cresce esponenzialmente, quindi occorre più tempo per eseguire l’algoritmo.

4.5 Numero di bit degli interi da fattorizzare

Il seguente test ci permette di analizzare come cresce il tempo di fattorizzazione al crescere della

dimensione in bit dell'intero da fattorizzare.

Per il seguente test abbiamo adoperato alcuni interi descritti nella sezione 4.2. Inoltre, sono stati

utilizzati i seguenti parametri:

Dimensione Sieve = 20000;

Numero di host Server = 14;

Numero esperimento

Numero bit Real Time Tempo

Divisione Lavoro e Calcolo

Tempo Generazione File di input

1 64 bit 00:00:09,938 00:00:08,656 00:00:00,016

2 72 bit 00:00:26,312 00:00:24,890 00:00:00,016

3 80 bit 00:01:11,796 00:01:10,265 00:00:00,047

4 88 bit 00:03:12,964 00:03:11,276 00:00:00,063

5 96 bit 00:08:14,147 00:08:12,193 00:00:00,078

6 104 bit 00:21:50,496 00:21:48,199 00:00:00,156

7 112 bit 01:17:37,114 01:17:33,958 00:00:00,328

8 128 bit 07:02:48,738 07:02:41,254 00:00:01,047

9 138 bit 28:41:21,207 28:41:03,598 00:00:06,094

Page 34: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Figura 4.5 Nel grafico, si mostrano i tempi totali di esecuzione della fattorizzazione al variare del numero di bit.

Come ci aspettiamo da un algoritmo esponenziale, al crescere della dimensione dell’input (numero

di bit dell’intero da fattorizzare) il tempo di esecuzione totale aumenta radicalmente. Nel nostro

caso, i tempi aumentano perché il numero di sieve cresce esponenzialmente, come si nota dal

grafico sottostante.

00.00.47,293 00.01.04,382 00.01.38,432 00.02.59,769

00.07.41,243

00.19.33,253

00.58.18,101

00.00.00,000

00.07.12,000

00.14.24,000

00.21.36,000

00.28.48,000

00.36.00,000

00.43.12,000

00.50.24,000

00.57.36,000

01.04.48,000

0 1 2 3 4 5 6 7 8

Re

al T

ime

Numero esperimento

Real Time al variare del numero di bit

RT

Page 35: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

Figura 4.6 Nel grafico, si mostra come aumenta il numero di sieve da analizzare, estendendo il numero di bit del numero da fattorizzare.

Page 36: Fattorizzazione di numeri interi con Java RMIdigitalforensics.dia.unisa.it/Tesine_SO2/2011-2012/Cinque_Testorio...modo unico, a meno dell’ordine dei fattori, nel prodotto di numeri

5 Conclusioni

L’obiettivo del progetto è: “fattorizzare un intero adoperando il framework Java RMI ”.

Abbiamo scelto di implementare il progetto con Java RMI per sfruttare la sua capacità di invocare

metodi remoti, utilizzando inoltre i thread di Java per distribuire il lavoro tra più macchine Server.

Dai test effettuati si evince che l’implementazione realizzata riesce a fattorizzare un numero

sfruttando la potenza computazionale delle macchine messe a disposizione, ma è facile intuire che

con granularità molto piccola (5-10) o molto grande (30000-40000) del parametro “Dimensione

Sieve”, si ha un degrado progressivo delle prestazioni in termini di tempo impiegato per trovare i

fattori primi del numero. Questo perché con granularità molto piccola il Client genera un file molto

grande in termini di linee di testo, cioè costituito da intervalli di sieve molto piccoli per cui ogni

macchina Server esegue poco calcolo computazionale ma molte volte. Al contrario, con granularità

molto grande viene generato un file con poche linee di testo, ognuna delle quali è costituita da

intervalli di sieve molto grandi e tutto ciò comporta un notevole sforzo computazionale da parte

dei Server.

Come risultato complessivo siamo riusciti a fattorizzare un intero a 138 bit in circa 28 ore su 14

host Server.