Как SecureString зашифрован и по-прежнему можно использовать?

Согласно MSDN, содержимое SecureString зашифровано для дополнительных безопасность, так что, если программа заменена на диск, содержимое строки не может быть перехвачено.

Интересно, как возможно такое шифрование? Алгоритм будет фиксированным и, следовательно, либо хорошо известным, либо подлежащим вычету (скажем, одним из семи широко используемых в отрасли алгоритмов), и где-то в программе должен быть ключ. Таким образом, злоумышленник может получить зашифрованную строку, получить ключ и расшифровать данные.

Чем может быть полезно такое шифрование?


person sharptooth    schedule 08.08.2011    source источник
comment
Там не сказано, что это безопасно, только безопаснее   -  person Mark Peters    schedule 08.08.2011
comment
@Mark Peters: Вот почему я говорю дополнительная безопасность.   -  person sharptooth    schedule 08.08.2011
comment
вы можете спросить об этом на сайте crypto.SE - там очень по теме   -  person Rory Alsop    schedule 09.08.2011


Ответы (4)


Я цитирую статью о DPAPI, который используется для получения ключ. Это должно ответить на большинство ваших вопросов о SecureString.

И да, SecureString имеет недостатки и не совсем безопасен, есть способы доступа к данным, например, инъекция Hawkeye в процессе упоминается в MSDN как способ извлечения SecureString. Я лично не проверял это утверждение.

Управление ключами DAPI

DAPI - это метод симметричного шифрования, что означает, что он использует один и тот же ключ как для шифрования, так и для дешифрования данных. Прежде чем перейти к некоторым примерам использования DAPI, стоит рассказать, как DAPI управляет своим ключом. По большей части процесс управления ключами DAPI незаметен, и вам обычно не нужно о нем беспокоиться, что является основной причиной, по которой DAPI является хорошим подходом.

Во введении я написал, что мастер-ключ генерируется из пароля пользователя для входа. Это не полная картина. На самом деле происходит то, что Windows использует пароль для входа пользователя для генерации главного ключа. Этот главный ключ защищен паролем пользователя и затем сохраняется вместе с профилем пользователя. Затем этот главный ключ используется для получения ряда других ключей, и именно эти ключи используются для защиты данных.

Причина, по которой Windows делает это, заключается в том, что она позволяет приложениям добавлять дополнительную информацию, называемую энтропией, в процесс генерации отдельных ключей. Вы видите, если каждое приложение, работающее под учетной записью пользователя, использовало один и тот же ключ, тогда каждое приложение могло бы снять защиту данных, защищенных DAPI. Иногда вам может потребоваться, чтобы приложения могли совместно использовать данные, защищенные DAPI; однако иногда вы этого не сделаете. Позволяя приложению вносить энтропию в генерацию ключа, этот ключ становится специфичным для приложения, и любые данные, которые защищены этим приложением, могут быть снова сняты с защиты только в том случае, если им известна энтропия.

Хотя создание главного ключа и последующее использование этого главного ключа для генерации других ключей для фактического шифрования может показаться многословным подходом, у него есть одно важное преимущество. Поскольку существует дополнительный уровень абстракции между главным ключом, защищенным паролем пользователя, и фактическими ключами, используемыми для защиты данных, это означает, что, когда пользователь меняет свой пароль, необходимо повторно защищать только главный ключ; ни одна из защищенных данных не нуждается в повторной защите. Поскольку главный ключ намного меньше по размеру, чем данные, достигается значительная экономия производительности.

При изменении пароля пользователя, конечно же, создается новый мастер-ключ. Этот новый главный ключ затем используется для создания новых индивидуальных ключей. Однако, поскольку все ранее сгенерированные индивидуальные ключи были получены из старого главного ключа, Windows должна сохранить все предыдущие главные ключи, что она и делает. Windows никогда не забывает мастер-ключ, и все защищенные данные помечаются идентификатором GUID, который указывает, какой мастер-ключ использовался для защиты данных. Таким образом, с точки зрения адаптируемости DAPI способен справляться с изменениями паролей пользователей, обеспечивая при этом: а) то, что защищенные данные не нужно повторно защищать, и б) ключи, которые ранее использовались для защиты данных, оставаясь доступными, и ) он сделает все это автоматически за вас.

