Come gestire correttamente le password in C #

5

È risaputo che C # string è piuttosto insicuro, non è bloccato nella RAM, Garbage Collector può spostarlo, copiarlo, lasciarne più tracce nella RAM e la RAM può essere scambiata ed essere disponibile come un file da leggere, senza menzionare molti altri fatti noti.

Per mitigare questo Microsoft si avvicinò con SecureString . Il fatto è: qual è il modo corretto di usarlo?

Chiedo questo perché prima o poi dovrai estrarre la stringa interna. E sì, SecureString ci consente di scrivere un char alla volta e ci dà alcuni altri utilizzi minori nascondendo il suo segreto, ma a volte abbiamo bisogno dell'intera stringa in una volta o qualcosa del genere. Finora tutte le implementazioni che vedo utilizzano un normale string alla fine, con il contenuto estratto e decrittografato da SecureString che penso (o spero) sia evitabile in alcuni casi anche se potrebbe comportare un codice complicato da aggirare un .NET string .

Nel mio caso, utilizzo una libreria per l'hashing della password denominata BCrypt . Usa un string regolare per calcolare gli hash, che a mio parere è tutt'altro che ideale. Non ho trovato alcuna libreria che accetti direttamente un SecureString , quindi non ho molte opzioni ma la uso.

Attualmente eseguo codice come questo:

SecureString password; // This usually comes from a PasswordBox Property
IntPtr passwordBSTR = Marshal.SecureStringToBSTR(password);

string insecurePassword = Marshal.PtrToStringBSTR(passwordBSTR);
Marshal.ZeroFreeBSTR(passwordBSTR);
passwordBSTR = default(IntPtr);
password.Clear();

// Use the insecurePassword....usually as:
bool result = BCrypt.Net.BCrypt.Verify(insecurePassword, user.Password); // This hashes the provided password and compares it with another BCrypt hash.

insecureString = string.Empty; // hoping for the GC to act now, fingers crossed.

// use result and etc...

In questo modo la password% raw% co_de verrà copiata più volte per il metodo string e probabilmente anche più volte al suo interno.

Questo fa sorgere alcune domande nella mia mente:

1 - Sono BCrypt stringhe come BSTR stringhe nel senso della gestione della memoria? Sono bloccate nella RAM e posso manipolarle e cancellarle come ritengo opportuno così sarà più sicuro di usarli in C # o di interoplo con un codice C ++ in modo da poter eliminare molte delle mie manipolazioni .NET C (come verificare se la stringa della password è nullo o bianca o ha la lunghezza corretta o ha la password desiderata forza)?

2 - Se la risposta n. 1 della domanda è "sì" allora dovrei investire un po 'di tempo per passare la stringa BSTR a un codice C ++ interop per calcolare il suo hash e verificare?

3 - Il mio codice successivo è corretto o mi manca qualcosa su string manipolazione?

Giusto per essere chiari: il mio intento principale con questa domanda è valutare se dovrei passare tutto il mio codice di gestione password al C ++ dal mio C # (probabilmente usando C ++ / CLI o interop) per ottenere un codice più sicuro di quello che C # ha da offrire. Questo scenario mi riguarda davvero per l'hashing delle stringhe di password in cui sono state create più stringhe e copiate con le informazioni segrete dell'utente sparse in tutta la RAM.

Ad esempio: potrei creare un metodo come:

public string SecureHash(SecureString password)

E questo metodo estrarrà il valore SecureString e lo passerà come una stringa SecureString (o altra opzione di estrazione, onestamente non conosco i vantaggi tra di loro) per un metodo di hashing C ++, così possiamo controllare tutto i luoghi in cui la nostra password si trova in memoria.

Chiedo a questo di non avere un'enorme opera di refactoring del mio codice e alla fine scopro che è stato tutto inutile perché stavo usando BSTR in modo errato tutto il tempo e ci sono già soluzioni per questo, o un falso senso di sicurezza, come accade a volte, poiché non sono a conoscenza di come le stringhe SecureStrings siano implementate in memoria o l'altro BSTR opzioni di estrazione (Unicode, ANSI ed ecc.)

    
posta mFeinstein 20.09.2016 - 01:37
fonte

1 risposta

1

Dipende tutto da cosa vuoi fare.

Rispondi alla prima parte del tuo post:

Esistono implementazioni .net di string sicure in quanto segue: Il controllo di System.Windows.Controls.PasswordBox di WPF mantiene la password come SecureString internamente (esposta come copia tramite PasswordBox :: SecurePassword) The La proprietà System.Diagnostics.ProcessStartInfo :: Password è una SecureString e infine X509Certificate2 richiede una SecureString per la password.

Rispondi alla seconda parte del tuo post:

Se si desidera ottenere di più nella parte interna dell'hashing, BCrypt / BCryptPrimatives / PBKDF2 sono generalmente considerati FIPS 140-2 (A Government Standard) specificamente perché gestiscono con attenzione hashing e password su disco e in memoria.

Se vuoi davvero entrare nel nitty grintoso (e sembra che tu lo faccia ...) Vai qui: collegamento

Ci sono molti dettagli su come funziona in quel PDF, mi dispiace per il link, è troppo grande di un argomento da trattare in un singolo post.

    
risposta data 20.09.2016 - 05:15
fonte

Leggi altre domande sui tag