You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CryptUI库在C#中签名内存字节数组时遇到0x80070057参数错误求助

CryptUI库在C#中签名内存字节数组时遇到0x80070057参数错误求助

各位大佬好,我之前已经成功用CryptUI库的API,通过X509证书(.pfx文件)完成了磁盘文件的数字签名,代码如下:

const Int32 CRYPTUI_WIZ_NO_UI = 1;
const Int32 CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE = 1;
const Int32 CRYPTUI_WIZ_DIGITAL_SIGN_CERT = 1;

struct CRYPTUI_WIZ_DIGITAL_SIGN_INFO
{
    public Int32 dwSize;
    public Int32 dwSubjectChoice;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string pwszFileName;
    public Int32 dwSigningCertChoice;
    public IntPtr pSigningCertContext;
    public string pwszTimestampURL;
    public Int32 dwAdditionalCertChoice;
    public IntPtr pSignExtInfo;
}

[DllImport("Cryptui.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool CryptUIWizDigitalSign(Int32 dwFlags, IntPtr hwndParent, string pwszWizardTitle, ref CRYPTUI_WIZ_DIGITAL_SIGN_INFO pDigitalSignInfo, ref IntPtr ppSignContext);

public bool SignExecutable(string certificatePath, string applicationPath, string certificatePassword)
{
    var cert = new X509Certificate2(certificatePath, certificatePassword);
    var pSigningCertContext = cert.Handle;

    var digitalSignInfo = default(CRYPTUI_WIZ_DIGITAL_SIGN_INFO);
    digitalSignInfo = new CRYPTUI_WIZ_DIGITAL_SIGN_INFO()
    {
        dwSize = Marshal.SizeOf(digitalSignInfo),
        dwSubjectChoice = CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE,
        pwszFileName = applicationPath,
        dwSigningCertChoice = CRYPTUI_WIZ_DIGITAL_SIGN_CERT,
        pSigningCertContext = pSigningCertContext,
        pwszTimestampURL = null,
        dwAdditionalCertChoice = 0,
        pSignExtInfo = IntPtr.Zero
    };

    var pSignContext = default(IntPtr);
    return CryptUIWizDigitalSign(CRYPTUI_WIZ_NO_UI, IntPtr.Zero, null, ref digitalSignInfo, ref pSignContext);
}

但现在我的需求是签名内存中动态生成的文件内容,不用先写入磁盘。根据CryptUI的文档,它应该支持这种场景,所以我修改了代码,改成处理内存Blob的版本:

const Int32 CRYPTUI_WIZ_NO_UI = 1;
const Int32 CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_BLOB = 2;
const Int32 CRYPTUI_WIZ_DIGITAL_SIGN_CERT = 1;

public struct CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO
{
    public Int32 dwSize;
    public IntPtr pGuidSubject;
    public Int32 cbBlob;
    public IntPtr pbBlob;
    public string pwszDisplayName;
}

struct CRYPTUI_WIZ_DIGITAL_SIGN_INFO
{
    public Int32 dwSize;
    public Int32 dwSubjectChoice;
    public IntPtr pSignBlobInfo;
    public Int32 dwSigningCertChoice;
    public IntPtr pSigningCertContext;
    public string pwszTimestampURL;
    public Int32 dwAdditionalCertChoice;
    public IntPtr pSignExtInfo;
}

struct CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT
{
    public Int32 dwSize;
    public Int32 cbBlob;
    public IntPtr pbBlob;
};

[DllImport("Cryptui.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool CryptUIWizDigitalSign(Int32 dwFlags, IntPtr hwndParent, string pwszWizardTitle, ref CRYPTUI_WIZ_DIGITAL_SIGN_INFO pDigitalSignInfo, ref CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT ppSignContext);

public byte[] SignExecutableBLOB(string certificatePath, byte[] applicationContent, string certificatePassword)
{
    var cert = new X509Certificate2(certificatePath, certificatePassword);
    var pSigningCertContext = cert.Handle;

    int size = Marshal.SizeOf(applicationContent[0]) * applicationContent.Length;
    var blobInfo = default(CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO);
    blobInfo = new CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO()
    {
        dwSize = Marshal.SizeOf(blobInfo),
        pGuidSubject = IntPtr.Zero,
        cbBlob = size,
        pbBlob = Marshal.AllocHGlobal(size),
        pwszDisplayName = null
    };

    Marshal.Copy(applicationContent, 0, blobInfo.pbBlob, size);

    IntPtr pBlobInfo = Marshal.AllocHGlobal(Marshal.SizeOf(blobInfo));
    Marshal.StructureToPtr(blobInfo, pBlobInfo, false);

    var digitalSignInfo = default(CRYPTUI_WIZ_DIGITAL_SIGN_INFO);
    digitalSignInfo = new CRYPTUI_WIZ_DIGITAL_SIGN_INFO()
    {
        dwSize = Marshal.SizeOf(digitalSignInfo),
        dwSubjectChoice = CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_BLOB,
        pSignBlobInfo = pBlobInfo,
        dwSigningCertChoice = CRYPTUI_WIZ_DIGITAL_SIGN_CERT,
        pSigningCertContext = pSigningCertContext,
        pwszTimestampURL = null,
        dwAdditionalCertChoice = 0,
        pSignExtInfo = IntPtr.Zero
    };

    try
    {
        var pSignContext = default(CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT);
        if (!CryptUIWizDigitalSign(CRYPTUI_WIZ_NO_UI, IntPtr.Zero, null, ref digitalSignInfo, ref pSignContext))
            throw new Win32Exception($"An error occurred attempting to digitally sign the content");

        var signedApplicationContent = new byte[pSignContext.cbBlob];
        Marshal.Copy(pSignContext.pbBlob, signedApplicationContent, 0, pSignContext.cbBlob);
        return signedApplicationContent;
    }
    finally
    {
        Marshal.FreeHGlobal(pBlobInfo);
        Marshal.FreeHGlobal(blobInfo.pbBlob);
    }
}

现在每次运行这段代码都会抛出错误0x80070057(参数不正确),我试了很多小调整都没解决问题,感觉应该是托管和非托管代码之间的封送处理有问题,但实在找不到具体哪里错了。有没有大佬能帮忙指点一下?

备注:内容来源于stack exchange,提问作者acordner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 14:24:36