Converti String in SecureString


Risposte:


137

Non lo fai. L'intera ragione per utilizzare l'oggetto SecureString è evitare di creare un oggetto stringa (che viene caricato in memoria e conservato in testo normale fino alla raccolta dei rifiuti). Tuttavia, puoi aggiungere caratteri a SecureString aggiungendoli.

var s = new SecureString();
s.AppendChar('d');
s.AppendChar('u');
s.AppendChar('m');
s.AppendChar('b');
s.AppendChar('p');
s.AppendChar('a');
s.AppendChar('s');
s.AppendChar('s');
s.AppendChar('w');
s.AppendChar('d');

13
"La combinazione è 12345... questo è il genere di cose che un idiota ha nel suo bagaglio!"
Kolob Canyon,

8
Tutto quello che vedo è*****
Ian Boyd

AppendCharnon viene eseguito fino al runtime, quindi quei caratteri possono ancora essere letti dall'IL, giusto? Forse anche un po 'di offuscamento in fase di compilazione potrebbe aiutare ... cioè, se stai codificando le password.
samis

5
Questo è un argomento noioso. Dove prendi una password? Da un modulo o da una riga di comando. Fino a quando non creano un metodo per leggere una stringa sicura direttamente da un dispositivo o da argomenti della riga di comando, dovremo convertire una stringa in SecureString.
Quarkly

1
@DonaldAirey ottieni una password da un gestore di segreti. Generalmente i segreti di cui stiamo parlando qui non sono le password degli utenti, ma cose che potenzialmente portano all'escalation dei privilegi o alla fuga di dati. Ciò significa che le password sono per altri servizi e non devono essere passate su righe di comando o in chiaro sui canali di rete.
Barry Kelly

160

C'è anche un altro modo per convertire tra SecureStringeString .

1. String a SecureString

SecureString theSecureString = new NetworkCredential("", "myPass").SecurePassword;

2. SecureString a String

string theString = new NetworkCredential("", theSecureString).Password;

Ecco il link


4
Questa è di gran lunga la migliore soluzione per il caso d'uso più comune!
Dan Bechard

16
Non ha senso usare a SecureStringse il codice crea un stringoggetto con il valore che si desidera proteggere. L'obiettivo di SecureStringè evitare di avere la stringa nella memoria gestita, in modo che un utente malintenzionato che esamina quella memoria possa individuare il valore che si desidera nascondere. Poiché il NetworkCredentialcostruttore che stai chiamando richiede una stringa, non è questa la strada da percorrere ... Certo, il tuo codice è un modo semplice per convertire da e verso una SecureString, ma usarlo rende il tuo codice sicuro come usare un semplicestring
Gian Paolo

15
@GianPaolo mentre è corretto in teoria, in pratica dobbiamo ancora usarlo SecureStringquando lavoriamo con alcune librerie. E siamo onesti qui, se qualcuno sta attivamente scansionando la memoria della tua applicazione, allora hai già perso. Anche se hai usato SecureString correttamente, cosa che non ho mai visto, ci saranno altri dati preziosi da estrarre.
Jonathan Allen

1
@ JonathanAllen: Probabilmente hai ragione, ma solo perché abbiamo una cultura di considerare la sicurezza come un ripensamento. Se stai creando un sito web di ricette, è improbabile che la Corea del Nord provi a scansionare la memoria del tuo programma. Se stai scrivendo software bancario, la minaccia è molto più reale.
Eric J.

58

sotto il metodo aiuta a convertire la stringa in stringa sicura

private SecureString ConvertToSecureString(string password)
{
    if (password == null)
        throw new ArgumentNullException("password");

    var securePassword = new SecureString();

    foreach (char c in password)
        securePassword.AppendChar(c);

    securePassword.MakeReadOnly();
    return securePassword;
}

26
+1, ma si noti che il passaggio della password come parametro di stringa crea un'istanza di stringa non crittografata nella memoria gestita e annulla lo scopo di "SecureString" in primo luogo. Faccio solo notare questo per le persone future che vengono e usano questo codice.
Cody

19
@Cody È vero, ed è un buon punto, ma a molti di noi non interessa se SecureString è sicuro o meno e lo utilizzano solo perché alcune API Microsoft lo richiedono come parametro.
Dan Bechard

3
@Cody Si scopre che anche la classe SecureString non può mantenere la stringa crittografata. Questo è il motivo per cui MS sta valutando di rendere obsoleto il tipo github.com/dotnet/platform-compat/blob/master/docs/DE0001.md .
Martin Brown

19

Puoi seguire questo:

string password = "test";
SecureString sec_pass = new SecureString();
Array.ForEach(password.ToArray(), sec_pass.AppendChar);
sec_pass.MakeReadOnly();

11

Ecco un trucco linq economico.

            SecureString sec = new SecureString();
            string pwd = "abc123"; /* Not Secure! */
            pwd.ToCharArray().ToList().ForEach(sec.AppendChar);
            /* and now : seal the deal */
            sec.MakeReadOnly();

32
Questa risposta è un esercizio per vedere quante copie temporanee del testo normale possono essere generate in un colpo solo
Mike Caron

1
come suggerito da @ john-dagg, l'idea è di NON impostare una stringa con la tua password perché se lo fai non c'è alcun vantaggio nell'usare una stringa di sicurezza. Nel tuo caso hai inserito la password in testo normale, non stai proteggendo nulla in seguito utilizzando una stringa di sicurezza. Spero che tu capisca che la stringa di sicurezza aveva lo scopo di proteggere la tua stringa da persone che guardano il disassemblaggio o un debugger, quindi guarda cosa c'è nella memoria IL /.
user734028