Если компьютер не является членом домена, DAPI может использовать только незащищенные данные на том же компьютере, который использовался для его защиты.

Помимо обеспечения защиты на уровне пользователя, поскольку главные ключи основаны на паролях пользователей, а защищенные данные для одного пользователя не могут быть сняты с защиты другим пользователем, DAPI также обеспечивает защиту на уровне компьютера, поскольку главные ключи основаны на информации, зависящей от компьютера. Мастер-ключи машинного уровня позволяют приложениям хранить защищенные данные, так что они могут быть незащищены всеми пользователями приложения. Единственная разница в уже описанном процессе заключается в том, что главный ключ генерируется на основе информации о машине, а не информации пользователя.

person NetSquirrel    schedule 08.08.2011
comment
Я думаю, что ключевым моментом, который следует вынести из опубликованной статьи, является то, что по большей части процесс управления ключами DAPI является невидимым, и вам, как правило, не нужно об этом беспокоиться. Это сразу заставляет меня склоняться к индивидуальному решению. Достаточно хорошая защита не всегда достаточно хороша. - person Michael Brown; 05.02.2015
comment
Примечание. По состоянию на 18.05.2017 ссылка на статью возвращает 404: dsmyth.net /wiki/Print.aspx?Page=StudyNotes_DAPI - person iokevins; 18.05.2017

Я просмотрел один момент в его коде, и он использует advapi32 Windows для выполнения своей грязной работы. Таким образом, ключ не хранится в памяти приложения.

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static int SystemFunction040([In, Out] SafeBSTRHandle pDataIn, [In] uint cbDataIn, [In] uint dwFlag)

Что более известно как RtlEncryptMemory.

Он расшифровывает с помощью RtlDecryptMemory (SystemFunction041).

Я уверен, что компилятор что-то делает и с SecurityCriticalAttribute.

изменить это было отражено в 4.0. другие версии могут отличаться.

person Daniel A. White    schedule 08.08.2011

Как уже ответили другие, содержимое SecureString зашифровано с использованием DPAPI, поэтому ключи не хранятся в вашем приложении, они являются частью ОС. Я не уверен на 100%, но я бы предположил, что SecureString использует специфичный для пользователя ключ, так что даже если другой процесс получит доступ к блоку памяти, он должен будет работать под теми же учетными данными, чтобы просто расшифровать контент с помощью DPAPI. Даже если нет, машинный ключ (теоретически) предотвращает быстрое дешифрование строки при передаче в другую систему.

Более важным с SecureString является то, как и когда вы его используете. Его следует использовать для хранения строковых данных, которые должны храниться в памяти в течение «продолжительных» периодов времени, но которые не часто нужны в их расшифрованном виде. В какой-то момент вам придется расшифровать его в обычный старый System.String или System.Char[]. Это когда память наиболее уязвима. Если вы будете делать это слишком часто, у вас будет несколько копий расшифрованной строки, плавающих в памяти, ожидающих сбора.

Как правило, если я читаю зашифрованные данные (например, учетные данные для входа), которые мне нужно сохранить для нечастого использования (например, для взаимодействия с PayPal или Amazon API), я сохраняю / кэширую эти учетные данные как SecureString, а затем расшифровываю их как -достаточно долго, чтобы выполнять вызовы веб-службы, и гарантировать, что срок службы любой дешифрованной копии составляет всего несколько строк кода.

Вероятно, также разумно использовать критические блоки или аналогичные подсказки для CLR о том, что не следует переключать контекст во время использования расшифрованной строки, чтобы повысить шансы того, что любые расшифрованные копии будут собраны до того, как память будет кэширована или заменена.

person Toby    schedule 08.08.2011

Магией DPAPI:

Этот класс хранит свои данные с помощью модели защищенной памяти Data Protection API (DPAPI). Другими словами, данные всегда находятся в зашифрованном виде, пока они хранятся внутри SecureString. Ключ шифрования управляется подсистемой локального органа безопасности (LSASS.EXE), и через DPAPI данные могут быть расшифрованы посредством межпроцессного взаимодействия.

person Steve Morgan    schedule 08.08.2011