Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - Crittare un file grande tramite AES
Forum - C# / VB.NET - Crittare un file grande tramite AES

Avatar
Furion (Normal User)
Rookie


Messaggi: 51
Iscritto: 31/01/2008

Segnala al moderatore
Postato alle 23:24
Giovedì, 05/11/2009
Questo topic è stato chiuso dal moderatore

Salve ragazzi, vorrei porvi questo quesito: sto sviluppando un software tuttofare, una sorta di raccolta di utility, di cui una dovrebbe essere quella di crittaggio tramite AES. Ho trovato un modulo su internet per implementare questo algoritmo ed inzialmente avevo fatto in modo che il mio sw leggesse tutto il file sorgente (es. quello da crittare) e lo crittasse e poi riscrivesse su un nuovo file in un colpo. Ovviamente, però, provando a leggere un file più grande (ho provato con un file di circa 1 Gb e mezzo), il sw ha crashato sollevando la System.OutOfMemoryException (giustamente direi). Allora ho pensato di risolvere avviando un ciclo del genere (scrivo tipo pseudocodice xkè è tardi):

dim buff(1024) as byte
dim readed as ulong = 0
dim info as FileInfo = <File Sorgente>
dim sourceStream as FileStream = info.Open
dim outStream as FileStream = File.Create(fileDiDestinazione)
dim pass as string = "NoNlEgGeRe"
while (readed < info.Length)
  ' leggo nuovi dati
  readed += sourceStream.read(buff, 0, buff.length)
  ' AES è il nome del modulo che ho scritto/trovato ed Encrypt è la funzione di crittaggio
  ' Encrypt vuole la stringa da crittare e la password. Pensa da solo a richiamare i
  ' due metodi private per creare la chiave e l'IV.
  buff = Encoding.Default.GetBytes(AES.Encrypt(Encoding.Default.GetString(buff), pass))
  ' scrivo i dati crittati
  outStream.Write(buff, 0, buff.Length)
end while

Il codice non è proprio quello che sto usando, cmq sta di fatto che finchè tentavo di crittare il file leggendolo in un colpo solo (facendo "sourceStream.Read(buff, 0, info.Length)") e poi passandolo alla funzione di crittaggio con le stesse modalità di codifica che ho scritto, funzionava tutto. Adesso non funziona nulla, o meglio: il processo va a buon fine (secondo lui) ma ho notato che se prima (leggendo e crittando tutto insieme) il file risultante era grande circa il doppio di quello originario, adesso la dimensione finale è addirittura inferiore. Infatti, se poi si prova a decrittare quanto ottenuto (con un ciclo del tutto simile) il sw mi solleva un'eccezione che purtroppo al momento non ricordo. Cos'è che sbaglio? Grazie a tutti in anticipo :hail:

PM
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Segnala al moderatore
Postato alle 20:57
Venerdì, 06/11/2009
Gli algoritmi di crittazione lavorano solitamente su flussi binari di dati. Tu ottieni una stringa, ma può darsi che nella crittazione parte dell'informazione si stata trasformata in blocchi contenenti bytes terminatori che hanno troncato la stringa, diminuendone la lunghezza. Usa Binary Writer e Reader, oppure un semplice FileStream per lavorare su dati binari.
Inoltre, AES mi sembra un algoritmo simmetrico, ma nel caso usassi qualcos'altro non è sicuro che la dimensione dei blocchi di input sia uguale a quella di output, quindi crittare a blocchi non è consigliabile (perchè poi non sapresti come tornare indietro).

PM
Avatar
Furion (Normal User)
Rookie


Messaggi: 51
Iscritto: 31/01/2008

Segnala al moderatore
Postato alle 21:25
Venerdì, 06/11/2009
Allora, intanto grazie per la risposta ed il conseguente interessamento. Mi sembra doveroso fare qualche altra precisazione: innanzitutto il fatto di passare una stringa all'AES non è una mia idea, ma di chi ha scritto il modulo che ho trovato di cui scrivevo nel post precedente. In effetti, vedendo questa soluzione, anch'io ho pensato alle stesse cose che mi hai detto, però ho voluto provare ugualmente. Seconda cosa, in effetti oltre all'AES sto usando un altro piccolo giochino sui byte. Terza ed ultima cosa, il buffer che uso, in realtà, ha una dimensione di 16 Mb esatti (16.777.216 byte): questo perchè ho visto che se riesco a caricare tutto il file sorgente in memoria ed a crittarlo con un unica istruzione, il mio "giochino" e l'AES (nonostante il fatto della stringa) lavorano benissimo di comune accordo. In pratica quello che il mio sw fa è questo

SE fileSorgente.dimensione <= 16 Mb
  arrayDiByte = leggiTutto(fileSorgente)
  arrayDiByte = crittaConMioAlgoritmo(arrayDiByte)
  arrayDiByte = crittaConAES(arrayDiByte)
  scriviSuNuovoFile(arrayDiByte)
ALTRIMENTI
  avvia ciclo di crittaggio a blocchi

Ora il dubbio è: perchè se viene eseguito il primo ramo dell'if funziona tutto? Ti sarebbe di troppo disturbo, inoltre, scrivermi un piccolo esempio (pure in pseudocodice va bene) con le classi che mi hai suggerito? Grazie molte Totem.

Ultima modifica effettuata da Furion il 06/11/2009 alle 21:26
PM
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Segnala al moderatore
Postato alle 10:20
Sabato, 07/11/2009
Qui:
http://totem.altervista.org/guida/versione2/D7.php
C'è un mio esempio che usa l'algoritmo Rinjdael (AES) con dati binari. Il metodo accetta come input un testo solo perchè l'esempio doveva crittare un testo, ma vedi bene che nel corpo della funzione viene convertito in array di byte, quindi puoi modificare la signature di conseguenza.

Qui:
http://totem.altervista.org/guida/versione2/B8.php
C'è un esempio sui file binari, ma vedo che hai usato anche tu un FileStream e non dovresti avere problemi.

PM
Avatar
Furion (Normal User)
Rookie


Messaggi: 51
Iscritto: 31/01/2008

Segnala al moderatore
Postato alle 20:05
Sabato, 07/11/2009
Grazie Totem. Appena ho una attimo di tempo provo a vedere la questione dell'AES e vedo se cambiando il mio reader (io uso un FileStream per leggere e non un BinaryReader) riesco a tirare fuori qualche ragno dal buco. Grazie ancora.

PM
Avatar
Furion (Normal User)
Rookie


Messaggi: 51
Iscritto: 31/01/2008

Segnala al moderatore
Postato alle 22:29
Giovedì, 19/11/2009
Ragazzi scusate il doppio post e la risposta così tardiva. Volevo solo ringraziare Totem xkè la sua risposta mi ha aiutato ha risolvere: in pratica aveva ragione quando parlava della dimensione del blocco da passare all'AES. L'ho corretta ed ora funziona tutto. Ho deciso di rispondere alla discussusione perchè potrebbe essere utile ad altri. Ciao a tutti

PM