Todas as reservas sobre a falta de segurança do SecureString, criando um System.String, deixando de lado , como isso pode ser feito?
Como posso converter um System.Security.SecureString comum em System.String?
Tenho certeza de que muitos de vocês familiarizados com o SecureString responderão que nunca se deve transformar um SecureString em uma string .NET comum porque remove todas as proteções de segurança. Eu sei . Mas, no momento, meu programa faz tudo com seqüências comuns de qualquer maneira, e estou tentando aprimorar sua segurança e, embora eu esteja usando uma API que me devolva uma SecureString, não estou tentando usá-la para aumentar minha segurança.
Estou ciente do Marshal.SecureStringToBSTR, mas não sei como pegar esse BSTR e criar um System.String com ele.
Para aqueles que exigem saber por que eu desejaria fazer isso, estou pegando uma senha de um usuário e enviando-a como um formulário html POST para fazer logon do usuário em um site. Então ... isso realmente precisa ser feito com buffers gerenciados e não criptografados. Se eu conseguisse acessar o buffer não gerenciado e não criptografado, imagino que poderia escrever o fluxo de bytes por byte no fluxo da rede e espero que isso mantenha a senha segura por todo o caminho. Espero uma resposta para pelo menos um desses cenários.
fonte
StopWatch
eSecureStringToString
levei 4,6 segundos para executar. É lento para mim. Alguém consegue o mesmo tempo ou algo mais rápido?Database.GetConnectionString()
no seu código, para obter o meu secureString, que foi a parte maligna que levou quase 5 segundos (e sim, eu deveria analisar isso! :) Seu código levou 0,000 mili segundos no meu cronômetro, para que seja tudo bom. Obrigado por me apontar na direção certa.Obviamente, você sabe como isso derrota todo o propósito de um SecureString, mas eu o reafirmarei de qualquer maneira.
Se você deseja uma linha única, tente o seguinte: (somente .NET 4 e superior)
Onde securePassword é um SecureString.
fonte
[System.Net.NetworkCredential]::new('', $securePassword).Password
''
não é do mesmo tipo que[String]::Empty
? TambémNew-Object Net.Credential
não funciona para mim: Não é possível localizar tipo [Net.Credential]: verificar se o assembly que contém esse tipo é carregadoDang. logo após postar isso, encontrei a resposta profunda neste artigo . Mas se alguém souber como acessar o buffer não gerenciado e não criptografado do IntPtr que esse método expõe, um byte de cada vez, para que eu não precise criar um objeto de string gerenciado para manter minha segurança alta, adicione uma resposta. :)
fonte
unsafe
palavra - chave e achar*
, basta ligarbstr.ToPointer()
e transmitir.SecureString.Length
.SecureString
não está tentando ocultar o valor, está tentando impedir que cópias do valor sejam feitas em regiões que não podem ser sobrescritas com segurança, como memória coletada de lixo, arquivo de paginação etc. A intenção é que, quando aSecureString
vida útil terminar, absolutamente nenhuma cópia do segredo permanece na memória. Isso não impede que você faça e vaze uma cópia, mas nunca o faz.Na minha opinião, métodos de extensão são a maneira mais confortável de resolver isso.
Peguei Steve na excelente resposta de CO e coloquei-a em uma classe de extensão da seguinte forma, juntamente com um segundo método que adicionei para apoiar a outra direção (string -> string segura), para que você possa criar uma string segura e convertê-la em uma sequência normal depois:
Com isso, agora você pode simplesmente converter suas seqüências para frente e para trás da seguinte maneira:
Mas lembre-se de que o método de decodificação deve ser usado apenas para teste.
fonte
Eu acho que seria melhor para
SecureString
funções dependentes encapsular sua lógica dependente em uma função anônima para melhor controle sobre a string descriptografada na memória (uma vez fixada).A implementação para descriptografar SecureStrings neste trecho irá:
finally
bloco.Obviamente, isso torna muito mais fácil "padronizar" e manter os chamadores versus confiar em alternativas menos desejáveis:
string DecryptSecureString(...)
função auxiliar.Observe aqui, você tem duas opções:
static T DecryptSecureString<T>
que permite acessar o resultado doFunc
delegado do chamador (conforme mostrado naDecryptSecureStringWithFunc
método de teste).static void DecryptSecureString
é simplesmente uma versão "vazia" que emprega umAction
delegado nos casos em que você realmente não deseja / precisa retornar nada (como demonstrado noDecryptSecureStringWithAction
método de teste).Exemplo de uso para ambos pode ser encontrado na
StringsTest
classe incluída.Strings.cs
StringsTest.cs
Obviamente, isso não impede o abuso dessa função da seguinte maneira, portanto, tome cuidado para não fazer isso:
Feliz codificação!
fonte
Marshal.Copy(new byte[insecureString.Length], 0, insecureStringPointer, (int)insecureString.Length);
vez dafixed
seção?[char]
, não[byte]
.String.Empty
, não a instância recém-alocada criada e retornada porMarshal.PtrToStringUni()
.Eu criei os seguintes métodos de extensão com base na resposta do rdev5 . Fixar a sequência gerenciada é importante, pois evita que o coletor de lixo a mova e deixe para trás cópias que você não pode apagar.
Penso que a vantagem da minha solução é que não é necessário código inseguro.
fonte
System.String
objeto fazem cópias não fixadas e não utilizadas. É por isso que isso não está embutidoSecureString
.new char[length]
(ou se multiplicamlength
comsizeof(char)
).action
delegado não crie cópias da string temporária, fixada e zerada, essa abordagem deve ser tão segura quanto insegura comoSecureString
ela mesma - para usar a última, uma representação em texto sem formatação também deve ser ser criado em algum momento, considerando que cadeias seguras não são construções no nível do SO; a segurança relativa vem do controle do tempo de vida dessa sequência e da garantia de que ela seja apagada após o uso.SecureString
não possui funções membros e operadores sobrecarregados que fazem cópias em todo o lugar.System.String
faz.NetworkCredential
construtor que aceita aSecureString
.Esse código C # é o que você deseja.
%ProjectPath%/SecureStringsEasy.cs
fonte
Eu derivado de Esta resposta por sclarke81 . Eu gosto da resposta dele e estou usando o derivado, mas o sclarke81's tem um bug. Eu não tenho reputação, então não posso comentar. O problema parece pequeno o suficiente para que não justifique outra resposta e eu possa editá-lo. Então eu fiz. Foi rejeitado. Então agora temos outra resposta.
Espero que você veja isso (finalmente):
deveria estar:
E a resposta completa com a correção de bug:
fonte
A solução final de trabalho de acordo com a solução sclarke81 e as correções de John Flaherty é:
fonte
fonte
BSTR
explicitamente, e não é um objeto .NET, portanto o coletor de lixo também não cuida dele. Comparado a stackoverflow.com/a/818709/103167, publicado 5 anos antes e não vaza.Se você usar um em
StringBuilder
vez de umstring
, poderá sobrescrever o valor real na memória quando terminar. Dessa forma, a senha não ficará na memória até que a coleta de lixo a recolha.fonte