У меня есть зашифрованная стандартная строка, созданная в powershell через «convertfrom-securestring» и сохраняемая в файл. Позже я прочитал эту зашифрованную строку с помощью приложения C# (под тем же идентификатором пользователя и на том же компьютере). Я хочу преобразовать эту зашифрованную строку в объект securestring. В powershell можно сделать это, используя «convertto-securestring». Как можно это сделать безопасно в C#?безопасно преобразовать зашифрованную стандартную строку в securestring
Мне известно об этом ответе (How can I use ConvertTo-SecureString), , но предполагается, что зашифрованная строка была создана с помощью известного ключа. Это отличается от случая, когда зашифрованная строка была создана без ключа (и, таким образом, привязана к идентификатору пользователя и машине, на которой она была создана.)
Обратите также внимание на то, что в комментариях по вышеуказанному вопросу, была указана документация от Microsoft, в которой указано, что API защиты данных Windows (DPAPI) используется в случае отсутствия ключа. В этой статье (https://msdn.microsoft.com/en-us/library/ms229741(v=vs.110).aspx) показано, как использовать DPAPI, но, к сожалению, использование этого метода, как указано в статье Microsoft, приведет к тому, что строка будет иметь четкий текст в строковом объекте (над которым мы не имеем никакого контроля, a-vis), и поэтому использование его в указанном порядке будет небезопасным.
Фактически, это фактически комбинация этого (How to decrypt a string in C# which is encrypted via PowerShell) и вопроса в How can I use ConvertTo-SecureString.
Для записи, этот код работает, но я не уверен, что проблемы могут быть с хранением расшифрованные строки в массиве байт, даже если я колошматить его как можно быстрее:
public static unsafe SecureString MakeSecurityString(string pwd)
{
int lngth = pwd.Length/2;
byte[] encrypted = new byte[lngth];
for (int i = 0; i < lngth; ++i)
{
encrypted[i] = byte.Parse(pwd.Substring(2 * i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
byte[] decrypted = ProtectedData.Unprotect(encrypted, (byte[])null, DataProtectionScope.CurrentUser);
lngth = decrypted.Length - 1;
byte[] chr = new byte[2];
SecureString secureString = new SecureString();
for (int i = 0; i < lngth;)
{
chr[0] = decrypted[i]; decrypted[i++] = 0;
chr[1] = decrypted[i]; decrypted[i++] = 0;
string passwd = UnicodeEncoding.Unicode.GetString(chr);
secureString.AppendChar(passwd[0]);
}
return secureString;
}
Обратите внимание на кажущуюся глупость копирования байтовых пар от decrypted
до chr
, а затем с применением UnicodeEncoding.Unicode.GetString
по одному символу за раз. Если бы мы просто сделать это
string passwd = UnicodeEncoding.Unicode.GetString(decrypted);
for (int i = 0; i < passwd.Length; ++i)
{
secureString.AppendChar(passwd[i]);
}
тогда мы разместили «расшифрованы» строку в объект строки, и он может торчать в памяти - мы не имеем никакого контроля. Вышеприведенный код избегает этого. Мне непонятно, что оставить массив байтов и обнулить его там гарантирует, что в памяти не будет никаких копий. Может кто-нибудь прокомментировать это?
Возможный дубликат [Как использовать ConvertTo-SecureString] (http://stackoverflow.com/questions/13633826/how-can-i-use-convertto-securestring) –
Насколько безопасна SecureString? Он защищает (расшифровывает) буфер с каждым вызовом AppendChar() или вызовом InsertAt() или SetAt(), и выполняет работу, и снова зашифровывает буфер. Блок памяти будет содержать незашифрованные данные в течение очень короткого времени. Я думаю, что это то, что вы также должны реализовать; хранить незашифрованные данные в памяти как можно короче. –
Да, отдельные байты будут отображаться мгновенно в ясном тексте один за другим. Но проблема заключается в следующем: при использовании одного символа для хранения символов этот одиночный символ не является чем-то вроде кучи, где нужно беспокоиться о его жизни после смерти, т. Е. О том, что он висит вокруг в памяти кучи. Во-вторых, мы помещаем что-то вроде пароля в строку, в C# мы теряем контроль над памятью, содержащей эту строку: у нас нет способа гарантировать уничтожение (переписывание) строки байта. Он может долгое время находиться в памяти и находить его в спящих изображениях и т. Д. –