在您的CPSetProvParam
实现中,PP_KEYSET_SEC_DESCR
您获得了 a 的地址SECURITY_DESCRIPTOR
,您需要以某种方式将其应用于您的私钥存储。如果您的存储基于文件或注册表项(原则上是任何内核对象类型,但这里还可以使用什么?)您需要SetKernelObjectSecurity
使用文件或密钥HANDLE
(必须具有WRITE_DAC
访问权限)调用(可能是多次如果您说有多个文件用于存储单个密钥)。在内核中对对象的 GENERIC 访问将自动转换为对象特定权限。
如果您的存储实现不是直接基于某些内核对象,而是自定义 - 此时您需要自己将 GENERIC 访问(0xF0000000
掩码)转换为特定访问权限(0x0000FFFF
掩码)
__________________ 编辑 ____________________
经过更多检查后,我发现提供者不仅必须将通用转换为特定访问,CPSetProvParam
而且还必须将特定转换为通用,CPGetProvParam
尽管这不是直接指向文档。
这就是MS_ENHANCED_PROV
(在 中实现rsaenh.dll
)大致执行此操作的方式:
void CheckAndChangeAccessMask(PSECURITY_DESCRIPTOR SecurityDescriptor)
{
BOOL bDaclPresent, bDaclDefaulted;
PACL Dacl;
ACL_SIZE_INFORMATION asi;
if (
GetSecurityDescriptorDacl(SecurityDescriptor, &bDaclPresent, &Dacl, &bDaclDefaulted)
&&
bDaclPresent
&&
Dacl
&&
GetAclInformation(Dacl, &asi, sizeof(asi), AclSizeInformation)
&&
asi.AceCount
)
{
union{
PVOID pAce;
PACE_HEADER pah;
PACCESS_ALLOWED_ACE paa;
};
do
{
if (GetAce(Dacl, --asi.AceCount, &pAce))
{
switch (pah->AceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
case ACCESS_DENIED_ACE_TYPE:
ACCESS_MASK Mask = paa->Mask, Gen_Mask = 0;
if (Mask & FILE_READ_DATA)
{
Gen_Mask |= GENERIC_READ;
}
if (Mask & FILE_WRITE_DATA)
{
Gen_Mask |= GENERIC_ALL;
}
paa->Mask = Gen_Mask;
break;
}
}
} while (asi.AceCount);
}
}
因此FILE_READ_DATA
转换为GENERIC_READ
和转换FILE_WRITE_DATA
为GENERIC_ALL
(这正是算法)-但是您可以查看自己的代码rsaenh.CheckAndChangeAccessMask
(名称来自 pdb 符号)
rsaenh
GetNamedSecurityInfoW
首先通过( )从文件中获取 SD SE_FILE_OBJECT
,然后将其转换为特定于通用访问。这里是调用图和修改后的 DACL(在右上角,修改后的 ACCESS_MASK 为红色)
![在此处输入图像描述](https://i.stack.imgur.com/riAD2.png)