Conversão String para SecureString

Respostas:

137

Você não Todo o motivo do uso do objeto SecureString é evitar a criação de um objeto de seqüência de caracteres (carregado na memória e mantido em texto sem formatação até a coleta de lixo). No entanto, você pode adicionar caracteres a um SecureString anexando-os.

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');
John Dagg
fonte
13
"A combinação é 12345... esse é o tipo de coisa que um idiota tem na bagagem!"
Kolob Canyon
8
Tudo o que vejo é*****
Ian Boyd
AppendCharnão é executado até o tempo de execução; portanto, esses caracteres ainda podem ser lidos na IL, correto? Talvez alguma ofuscação em tempo de compilação ajude também ... isto é, se você estiver codificando senhas.
samis 22/08/19
5
Esse é um argumento manco. Onde você consegue uma senha? De um formulário ou de uma linha de comando. Até que eles criem um método para ler uma string segura diretamente de um dispositivo ou argumentos de linha de comando, precisaremos converter uma string em um SecureString.
Quarkly 11/04/19
1
@DonaldAirey, você recebe uma senha de um gerente de segredos. Geralmente, os segredos de que falamos aqui não são senhas de usuários, mas coisas que potencialmente levam a escalonamento de privilégios ou vazamento de dados. Isso significa que as senhas são para outros serviços e não devem ser passadas por linhas de comando ou por canais de rede.
Barry Kelly
159

Também há outra maneira de converter entre SecureStringe String.

1. String para SecureString

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

2. SecureString para String

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

Aqui está o link

Hossein Narimani Rad
fonte
3
Essa é a melhor solução de longe para o caso de uso mais comum!
precisa saber é o seguinte
16
Não faz sentido usar a SecureStringse seu código criar um stringobjeto com o valor que você deseja proteger. O objetivo SecureStringé evitar ter a sequência na memória gerenciada, para que um invasor examine essa memória para identificar o valor que deseja ocultar. Como o NetworkCredentialconstrutor que você está chamando exige uma string, esse não é o caminho a percorrer ... Claro, seu código é uma maneira fácil de converter de e para um SecureString, mas usá-lo torna seu código tão seguro quanto usar um simplesstring
Gian Paolo
14
@GianPaolo Enquanto isso estiver correto na teoria, na prática ainda precisamos usar SecureStringquando estiver trabalhando com algumas bibliotecas. E vamos ser honestos aqui, se alguém estiver examinando ativamente a memória do seu aplicativo, então você já perdeu. Mesmo se você tiver usado o SecureString corretamente, o que nunca vi, haverá outros dados valiosos para extrair.
Jonathan Allen
1
@ JonathanAllen: Você provavelmente está certo, mas apenas porque temos uma cultura de tratar a segurança como uma reflexão tardia. Se você estiver criando um site de receitas, é provável que a Coreia do Norte não tente digitalizar a memória do seu programa. Se você está escrevendo software bancário, a ameaça é muito mais real.
Eric J.
58

O método abaixo ajuda a converter a string em uma string segura

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;
}
M2012
fonte
26
+1, mas observe que passar a senha como um parâmetro de string cria uma instância de string não criptografada na memória gerenciada e anula o objetivo de 'SecureString' em primeiro lugar. Basta apontar isso para futuras pessoas que aparecerem e usarem esse código.
Cody
19
@Cody Isso é verdade, e um bom argumento, mas muitos de nós não se importam se o SecureString é seguro ou não e só o estão usando porque algumas APIs da Microsoft exigem isso como parâmetro.
precisa saber é o seguinte
3
@Cody Acontece que mesmo a classe SecureString não pode manter a string criptografada. É por isso que a MS está pensando em obsoleta o tipo github.com/dotnet/platform-compat/blob/master/docs/DE0001.md .
Martin Brown
19

Você pode seguir isto:

string password = "test";
SecureString sec_pass = new SecureString();
Array.ForEach(password.ToArray(), sec_pass.AppendChar);
sec_pass.MakeReadOnly();
Escorpião
fonte
11

Aqui está um truque barato de linq.

            SecureString sec = new SecureString();
            string pwd = "abc123"; /* Not Secure! */
            pwd.ToCharArray().ToList().ForEach(sec.AppendChar);
            /* and now : seal the deal */
            sec.MakeReadOnly();
granadaCoder
fonte
32
Esta resposta é um exercício é ver quantas cópias temporárias do texto simples podem ser gerados em um único tiro
Mike Caron
1
como @ john-dagg sugeriu, a idéia é NÃO definir uma string com sua senha, porque, se você fizer isso, não haverá mais vantagem em usar uma proteção. No seu caso, você inseriu a senha em texto sem formatação, nada protegendo mais tarde, usando uma proteção. Espero que você entenda que a proteção foi feita para proteger sua cadeia de pessoas que estão olhando para a desmontagem ou um depurador, para ver o que está na IL / memória.
user734028
8

