Как SecureString "зашифрована" и все еще может использоваться? - PullRequest
36 голосов
/ 08 августа 2011

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

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

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

Ответы [ 4 ]

18 голосов
/ 08 августа 2011

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

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

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

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

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

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

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

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

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

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

11 голосов
/ 08 августа 2011

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

[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.

edit Это было отражено с помощью 4.0. другие версии могут разные.

7 голосов
/ 08 августа 2011

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

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

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

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

2 голосов
/ 08 августа 2011

Волшебством DPAPI:

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

...