Сводка:
Метод Dispose () объекта RSACryptoServiceProvider выбрасывает CryptographicException без видимой причины. Похоже, что это происходит из-за плохого программирования в классе SafeProvHandle, который он использует для базового провайдера на неуправляемом уровне, где он пытается работать с временным файлом. Я предполагаю, что мой вопрос в основном «почему это происходит?», Но, конечно, с конечной целью: «как программисту лучше всего этого избежать?»
Контекст:
Старое консольное приложение, предназначенное для NET Framework 3.5 для процессора типа x86, но работающее на Windows 10 x64 Pro (в частности, 10.0.17134 Build 17134). Приложение не имеет каких-либо явных настроек в конфигурации или манифесте приложения, говорящих о том, что оно поддерживает windows 10. Большинство вещей работают просто отлично, как и на Windows XP (!), Но это одно из пары странных отличий Я столкнулся с. На самом деле, я почти уверен, что это раньше работало просто (без исключения) на Windows 10 некоторое время назад, и я не уверен, почему это изменилось (я знаю, что программа работала, и она будет иметь должен был расшифровать один из его параметров, даже если он пытается это сделать, но получает это исключение). Когда тот же код предназначен для более новых платформ (> =. NET Framework 4), это исключение не генерируется, но оно имеет небольшую ценность, когда приложение застряло на 3.5 (как у меня, по причинам, неважным здесь). Это не имеет никакого отношения к любой другой платформе - это происходит даже в простом консольном приложении.
Исключение:
Исключение выдается, когда какой-либо объект RSACryptoServiceProvider имеет расположены. Чтобы изолировать его, можно перейти от блока «using» к структуре «try / finally», а затем использовать метод Clear () в блоке finally (метод Dispose () сделан недоступным, и Сейчас я делаю это вместо того, чтобы иметь блок «using» только для того, чтобы я мог выделить точную точку, в которую выдается исключение). Обычно ToString () исключения дает строку примерно так:
System.Security.Cryptography.CryptographicException: The process cannot access the file because it is being used by another process.
at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
at System.Security.Cryptography.SafeProvHandle._FreeCSP(IntPtr pProvCtx)
at System.Security.Cryptography.SafeProvHandle.ReleaseHandle()
at System.Runtime.InteropServices.SafeHandle.InternalDispose()
at System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
at System.Runtime.InteropServices.SafeHandle.Dispose()
at System.Security.Cryptography.RSACryptoServiceProvider.Dispose(Boolean disposing)
at System.Security.Cryptography.AsymmetricAlgorithm.System.IDisposable.Dispose()
at System.Security.Cryptography.AsymmetricAlgorithm.Clear()
at Baker.Security.SafelyDisposeRCSP(RSACryptoServiceProvider rsa, Boolean encVsDec) in %PROJECT_DIR%\Security.cs:line 95
(я заменил путь к своему источнику на% PROJECT_DIR%).
Этот появляется сразу после любой успешной попытки расшифровать строку. Но после любой успешной попытки зашифровать строку последующий вызов Clear приводит к возникновению CryptographicException с той же трассировкой стека, но с другим Message : доступ запрещен.
Поэтому сообщение об исключении будет быть одной из двух форм:
The process cannot access the file because it is being used by another process.
Access is Denied
Я также выделил демонстрационный код в очень маленький проект. Он показывает то же поведение за исключением того, что по крайней мере иногда и Encrypt и Decrypt приводят к «Доступ запрещен». Так что именно то, что вы получаете, когда может меняться. Но я собрал следующие детали из исходного приложения:
Неуместность:
В любом случае, даже мой клиентский код в непосредственной близости от вызова метода-нарушителя не является явным пытается что-то сделать с файлом, поэтому сообщение об исключении совершенно бесполезно. На самом деле, это вводит в заблуждение, потому что изначально код перехватывал исключение только на гораздо более высоком уровне, когда мой клиентский код был на самом деле пытался записывать или читать из файла настроек XML, где имя пользователя и пароль для соединения с базой данных оба зашифрованы, но это была скорее ошибка этого клиентского кода, не имеющего отношения к исключению в месте, где его несвязанность с файлом настроек XML будет ясна. И кто бы мог ожидать, что избавление от объекта, не рекламирующего какое-либо использование файловой системы, вызовет этот тип исключения? Но мы можем предположить, что исключения относятся к чему-то внутреннему к тому, как работает RSACryptoServiceProvider.
Подробности причины низкого уровня:
Поскольку исключение не дает представления о том, к какому файлу оно может относиться, единственный способ, который я смог выяснить, - это одновременно использовать procmon (из SysInternals ) для отслеживания системных вызовов. Как вы увидите ниже, кажется, что объект RSACryptoServiceProvider создает временный файл, возможно, для хранения некоторой информации о состоянии, а затем он пытается переименовать (переместить?) Этот файл в другой временный путь к файлу (оба находятся в AppData). под профилем пользователя). Либо эта операция, либо повторное открытие (создание) завершается неудачей. Ничего из этого не описано в документации, поэтому трудно догадаться, какова реальная цель этого действия. В любом случае, как показано в приведенной выше трассировке стека, он выдает исключение из Dispose () SafeProvHandle (который, как я предполагаю, является всего лишь производным классом со спецификацией типа c, расширяющим SafeHandle ), который является одним из двух обернутых элементов дескриптора объекта RSACryptoServiceProvider.
Еще одна странность заключается в том, что всякий раз, когда у меня останавливается код в отладчике, где выбрасывается исключение, исходный файл имеет 1318 все байты установлены в 0, поэтому файл фактически не содержит никакой полезной информации. Какова его цель? Я не знаю. Кроме того, я попытался выполнить операцию переименования вручную, и она прошла успешно, и ничего необычного не произошло. Так почему же RSACryptoServiceProvider не может это сделать? Я не знаю, но, возможно, выполнение этого из Windows Explorer включает в себя различные системные вызовы.
Из procmon, вот некоторые соответствующие крипто-события, которые выполнял процесс, приводящий к созданию исключения. Я заменил префикс пути моего домашнего каталога на% USERPROFILE%, и я предполагаю, что это SID пользователя с% USERSID%, чтобы уменьшить размер этих строк, которые были вставлены здесь в формате с разделителями табуляции, но я не думаю, что переполнение стека сохраняет вкладки:
Time of Day Operation Path Result Detail
4:30:00.1340329 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Desired Access: Generic Write, Read Attributes, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: S, ShareMode: None, AllocationSize: n/a, OpenResult: Opened
4:30:00.1342753 p.m. QueryStandardInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS AllocationSize: 4,096, EndOfFile: 1,318, NumberOfLinks: 1, DeletePending: False, Directory: False
4:30:00.1342908 p.m. WriteFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Offset: 0, Length: 1,318, Priority: Normal
4:30:00.1343567 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS
4:30:00.1346438 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Desired Access: Read Attributes, Delete, Disposition: Open, Options: Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
4:30:00.1348435 p.m. QueryAttributeTagFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Attributes: SA, ReparseTag: 0x0
4:30:00.1348624 p.m. SetDispositionInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 ACCESS DENIED Delete: True
4:30:00.1746923 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS
4:30:00.1749270 p.m. CreateFile %USERPROFILE%\AppData\Local\Temp SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
4:30:00.1749638 p.m. QueryBasicInformationFile %USERPROFILE%\AppData\Local\Temp SUCCESS CreationTime: 9/19/2018 3:24:30 p.m., LastAccessTime: 1/31/2020 4:29:47 p.m., LastWriteTime: 1/31/2020 4:29:47 p.m., ChangeTime: 1/31/2020 4:29:47 p.m., FileAttributes: D
4:30:00.1749774 p.m. CloseFile %USERPROFILE%\AppData\Local\Temp SUCCESS
4:30:00.1751791 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
4:30:00.1752765 p.m. QueryAttributeTagFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Attributes: SA, ReparseTag: 0x0
4:30:00.1753066 p.m. QueryBasicInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS CreationTime: 1/31/2020 4:30:00 p.m., LastAccessTime: 1/31/2020 4:30:00 p.m., LastWriteTime: 1/31/2020 4:30:00 p.m., ChangeTime: 1/31/2020 4:30:00 p.m., FileAttributes: SA
4:30:00.1754060 p.m. CreateFile %USERPROFILE%\AppData\Local\Temp SUCCESS Desired Access: Write Data/Add File, Synchronize, Disposition: Open, Options: , Attributes: n/a, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
4:30:00.1756804 p.m. SetRenameInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 ACCESS DENIED ReplaceIfExists: True, FileName: %USERPROFILE%\AppData\Local\Temp\csp2483.tmp
4:30:00.1759340 p.m. CloseFile %USERPROFILE%\AppData\Local\Temp SUCCESS
4:30:00.1760082 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS
4:30:00.1761512 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID% SUCCESS Desired Access: Read Data/List Directory, Synchronize, Disposition: Open, Options: Directory, Synchronous IO Non-Alert, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
4:30:00.1761977 p.m. QueryDirectory %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_* SUCCESS Filter: b501608ed52de158b562a9467bbebaa6_*, 1: b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375
4:30:00.1763073 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, AllocationSize: n/a, OpenResult: Opened
4:30:00.1764712 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID% SUCCESS
4:30:00.1765216 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS
4:30:00.1766530 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\b501608ed52de158b562a9467bbebaa6_7c965620-2eb3-4093-97cc-3e136a471375 SHARING VIOLATION Desired Access: Generic Write, Read Attributes, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: S, ShareMode: None, AllocationSize: n/a
Вскоре после этого возникает другое исключение при удалении другого экземпляра RSACryptoServiceProvider, который использовался для расшифровки. Используемое имя файла c с указанием объекта изменилось на другой идентификатор, но в противном случае операции и их результаты следуют одному и тому же шаблону, и результат сообщения об одном и том же исключении.
Чуть позже программа переходит зашифровать строку. На этот раз события немного отличаются: последняя капля просто ЗАПРЕЩЕНА ДО ДОСТУПА, а не ОБЩАЯ НАРУШЕНИЕ:
4:49:56.3149713 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Desired Access: Generic Write, Read Attributes, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: S, ShareMode: None, AllocationSize: n/a, OpenResult: Opened
4:49:56.3151740 p.m. QueryStandardInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS AllocationSize: 4,096, EndOfFile: 1,318, NumberOfLinks: 1, DeletePending: False, Directory: False
4:49:56.3151919 p.m. WriteFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Offset: 0, Length: 1,318, Priority: Normal
4:49:56.3152521 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS
4:49:56.3155032 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Desired Access: Read Attributes, Delete, Disposition: Open, Options: Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
4:49:56.3156288 p.m. QueryAttributeTagFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Attributes: SA, ReparseTag: 0x0
4:49:56.3156477 p.m. SetDispositionInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 ACCESS DENIED Delete: True
4:49:56.3542999 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS
4:49:56.3546286 p.m. CreateFile %USERPROFILE%\AppData\Local\Temp SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
4:49:56.3546780 p.m. QueryBasicInformationFile %USERPROFILE%\AppData\Local\Temp SUCCESS CreationTime: 9/19/2018 3:24:30 p.m., LastAccessTime: 1/31/2020 4:48:02 p.m., LastWriteTime: 1/31/2020 4:48:02 p.m., ChangeTime: 1/31/2020 4:48:02 p.m., FileAttributes: D
4:49:56.3546974 p.m. CloseFile %USERPROFILE%\AppData\Local\Temp SUCCESS
4:49:56.3549030 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
4:49:56.3550494 p.m. QueryAttributeTagFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Attributes: SA, ReparseTag: 0x0
4:49:56.3550785 p.m. QueryBasicInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS CreationTime: 1/31/2020 4:49:56 p.m., LastAccessTime: 1/31/2020 4:49:56 p.m., LastWriteTime: 1/31/2020 4:49:56 p.m., ChangeTime: 1/31/2020 4:49:56 p.m., FileAttributes: SA
4:49:56.3551978 p.m. CreateFile %USERPROFILE%\AppData\Local\Temp SUCCESS Desired Access: Write Data/Add File, Synchronize, Disposition: Open, Options: , Attributes: n/a, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
4:49:56.3555954 p.m. SetRenameInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 ACCESS DENIED ReplaceIfExists: True, FileName: %USERPROFILE%\AppData\Local\Temp\cspA6D4.tmp
4:49:56.3559595 p.m. CloseFile %USERPROFILE%\AppData\Local\Temp SUCCESS
4:49:56.3560327 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS
4:49:56.3562301 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID% SUCCESS Desired Access: Read Data/List Directory, Synchronize, Disposition: Open, Options: Directory, Synchronous IO Non-Alert, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
4:49:56.3562921 p.m. QueryDirectory %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_* SUCCESS Filter: e0b0f7743bf0ba1af76a0a9f21e83437_*, 1: e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375
4:49:56.3564453 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Sequential Access, Synchronous IO Non-Alert, Non-Directory File, Attributes: n/a, ShareMode: Read, AllocationSize: n/a, OpenResult: Opened
4:49:56.3567585 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID% SUCCESS
4:49:56.3568211 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS
4:49:56.3569981 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Desired Access: Generic Write, Read Attributes, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: S, ShareMode: None, AllocationSize: n/a, OpenResult: Opened
4:49:56.3572681 p.m. QueryStandardInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS AllocationSize: 4,096, EndOfFile: 1,318, NumberOfLinks: 1, DeletePending: False, Directory: False
4:49:56.3572967 p.m. WriteFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Offset: 0, Length: 1,318, Priority: Normal
4:49:56.3573971 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS
4:49:56.3576710 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Desired Access: Read Attributes, Delete, Disposition: Open, Options: Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
4:49:56.3578194 p.m. QueryAttributeTagFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Attributes: SA, ReparseTag: 0x0
4:49:56.3578848 p.m. SetDispositionInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 ACCESS DENIED Delete: True
4:49:56.3878718 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS
4:49:56.3881894 p.m. CreateFile %USERPROFILE%\AppData\Local\Temp SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
4:49:56.3882383 p.m. QueryBasicInformationFile %USERPROFILE%\AppData\Local\Temp SUCCESS CreationTime: 9/19/2018 3:24:30 p.m., LastAccessTime: 1/31/2020 4:48:02 p.m., LastWriteTime: 1/31/2020 4:48:02 p.m., ChangeTime: 1/31/2020 4:48:02 p.m., FileAttributes: D
4:49:56.3882567 p.m. CloseFile %USERPROFILE%\AppData\Local\Temp SUCCESS
4:49:56.3884424 p.m. CreateFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
4:49:56.3885627 p.m. QueryAttributeTagFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS Attributes: SA, ReparseTag: 0x0
4:49:56.3885898 p.m. QueryBasicInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS CreationTime: 1/31/2020 4:49:56 p.m., LastAccessTime: 1/31/2020 4:49:56 p.m., LastWriteTime: 1/31/2020 4:49:56 p.m., ChangeTime: 1/31/2020 4:49:56 p.m., FileAttributes: SA
4:49:56.3887004 p.m. CreateFile %USERPROFILE%\AppData\Local\Temp SUCCESS Desired Access: Write Data/Add File, Synchronize, Disposition: Open, Options: , Attributes: n/a, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
4:49:56.3889472 p.m. SetRenameInformationFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 ACCESS DENIED ReplaceIfExists: True, FileName: %USERPROFILE%\AppData\Local\Temp\csp2011.tmp
4:49:56.3891731 p.m. CloseFile %USERPROFILE%\AppData\Local\Temp SUCCESS
4:49:56.3892245 p.m. CloseFile %USERPROFILE%\AppData\Roaming\Microsoft\Crypto\RSA\%USERSID%\e0b0f7743bf0ba1af76a0a9f21e83437_7c965620-2eb3-4093-97cc-3e136a471375 SUCCESS
Исключение также отличается:
System.Security.Cryptography.CryptographicException: Access is denied.
at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
at System.Security.Cryptography.SafeProvHandle._FreeCSP(IntPtr pProvCtx)
at System.Security.Cryptography.SafeProvHandle.ReleaseHandle()
at System.Runtime.InteropServices.SafeHandle.InternalDispose()
at System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
at System.Runtime.InteropServices.SafeHandle.Dispose()
at System.Security.Cryptography.RSACryptoServiceProvider.Dispose(Boolean disposing)
at System.Security.Cryptography.AsymmetricAlgorithm.System.IDisposable.Dispose()
at System.Security.Cryptography.AsymmetricAlgorithm.Clear()
at Baker.Security.SafelyDisposeRCSP(RSACryptoServiceProvider rsa, Boolean encVsDec) in %PROJECT_DIR%\Security.cs:line 95
Обратите внимание, однако, что он все еще возникает в результате удаления SafeProvHandle в объекте RSACryptoProviderService.
В обоих случаях выполняются одни и те же 2 операции ( SetDispositionInformationFile , SetRenameInformationFile ) с тот же сбой (ACCESS DENIED), но в первом случае (после выполнения Decrypt) эта пара операций выполняется только один раз и не приводит к возникновению исключения, тогда как в последнем случае (после выполнения Encrypt) пара операций выполняется дважды, а затем выдается исключение. В первом случае исключение не генерируется до тех пор, пока не произойдет последующий сбой (НАРУШЕНИЕ ОБМЕНА), возникающий при попытке создать файл (если он уже существует) для записи без совместного использования. Разумеется, возможно, что если после дешифрования распоряжение не получило такого совместного нарушения, оно также могло бы в конечном итоге вызвать исключение для отказа [ACCESS DENIED] - но зачем спекулировать? Как я упоминал ранее, мой упрощенный демонстрационный пример кода может (время от времени) только получать ошибку ACCESS DENIED, но я не уверен, почему она должна отличаться.
Вывод:
Позвольте мне предположить, что это какой-то дефект в коде Crypto в реализации Windows 10. NET 3.5. Или есть какое-то состояние окружающей среды, которое мешает его правильной работе? Если это так, что это может быть? И в этом случае дефект может быть в документации, которая не дает ни малейшего представления о том, что подобные вещи должны происходить. Но Microsoft уже давно отказалась. NET 3.5.
Пример кода:
Этот код для проекта консоли уже перехватывает недопустимые исключения, которые вполне могут быть лучшее, что кто-то может сделать, здесь. По крайней мере, это позволяет вам видеть их. Не забудьте нацелиться. NET Framework 3.5, чтобы увидеть проблему.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Security.Cryptography;
namespace Scratch
{
class ProgramBad
{
static void Main(string[] args) {
try { Environment.ExitCode = SecurityBad.QuickEncDecTest(args.Length>0 ? args[1] : null); }
catch (Exception exc) {
Console.WriteLine("WARNING: unhandled " + exc.ToString());
Environment.ExitCode = 1;
} finally {
Console.WriteLine("Press return to end program...");
Console.ReadLine();
}
}
}
public static class SecurityBad {
public static int QuickEncDecTest(string original = null) {
var key = CreateRandomRSAKey();
original = original ?? "My super-secret password";
var encrypted = EnCrypt(original, key);
var decrypted = DeCrypt(encrypted, key);
int retval = decrypted.CompareTo(original);
if (retval == 0) Console.WriteLine("Encrypt/Decrypt round trip resulted in original. PASSED!");
else Console.WriteLine("Encrypt/Decrypt failed to result in original. FAILED!"
+ Environment.NewLine
+ "Original '" + original + "' != round-trip '" + decrypted + "'");
return retval;
}
public static byte[] CreateRandomRSAKey() {
RSACryptoServiceProvider rsa = null;
try { rsa = new RSACryptoServiceProvider();
return rsa.ExportCspBlob(true);
} finally {
try { rsa.Clear(); }
catch (Exception ce) {
Console.WriteLine(ce.ToString());
}
}
}
public static byte[] EnCrypt(string str, byte[] key) {
RSACryptoServiceProvider rsa = null; // This code originally had a using(var rsa = new ...) block, but see comments in SafelyDisposeRCSP.
try {
rsa = new RSACryptoServiceProvider();
rsa.ImportCspBlob(key);
var bytConvertor = new UTF8Encoding();
var plainData = bytConvertor.GetBytes(str);
return rsa.Encrypt(plainData, false);
}
finally { if (rsa != null)
try { rsa.Clear(); }
catch (Exception ce) { Console.WriteLine(ce.ToString()); }
}
}
public static string DeCrypt(byte[] alldata, byte[] key) {
RSACryptoServiceProvider rsa = null;
try {
var bytConvertor = new UTF8Encoding();
rsa = new RSACryptoServiceProvider();
rsa.ImportCspBlob(key);
return bytConvertor.GetString(rsa.Decrypt(alldata, false));
} catch (Exception e) {
Console.WriteLine("Warning: Decrypting a string failed due to the following " + e.GetType().Name);
Console.WriteLine(e);
return String.Empty;
}
finally { if (rsa != null)
try { rsa.Clear(); }
catch (Exception ce) { Console.WriteLine(ce.ToString()); }
}
}
}
}