C# Win10.NET 3.5 RSACryptoServiceProvider.Dispose引发加密异常(访问被拒绝或共享冲突)

C# Win10.NET 3.5 RSACryptoServiceProvider.Dispose引发加密异常(访问被拒绝或共享冲突),c#,windows,cryptography,.net-3.5,C#,Windows,Cryptography,.net 3.5,摘要: rsaccryptoserviceprovider对象的Dispose()方法正在无明显原因地抛出加密异常。这似乎是由于它在非托管级别用于底层提供程序工具的SafeProvHandle类中的某些编程错误造成的,该类尝试使用临时文件。我想我的问题主要是“为什么会发生这种情况?”,但当然要记住最终目标:“程序员应该如何最好地避免这种情况?” 上下文: 针对x86 CPU类型的.NET Framework 3.5的旧控制台应用程序,但在Windows 10 x64 Pro(特别是10.0.17

摘要:

rsaccryptoserviceprovider对象的Dispose()方法正在无明显原因地抛出加密异常。这似乎是由于它在非托管级别用于底层提供程序工具的SafeProvHandle类中的某些编程错误造成的,该类尝试使用临时文件。我想我的问题主要是“为什么会发生这种情况?”,但当然要记住最终目标:“程序员应该如何最好地避免这种情况?”

上下文:

针对x86 CPU类型的.NET Framework 3.5的旧控制台应用程序,但在Windows 10 x64 Pro(特别是10.0.17134 Build 17134)上运行。应用程序在应用程序配置或清单中没有任何明确的设置表明它支持windows 10。大多数东西都像在WindowsXP上一样工作正常(!),但这是我遇到的几个奇怪的差异之一。事实上,我很确定这在不久前的Windows 10上运行得很好(没有例外),我也不确定为什么会发生变化(我知道这个程序曾经工作过,它必须解密它的一个设置,即使它现在尝试解密,但得到了这个例外)。当相同的代码针对较新的框架(>=.NET Framework 4)时,不会引发此异常,但当应用程序卡在3.5上时,此异常没有多大价值(因为我的代码在这里并不重要)。这与任何其他框架无关——即使在一个简单的控制台应用程序中也会发生这种情况

例外情况:

释放任何RSACryptoServiceProvider对象时引发异常。要隔离它,可以从“using”块切换到“try/finally”结构,然后在finally块中使用Clear()方法(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\u DIR%替换了到源代码的路径)

这是在任何成功解密字符串的尝试之后出现的。 但是,在任何加密字符串的成功尝试之后,随后调用Clear会导致加密异常,该异常具有相同的堆栈跟踪,但有一条不同的消息:访问被拒绝