8

Lo butto là fuori. Perché?

Non puoi semplicemente cambiare tutte le tue stringhe in stringhe protette e improvvisamente la tua applicazione è "sicura". La stringa sicura è progettata per mantenere la stringa crittografata il più a lungo possibile e decrittografata solo per un periodo di tempo molto breve, cancellando la memoria dopo che è stata eseguita un'operazione su di essa.

Azzarderei dire che potresti avere alcuni problemi a livello di progettazione da affrontare prima di preoccuparti di proteggere le stringhe dell'applicazione. Dacci qualche informazione in più su ciò che stai cercando di fare e potremmo essere in grado di aiutarti meglio.


1
Voglio solo usarlo per impostare la password per ProcessStartInfo ed eseguire il mio exe come utente diverso .. Ha funzionato per me ...
Developer404

4
La mia applicazione è protetta eseguendola su un sistema sicuro. Non mi potrebbe importare di meno che questa particolare stringa venga crittografata in memoria. Ci sono molte più informazioni vitali su questo sistema di cui preoccuparsi se dovesse mai essere compromesso. SecureString è semplicemente richiesto da un'API Microsoft che il mio programma deve utilizzare. È implicito che lo sviluppatore consideri il proprio caso d'uso e determini se la conversione di stringhe in SecureStrings è un'operazione valida nel contesto.
Dan Bechard

Quindi questo metodo non impedirà a qualcuno di vedere la password se usa un decompilatore come DotPeek? C'è un modo per nascondere le stringhe in questo caso?
M.Parent

Esistono alcuni metodi, a seconda della minaccia che stai cercando di sconfiggere. Se è per proteggere le informazioni degli utenti da chiunque tranne l'amministratore locale, è possibile utilizzare i metodi DPAPI su Windows per crittografare un file e archiviarvi un segreto, leggerlo in una stringa sicura e quindi buttarlo via. Se è per un segreto aziendale, la risposta breve è se la tua applicazione è in grado di decrittografarlo, così alla fine può farlo anche l'utente.
Spence

6
unsafe 
{
    fixed(char* psz = password)
        return new SecureString(psz, password.Length);
}

5

nessuna linq fantasia, non aggiungendo tutti i caratteri a mano, solo semplice e semplice:

var str = "foo";
var sc = new SecureString();
foreach(char c in str) sc.appendChar(c);

ancora più elaborato, non c'è bisogno di definire una variabile
bigworld12

ecco un one liner:var sc = new SecureString(); foreach(char c in "foo") sc.appendChar(c);
bigworld12

4

Sono d'accordo con Spence (+1), ma se lo stai facendo per l'apprendimento o per testare scopi, puoi usare un foreach nella stringa, aggiungendo ogni carattere alla stringa di sicurezza usando il metodo AppendChar.


3

Voglio solo far notare a tutto il popolo dicendo: "Non è questo il punto di SecureString", che molte delle persone che chiedono a questa domanda potrebbe essere in un'applicazione in cui, per qualsiasi motivo, giustificata o meno, essi sono non particolarmente preoccupati di avere una copia temporanea della password si trova nell'heap come stringa compatibile con GC, ma devono utilizzare un'API che accetta soloSecureString oggetti. Quindi, hai un'app in cui non sai interessase la password è nell'heap, forse è solo per uso interno e la password è presente solo perché è richiesta dai protocolli di rete sottostanti e si scopre che quella stringa in cui è memorizzata la password non può essere utilizzata, ad esempio, per configurare un PowerShell remoto Runspace - ma non esiste un one-liner semplice e diretto per creare quello SecureStringche ti serve. E 'un piccolo inconveniente - ma probabilmente ne vale la pena per garantire che le applicazioni che realmente fanno è necessario che SecureStringnon si tenti di utilizzare l'autori System.Stringo System.Char[]intermediari. :-)


2

Se desideri comprimere la conversione di a stringin a SecureStringin LINQun'istruzione, puoi esprimerla come segue:

var plain  = "The quick brown fox jumps over the lazy dog";
var secure = plain
             .ToCharArray()
             .Aggregate( new SecureString()
                       , (s, c) => { s.AppendChar(c); return s; }
                       , (s)    => { s.MakeReadOnly(); return s; }
                       );

Tuttavia, tieni presente che l'utilizzo LINQnon migliora la sicurezza di questa soluzione. Soffre dello stesso difetto di qualsiasi conversione da stringa SecureString. Finché l'originale stringrimane in memoria, i dati sono vulnerabili.

Detto questo, ciò che l'istruzione sopra può offrire è mantenere insieme la creazione del SecureString, la sua inizializzazione con i dati e infine bloccarlo dalla modifica.


2

Le seguenti 2 estensioni dovrebbero fare il trucco:

  1. Per un chararray

    public static SecureString ToSecureString(this char[] _self)
    {
        SecureString knox = new SecureString();
        foreach (char c in _self)
        {
            knox.AppendChar(c);
        }
        return knox;
    }
  2. E per string

    public static SecureString ToSecureString(this string _self)
    {
        SecureString knox = new SecureString();
        char[] chars = _self.ToCharArray();
        foreach (char c in chars)
        {
            knox.AppendChar(c);
        }
        return knox;
    }

Grazie a John Dagg per la AppendCharraccomandazione.


0

puoi usare questo semplice script

private SecureString SecureStringConverter(string pass)
{
    SecureString ret = new SecureString();

    foreach (char chr in pass.ToCharArray())
        ret.AppendChar(chr);

    return ret;
}

1
Questa risposta è stata pubblicata 15 mesi fa . Non c'era davvero bisogno di postarlo di nuovo.
GSerg
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.