2015-06-11 10 views
7

Sto recuperando una chiave unencrypted da un MemoryStream, convertendola in una sorta di stringa e utilizzando quella stringa con le funzioni di .Net crypto per crittografare i dati. Devo assicurarmi che la chiave unencrypted venga cancellata dalla memoria dopo averla utilizzata. Ho trovato SecureString, che penso si prenderà cura della stringa, ma non sono sicuro di come cancellare la memoria della chiave prima che diventi un SecureString.MemoryStream a SecureString: cancellazione della memoria

Quindi il modo tutto funziona è:

MemoryStream -> char [] -> SecureString

SecureString si passa il puntatore alla matrice char, quindi asciuga l'array di caratteri quando si è finito? Questo è di costruttore:

SecureString(Char*,int32) 

C'è un esempio attuazione here.

Tuttavia, una volta che il SecureString salviette i dati (se si asciuga i dati), ho ancora bisogno di sapere come pulire i dati nella MemoryStream, ed eventuali oggetti intermedi devo creare al fine di ottenere il char[].

Quindi questa domanda si riduce a due parti:

Come si fa a leggere un MemoryStream dritto in un char[] senza produrre niente altro nella memoria? (E se questo non è possibile, qual è il passaggio ideale? Cioè, MemoryStream -> string -> char[]?)

e,

Come si fa a sovrascrivere la memoria utilizzata dal MemoryStream (e qualsiasi altro firme create nel processo MemStream->char[]) Al termine?

+1

Cosa intendi con _ senza produrre altro nella memoria_? Quando leggi il tuo stream, la tua chiave è _already_ in memoria - presumibilmente non criptata. Puoi leggerlo in un 'char []' locale e passare a 'SecureString'. Sovrascrivi ed elimina l'array una volta terminato. Non è questo quello che stai cercando? – xxbbcc

+0

[domanda modificata per spiegare questo] Sì, stavo pensando anche a questo. Stavo cercando di evitare di sovrascrivere nulla in memoria manualmente (perché non ho idea di come farlo). Quindi, se ho lo stream di memoria, lo leggo in un char [], uso una stringa sicura (che cancella il char array, giusto?), Quindi ho bisogno di cancellare la memoria da memoryStream ... giusto? Come potrei farlo? Qualcos'altro è stato creato? – bordeo

+0

La risposta breve è che non puoi. Non appena hai i dati in una normale stringa gestita, hai già perso, e non c'è un modo reale affidabile per sbarazzartene. – Servy

risposta

1

Prima di tutto, SecureString non cancella la memoria dell'input char* - sei responsabile per questo. Pulirà solo la sua memoria interna.

Per leggere/pulito il contenuto del MemoryStream in un locale char[], si può semplicemente allocare la matrice (assumendo che il flusso contiene una stringa valida):

// Get the contents of the stream. 
var byKey = oMS.GetBuffer(); 

fixed (byte *pBytes = byKey) 
{ 
    var oSecStr = new SecureString ((char*) pBytes, 
     (int) (oMS.Length/2)); 

    // Clear stream (there's no separate char/byte array 
    // to clean). 
    Array.Clear (byKey, 0, byKey.Length); 
} 

Tutto questo, naturalmente, assume unsafe codice. Non c'è, tuttavia, un modo completamente sicuro per cancellare tutte le potenziali istanze della chiave dalla memoria - durante le chiamate per ottenere la chiave nello stream, può essere copiata un certo numero di volte (in vari buffer privati ​​a cui non si ha accesso) quindi probabilmente non conoscerai nemmeno il numero di copie che ti attendono.

+0

Si consiglia di utilizzare MemorySteams GetBuffer invece di ToArray. Evita di creare una copia del buffer interno di MemoryStream – CSharpie

+0

@CSharpie True. Aggiornerò il campione – xxbbcc

+0

ToArray creerà una copia aggiuntiva, GetBuffer no. Inoltre, stai troncando l'ultimo byte se la lunghezza non è pari. – Zotta

1

Quello che stai cercando è più problematico di quanto tu possa pensare. Un MemoryStream è molto probabilmente usato da qualcos'altro e molto probabilmente aumenterà di dimensioni nel tempo.

Ogni volta che si sviluppa, i dati vengono copiati in un nuovo array interno e il vecchio ci si libera => la chiave potrebbe fuoriuscire qui

Inoltre, un MemoryStream è probabilmente utilizzato da qualche altra API. Molto probabilmente le altre API non cancelleranno in modo sicuro la chiave, perché non sono progettate per farlo.

Ma per rispondere alla domanda originale: se la chiave è solo caratteri ascii, è sufficiente copiare i byte in un array di caratteri e sovrascrivere i byte originali con una posta indesiderata casuale. Puoi accedere ai suoi contenuti direttamente usando GetBuffer.

+0

Probabilmente devo rivedere queste risposte con il mio capo ... – bordeo