因此,异常消息将是两种形式之一:
  • 该进程无法访问该文件,因为另一进程正在使用该文件。
  • 访问被拒绝
  • 我还将演示代码隔离到一个非常小的项目中。它显示了相同的行为,只是至少有时加密和解密都会导致“访问被拒绝”。因此,确切地说,你得到哪一个可能会有所不同。但我从原始应用程序中收集了以下详细信息

    不恰当:

    无论哪种方式,即使是我的客户机代码在有问题的方法调用附近也没有显式地尝试对文件执行任何操作,因此异常消息完全没有帮助。事实上,这是误导性的,因为最初代码只是在更高的级别捕获异常,而我的客户机代码实际上是在尝试写入或读取XML设置文件,数据库连接的用户名和密码都是加密的——但这更多的是由于该客户机代码没有处理异常,而在该异常与XML设置文件不相关的地方,这一点是显而易见的。谁会想到,处置一个不公布任何文件系统使用情况的对象会引发这种类型的异常呢?但我们可以假设,这些异常与RSACryptServiceProvider的工作方式有关

    低级别原因详细信息:

    由于异常没有提供关于它可能关注的文件的线索,所以我唯一能找到的方法是同时使用“procmon”(from)跟踪系统调用。正如您将在下面看到的,RSACryptServiceProvider对象似乎正在创建一个临时文件,可能是为了保存一些状态信息,然后它似乎试图将该文件重命名(移动?)为不同的临时文件路径(两者都在用户配置文件下的AppData中)。该操作或重新打开(创建)失败。所有这些都没有在文档中描述,因此很难猜测此活动的实际目的是什么。在任何情况下,如上面的堆栈跟踪所示,它都会从SafeProvHandle的Dispose()抛出异常(我假设它只是扩展SafeHandle的特定于类型的派生类),它是RSACryptServiceProvider对象的两个包装句柄成员之一

    这里的另一个奇怪之处是,每当我在抛出异常的调试器中停止代码时,原始文件有1318个字节,所有字节都设置为0,因此该文件实际上根本不包含任何有用的信息。它的目的是什么?我不知道。此外,我尝试手动执行重命名操作,结果成功了,没有发生任何异常情况。那么为什么rsacyptoserviceprovider不能这样做呢?我不知道,但也许在Windows资源管理器中执行此操作会涉及不同的系统调用

    从procmon中,以下是一些相关的加密事件,这些事件是进程在引发异常之前执行的。我已将主目录的路径前缀替换为%USERPROFILE%,我假设用户SID为%USERSID%,以减小这些行的大小,这些行是以制表符分隔的格式粘贴在这里的,但我认为stackoverflow不会保留制表符:

    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
    
    不久之后,在处理另一个异常时抛出另一个异常
    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
    
    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()); }
                }
            }
        }
    }
    
            private static void SafelyDisposeRCSP(RSACryptoServiceProvider rsa, string attemptedOperation)
            {
                // This began happening in Windows 10, inexplicably, with a non-sensical error,
                // "The process cannot access the file because it is being used by another process." or, "Access is denied";
                // procmon determined that the system call generating this exception was all
                // about a file that the rsa object apparently uses under %USERPROFILE%\AppData\... when it tries to rename/move it from
                // Roaming/Microsoft/Crypto/RSA/%USERGUID%/%OBJECTGUID% to Local/Temp/csp%XXXX%.tmp, as if it failed to rename it because
                // it didn't have permission to do so (makes no sense).
                // But why should anyone care?  We're done with the rsa object by now!  
                // Here we just assume this is a serious defect somewhere in the framework.
    
                // So here we just swallow the exception with a log message, 
                // and that's the only reason for not doing a using block;
                // we could not separate such bogus disposal exceptions from valid exceptions with a "using" block.
    
                if (rsa != null)
                    try { rsa.Clear(); }
                    catch (Exception ce) {
                        var msg = "After successfully " + attemptedOperation + ", the RSACryptoServiceProvider.Dispose() method threw a "
                                    + ce.GetType().Name;
                        if (ce.Message.StartsWith("Access is denied") ||
                            ce.Message.StartsWith("The process cannot access the file because it is being used by another process."))
                            // note: the ce.Message usually ends with an Environment.NewLine, so we don't need to insert one:
                            Console.WriteLine(msg + ":  " + ce.Message + "Working around this defect in the .NET framework by ignoring the bogus exception.");
                        else {   // Haven't really seen this, not sure why it could happen, but maybe it is because of using a different language?
                            Console.WriteLine("Warning: " + msg);
                            Console.WriteLine(ce.ToString()); // we will log the full stack trace just in case it is important to investigate
                        }
                    }
            }
    
            public static byte[] CreateRSAKey() {
                RSACryptoServiceProvider rcsp = null;
                try {
                    rcsp = new RSACryptoServiceProvider();
                    return rcsp.ExportCspBlob(true);
                } finally {
                    SafelyDisposeRCSP(rcsp, "exporting key");
                }
            }
    
            // ...
    
            public static ... Encrypt(...) {
            // ...
                } finally {
                    SafelyDisposeRCSP(rcsp, "encrypting string");
                }
            // ...
    
            // ... etc. ...