Vou jogar isso lá fora. Por quê?

Você não pode simplesmente alterar todas as suas strings para protegê-las e, de repente, seu aplicativo é "seguro". A cadeia segura foi projetada para manter a cadeia criptografada pelo maior tempo possível e somente descriptografada por um período muito curto, limpando a memória após a execução de uma operação nela.

Eu arriscaria dizer que você pode ter alguns problemas no nível de design antes de se preocupar em proteger as seqüências de caracteres do aplicativo. Dê-nos mais algumas informações sobre o que você está tentando fazer e podemos ajudar melhor.

Spence
fonte
1
Eu só quero usá-lo para definir a senha para ProcessStartInfo e executar o meu exe como usuário diferente .. Isso funcionou para mim ...
Developer404
4
Meu aplicativo é protegido executando-o em um sistema seguro. Eu não poderia me importar menos com essa seqüência específica sendo criptografada na memória. Há muito mais informações vitais sobre este sistema para se preocupar, caso ele seja comprometido. O SecureString é simplesmente exigido por uma API da Microsoft que meu programa precisa utilizar. Está implícito que o desenvolvedor considere seu próprio caso de uso e determine se a conversão de Strings em SecureStrings é uma operação válida no contexto.
precisa saber é o seguinte
Portanto, esse método não impedirá que alguém veja a senha se ele usar um descompilador como o DotPeek? Existe uma maneira de ocultar seqüências de caracteres neste caso?
31519 M.Parent
Existem alguns métodos, dependendo da ameaça que você está tentando derrotar. Se é para proteger as informações dos usuários de qualquer pessoa que não seja o administrador local, você pode usar os métodos DPAPI no Windows para criptografar um arquivo e armazenar um segredo lá, lê-lo em uma string segura e jogá-lo fora. Se for para um segredo da empresa, a resposta curta será: se o seu aplicativo puder descriptografá-lo, o usuário poderá eventualmente.
Spence
6
unsafe 
{
    fixed(char* psz = password)
        return new SecureString(psz, password.Length);
}
hypersw
fonte
5

sem linq chique, sem adicionar todos os caracteres à mão, pura e simplesmente:

var str = "foo";
var sc = new SecureString();
foreach(char c in str) sc.appendChar(c);
garglblarg
fonte
ainda mais extravagante, não há necessidade de definir uma variável
bigworld12
Aqui está um exemplo:var sc = new SecureString(); foreach(char c in "foo") sc.appendChar(c);
bigworld12 22/07
4

Estou de acordo com Spence (+1), mas se você estiver aprendendo ou testando pourposes, poderá usar um foreach na string, anexando cada caractere ao securestring usando o método AppendChar.

Jonathan
fonte
3

Eu só quero salientar a todo o povo dizendo: "Isso não é o ponto de SecureString", que muitas das pessoas fazendo esta pergunta pode estar em uma aplicação onde, por qualquer motivo, justificado ou não, eles são não particularmente preocupado sobre ter uma cópia temporária da senha fica na pilha como uma sequência capaz de GC, mas eles precisam usar uma API que aceite apenasSecureString objetos. Então, você tem um aplicativo em que não se importa se a senha está no heap, talvez seja apenas para uso interno e a senha só esteja lá porque é necessária pelos protocolos de rede subjacentes e você descobre que a sequência em que a senha está armazenada não pode ser usada para, por exemplo, configurar um PowerShell Runspace remoto - mas não há uma linha única fácil e direta para criar essaSecureStringisto que você precisa. É um pequeno inconveniente - mas provavelmente vale a pena para garantir que as aplicações que realmente fazer precisa SecureStringnão tempt os autores ao uso System.Stringou System.Char[]intermediários. :-)

Jonathan Gilbert
fonte
2

Se você deseja compactar a conversão de a stringem a SecureStringem uma LINQinstrução, pode expressá-la da seguinte maneira:

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; }
                       );

No entanto, lembre-se de que o uso LINQnão melhora a segurança desta solução. Ele sofre da mesma falha que qualquer conversão de stringpara SecureString. Enquanto o original stringpermanecer na memória, os dados estarão vulneráveis.

Dito isto, o que a declaração acima pode oferecer é manter junto a criação do SecureString, sua inicialização com os dados e, finalmente, impedi-lo de modificar.

cel sharp
fonte
2

As 2 extensões a seguir devem fazer o truque:

  1. Para uma charmatriz

    public static SecureString ToSecureString(this char[] _self)
    {
        SecureString knox = new SecureString();
        foreach (char c in _self)
        {
            knox.AppendChar(c);
        }
        return knox;
    }
  2. E para 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;
    }

Obrigado a John Dagg pela AppendCharrecomendação.

Peet
fonte
0

você pode usar esse script simples

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

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

    return ret;
}
nadir
fonte
1
Esta resposta foi publicada há 15 meses . Realmente não havia necessidade de publicá-lo novamente.
GSerg