C# SetUserFileEncryptionKey的奇怪返回码

C# SetUserFileEncryptionKey的奇怪返回码,c#,winapi,interop,x509certificate,efs,C#,Winapi,Interop,X509certificate,Efs,我想读取EFS证书(比如从pfx文件中读取),并临时使用它来读/写一些文件。(我希望它在程序退出后不会保留在任何存储中。)它似乎可以提供此功能,但我在尝试时得到一个奇怪的返回代码(0x80092004)。这是我的密码: var x509Cert = new X509Certificate2(@"C:\Users\Public\Downloads\key.pfx", "<mypass>"); var certContext = Marshal.P

我想读取EFS证书(比如从pfx文件中读取),并临时使用它来读/写一些文件。(我希望它在程序退出后不会保留在任何存储中。)它似乎可以提供此功能,但我在尝试时得到一个奇怪的返回代码(
0x80092004
)。这是我的密码:

var x509Cert = new X509Certificate2(@"C:\Users\Public\Downloads\key.pfx", "<mypass>");
var certContext = Marshal.PtrToStructure<CertContext>(x509Cert.Handle);

var blob = new EfsCertificateBlob
{
    dwCertEncodingType = certContext.dwCertEncodingType,
    cbData = certContext.cbCertEncoded,
    pbData = certContext.pbCertEncoded,
};

var pCertBlob = Marshal.AllocHGlobal(Marshal.SizeOf(blob));
Marshal.StructureToPtr(blob, pCertBlob, false);

var id = WindowsIdentity.GetCurrent();
var curStringSid = id.User?.Value;
Console.WriteLine(curStringSid);

ConvertStringSidToSid(curStringSid, out var sidPtr);

var certStruct = new EncryptionCertificate
{
    cbTotalLength = (uint) Marshal.SizeOf(typeof(EncryptionCertificate)),
    pUserSid = sidPtr,
    pCertBlob = pCertBlob,
};

var res = SetUserFileEncryptionKey(certStruct);

Console.WriteLine($"Result: 0x{res:X}"); // Result: 0x80092004

SetUserFileEncryptionKey
是否实现了我希望的功能?我做错了什么


(我的用例用于处理敏感数据,我不希望用户以后能够读取或重新分发这些数据。因此,我希望在进程终止后立即无法访问这些文件。)似乎
0x80092004
CRYPT\u E\u未找到
,并且
SetUserFileEncryptionKey
仅适用于已经是用户证书存储的一部分的证书。导入相关证书时,上述代码返回
错误\u成功
。这个函数似乎不像我希望的那样为用例服务。

SetUserFileEncryptionKey
接受指向结构的指针。尝试将此函数的签名更改为
IntPtr
参数,并将指针传递到结构。感谢您的建议。我认为传递一个类实例与引用一个struct()是一样的,但我还是要尝试一下。有些API很难实现,并且在互操作中并不总是以相同的方式工作。考试只是一个小小的变化。如果不是,那么实际的证书可能会有问题。与structs和
IntPtr类似,我得到了相同的结果。当我双击certfile时,它似乎被添加得很好。您还能想到什么?最后一个问题:传递给
pUserSid
的是什么?文档似乎需要一些更新,以包括如何以及何时使用
SetUserFileEncryptionKey()
。通常,使用当前用户密钥对文件进行加密和解密。那么你能再描述一下你的用例吗?我同意;关于这个函数的用途,没有太多的信息。我添加了一些关于我的用例的信息。
[StructLayout(LayoutKind.Sequential)]
public class CertContext
{
    public uint dwCertEncodingType;
    public IntPtr pbCertEncoded;
    public uint cbCertEncoded;
    public IntPtr pCertInfo;
    public IntPtr hCertStore;
}

[StructLayout(LayoutKind.Sequential)]
public class EfsCertificateBlob
{
    public uint dwCertEncodingType;
    public uint cbData;
    public IntPtr pbData;
}

[StructLayout(LayoutKind.Sequential)]
public class EncryptionCertificate
{
    public uint cbTotalLength;
    public IntPtr pUserSid;
    public IntPtr pCertBlob;
}

[DllImport("Advapi32.dll")]
public static extern uint SetUserFileEncryptionKey(EncryptionCertificate pEncryptionCertificate);