Безопасные строки в .net – класс SecureString
Наверное вам приходилось хотя бы однажды иметь дело с паролями? Что если вашему приложению необходимо расшифровать данные и оперировать ними в памяти? А если это лицензионный ключ к вашей программе, который вы создаете путем шифрования каких-то данных?
Примеров, где безопасность строк может быть посталвена под сомнение можно найти сколько угодно. В данном случае речь идет о безопасном хранении строки в памяти, чтобы ее невозможно было узнать сняв дамп.
Для таких целей в .net существует специальный класс – System.Security.SecureString. Строка созданая посредством этого класса остается зашифрованой в памяти, поэтому узнать ее сняв дамп или просканировав память – не получится, разве что придется узнав ключ симмертического шифрований. Также основной особенностью таких строк есть то, как они располагаются в памяти. SecureString – “закреплен” в памяти, чтобы избежать содание копий объекта сборщиком мусора .NET, сохраняя всего одну копию. Также такие строки не попадуть в swap файл.
SecureString создается по особенному – по-символьно. То есть код создания экзепляра такого объекта будет выглядеть так:
SecureString secureStr = new SecureString();
for (int i = 0; i < someString.Length; i++)
secureStr.AppendChar(someString[i]);
secureStr.MakeReadOnly();
Метод MakeReadOnly делает объект read-only и запрещает его редактирование в дальнейшем. Вычитка SecureString также усложнена:
IntPtr stringPointer = Marshal.SecureStringToBSTR(secureStringObj);
try
{
string normalString = Marshal.PtrToStringBSTR(stringPointer);
}
finally
{
Marshal.ZeroFreeBSTR(stringPointer);
}
К тому же он реализует IDisposable для того чтобы в нужный момент можно было вручную удалить его из памяти и удалять такую строку сразу после использования – рекомендовано.
using (SecureString ss = new SecureString())
{
// use the secure string
}
SecureString наследуется от абстрактного CriticalFinalizerObject. Это обеспечивает что код финализации SecureString маркируется как критический и выполняется всегда даже если поток был завершен abnormally. И как результат SecureString успешно очищается из памяти.
SecureString не защищает от всех бед, а он защищает строку которая хранится в памяти и обеспечивает возможность ее быстрого удаления. SecureString создается посимвольно что позволяет использовать его в связки с ”password” textbox’ами. Существуют готовые реализции таких textbox’ов, хотя их еще нужно проверять, и написать свой, если понадобится, много труда не составит.
Некоторые части .NET Framework используют SecureString, вот некоторые примеры:
- В WPF элемент управления PasswordBox хранит строки внутри как SecureString
- Свойство Password класса System.Diagnostics.ProcessInfo – SecureString
- Конструктор класса X509Certificate2 принимает SecureString как пароль
Смысл SecureString проявляется тогда когда он создается и наполняется правильно. Дело в том что если мы будем создавать его из уже существующей строки в памяти, или конвертировать из существующей строки, то обычная строка останется какое-то время в памяти, что, фактически, сведет на нет все наши усилия и пляски с SecureString. Поэтому основные применения это посимольный ввод в “password” текст боксах или посимольное чтение из потока. Возможно также вычитывать какие-то зашифрованые данные и расшифровывать их сразу в SecureString .
Компании из статьи
Microsoft Украина | Украинское подразделение компании Microsoft. |