使用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
相关产品推荐
相关产品推荐

