如何查看 RSA 密钥容器的权限
我以非管理员身份创建了一个 RSA 机器存储容器,并将完全控制权分配给我自己,以及对其他帐户的读取访问权限。
我希望能够以编程方式查看密钥容器的 ACL。当我尝试使用下面的代码执行此操作时,即使我是密钥容器的所有者并具有完全控制权,我也会收到以下异常:
System.Security.AccessControl.PrivilegeNotHeldException: The process does not possess the 'SeSecurityPrivilege' privilege which is required for this operation.
at System.Security.AccessControl.Privilege.ToggleState(Boolean enable)
at System.Security.Cryptography.Utils.GetKeySetSecurityInfo(SafeProvHandle hProv, AccessControlSections accessControlSections)
at System.Security.Cryptography.CspKeyContainerInfo.get_CryptoKeySecurity()
...
我可以使用 Windows 资源管理器或 CACLS 查看 中的密钥文件来查看权限C:\Documents and Settings\All Users\...\Crypto\RSA\MachineKeys
,因此看来我的帐户具有所需的权限。
我正在使用的代码如下:
CspParameters cp = new CspParameters();
cp.Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore;
cp.KeyContainerName = containerName;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp))
{
// PrivilegeNotHeldException thrown at next line while
// dereferencing CspKeyContainerInfo.CryptoKeySecurity
if (rsa.CspKeyContainerInfo.CryptoKeySecurity != null)
{
foreach (CryptoKeyAccessRule rule in rsa.CspKeyContainerInfo.CryptoKeySecurity.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
{
... process rule
}
}
}
有 这里有类似问题的问题,但我看不到任何方法将答案应用于我的情况。
根据 MSDN ,CspKeyContainerInfo.CryptoKeySecurity
属性:
获取一个 CryptoKeySecurity 对象,该对象表示容器的访问权限和审核规则。
我想要一个代表访问权限但不代表审核规则的对象(因为我没有审核规则的权限)。
更新
我找到了一个解决方法,即找到包含密钥容器的文件并检查其 ACL。我对此并不完全满意,因为它取决于加密类的未记录的实现细节(例如,可能不适用于 Mono),并且仍然对更好的解决方案感兴趣。
... Initialize cp as above
CspKeyContainerInfo info = new CspKeyContainerInfo(cp);
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"Microsoft\\Crypto\\RSA\\MachineKeys\\" + info.UniqueKeyContainerName);
FileSecurity fs = new FileInfo(path).GetAccessControl(AccessControlSections.Access);
foreach (FileSystemAccessRule rule in fs.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
{
... process rules
}
I've created an RSA Machine-Store container as a non-administrator, and assigned Full Control to myself, as well as read access to other accounts.
I want to be able to programatically view the ACL for the key container. When I attempt to do so with the code below, I get the following exception even though I am owner of the key container and have Full Control:
System.Security.AccessControl.PrivilegeNotHeldException: The process does not possess the 'SeSecurityPrivilege' privilege which is required for this operation.
at System.Security.AccessControl.Privilege.ToggleState(Boolean enable)
at System.Security.Cryptography.Utils.GetKeySetSecurityInfo(SafeProvHandle hProv, AccessControlSections accessControlSections)
at System.Security.Cryptography.CspKeyContainerInfo.get_CryptoKeySecurity()
...
I can view the privileges by using Windows Explorer or CACLS to view the key file in C:\Documents and Settings\All Users\...\Crypto\RSA\MachineKeys
, so it appears that my account has the required privilege.
The code I'm using is as follows:
CspParameters cp = new CspParameters();
cp.Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore;
cp.KeyContainerName = containerName;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp))
{
// PrivilegeNotHeldException thrown at next line while
// dereferencing CspKeyContainerInfo.CryptoKeySecurity
if (rsa.CspKeyContainerInfo.CryptoKeySecurity != null)
{
foreach (CryptoKeyAccessRule rule in rsa.CspKeyContainerInfo.CryptoKeySecurity.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
{
... process rule
}
}
}
There's a question with a similar problem here, but I can't see any way to apply the answer to my situation.
According to MSDN, the CspKeyContainerInfo.CryptoKeySecurity
property:
Gets a CryptoKeySecurity object that represents access rights and audit rules for a container.
I want an object that represents access rights but not audit rules (as I don't have the privilege for audit rules).
UPDATE
I've found a workaround, which is to locate the file containing the key container and inspect its ACL. I'm not entirely happy with this as it depends on undocumented implementation details of the cryptography classes (e.g. presumably wouldn't work on Mono), and would still be interested in a better solution.
... Initialize cp as above
CspKeyContainerInfo info = new CspKeyContainerInfo(cp);
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"Microsoft\\Crypto\\RSA\\MachineKeys\\" + info.UniqueKeyContainerName);
FileSecurity fs = new FileInfo(path).GetAccessControl(AccessControlSections.Access);
foreach (FileSystemAccessRule rule in fs.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
{
... process rules
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
正如您在 .NET Framework 中看到的参考源,
CspKeyContainerInfo.CryptoKeySecurity
被硬编码以请求AccessControlSections.All
。除了使用 CSP 的内部实现细节来定位文件(这是可以理解的不可取的)之外,您还有两个选择。
选项 1:从头开始重新实现
这与列出关键容器时必须采取的策略相同,例子。
这是理想的解决方案,因为它不依赖于加密服务提供程序或 .NET Framework 和运行时的内部实现细节。此选项与选项 2 之间的唯一区别是,它不会尝试断言 SeSecurityPrivilege(您将得到 InvalidOperationException,就好像该对象没有安全描述符一样),并且它将针对所有其他错误抛出 Win32Exception。我保持简单。
用法:
实现:
选项 2:反射
您可以模拟
CspKeyContainerInfo.CryptoKeySecurity
的功能,但指定您想要的AccessControlSections
的任何值。这依赖于 .NET Framework 和 CLR 内部的实现细节,并且很可能不适用于其他 BCL 实现和 CLR,例如 .NET Core。 .NET Framework 和桌面 CLR 的未来更新也可能导致此选项失效。也就是说,它确实有效。用法:
实施:
As you can see in the .NET Framework reference source,
CspKeyContainerInfo.CryptoKeySecurity
is hardcoded to ask forAccessControlSections.All
.Besides using internal implementation details of CSP to locate the file, which is understandably undesirable, you have two options.
Option 1: Reimplement from scratch
This is the same tack you must take to list key containers, for example.
This is the ideal solution because it does not rely on internal implementation details of either the cryptographic service provider or the .NET Framework and runtime. The only difference between this and option 2 is that it will not attempt to assert the SeSecurityPrivilege (you'll get an InvalidOperationException as though the object has no security descriptor), and it will throw Win32Exception for all other errors. I kept it simple.
Usage:
Implementation:
Option 2: Reflection
You could simulate what the
CspKeyContainerInfo.CryptoKeySecurity
does, but specify whatever value ofAccessControlSections
you want. This relies on implementation details internal to the .NET Framework and CLR and will very likely not work on other BCL implementations and CLRs, such as .NET Core's. Future updates to the .NET Framework and desktop CLR could also render this option broken. That said, it does work.Usage:
Implementation: