C# CryptoAPI';使用PInvoke的s SignerItemsTampEx2
我试图使用C代码中的CryptoAPI向签名程序集添加SHA256时间戳。以下是我正在使用的代码:C# CryptoAPI';使用PInvoke的s SignerItemsTampEx2,c#,timestamp,pinvoke,sha256,cryptoapi,C#,Timestamp,Pinvoke,Sha256,Cryptoapi,我试图使用C代码中的CryptoAPI向签名程序集添加SHA256时间戳。以下是我正在使用的代码: Signer.TimestampSignedAssembly("MyAssembly.exe", "http://tsa.starfieldtech.com"); 签名者类别: public static class Signer { [StructLayoutAttribute(LayoutKind.Sequential)] struct SIGNER_SUBJECT_INFO
Signer.TimestampSignedAssembly("MyAssembly.exe", "http://tsa.starfieldtech.com");
签名者类别:
public static class Signer
{
[StructLayoutAttribute(LayoutKind.Sequential)]
struct SIGNER_SUBJECT_INFO
{
public uint cbSize;
public IntPtr pdwIndex;
public uint dwSubjectChoice;
public SubjectChoiceUnion Union1;
[StructLayoutAttribute(LayoutKind.Explicit)]
internal struct SubjectChoiceUnion
{
[FieldOffsetAttribute(0)]
public IntPtr pSignerFileInfo;
[FieldOffsetAttribute(0)]
public IntPtr pSignerBlobInfo;
}
}
[StructLayoutAttribute(LayoutKind.Sequential)]
struct SIGNER_FILE_INFO
{
public uint cbSize;
public IntPtr pwszFileName;
public IntPtr hFile;
}
[DllImport("Mssign32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int SignerTimeStampEx2(
uint dwFlags, // DWORD
IntPtr pSubjectInfo, // SIGNER_SUBJECT_INFO
string pwszHttpTimeStamp, // LPCWSTR
uint dwAlgId, // ALG_ID
IntPtr psRequest, // PCRYPT_ATTRIBUTES
IntPtr pSipData, // LPVOID
out IntPtr ppSignerContext // SIGNER_CONTEXT
);
public static void TimestampSignedAssembly(string appPath, string tsaServer)
{
if (tsaServer == null) throw new ArgumentNullException("tsaServer");
var pSubjectInfo = IntPtr.Zero;
try
{
pSubjectInfo = CreateSignerSubjectInfo(appPath);
TimestampSignedAssembly(pSubjectInfo, tsaServer);
}
finally
{
if (pSubjectInfo != IntPtr.Zero)
{
Marshal.DestroyStructure(pSubjectInfo, typeof(SIGNER_SUBJECT_INFO));
}
}
}
private static IntPtr CreateSignerSubjectInfo(string pathToAssembly)
{
var info = new SIGNER_SUBJECT_INFO
{
cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_SUBJECT_INFO)),
pdwIndex = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint)))
};
var index = 0;
Marshal.StructureToPtr(index, info.pdwIndex, false);
info.dwSubjectChoice = 0x1; //SIGNER_SUBJECT_FILE
var assemblyFilePtr = Marshal.StringToHGlobalUni(pathToAssembly);
var fileInfo = new SIGNER_FILE_INFO
{
cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_FILE_INFO)),
pwszFileName = assemblyFilePtr,
hFile = IntPtr.Zero
};
info.Union1 = new SIGNER_SUBJECT_INFO.SubjectChoiceUnion
{
pSignerFileInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SIGNER_FILE_INFO)))
};
Marshal.StructureToPtr(fileInfo, info.Union1.pSignerFileInfo, false);
IntPtr pSubjectInfo = Marshal.AllocHGlobal(Marshal.SizeOf(info));
Marshal.StructureToPtr(info, pSubjectInfo, false);
return pSubjectInfo;
}
/*
Here CryptoAPI function SignerTimeStampEx2 called.
*/
private static void TimestampSignedAssembly(IntPtr pSubjectInfo, string tsaServer)
{
IntPtr context;
var hResult = SignerTimeStampEx2(
0x1, // I have not found anywhere what value should have this parameter!
pSubjectInfo,
tsaServer,
0x0000800c, // 256 bit SHA hashing algorithm. This value taken form here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx
IntPtr.Zero,
IntPtr.Zero,
out context
);
if (hResult != 0)
{
throw new Exception(string.Format("Error occured when adding timestamp - Error code: 0x{0:X}", hResult));
}
}
}
尽管我向SignerTimeStampEx2函数传递了一个参数(dwAlgId),表明有必要添加SHA256时间戳(0x0000800c),但始终会生成SHA1时间戳
有人遇到过这个问题吗?我做错了什么?我应该为dwFlags和dwAlgId参数设置哪些值
提前谢谢 dwFlags需要是签名者\u时间戳\u RFC3161(2)。获取访问冲突的原因是SignerTimeStampEx2()错误。它期望算法是一个PCSTR而不是一个DWORD。如果您传递0x800C,它将尝试将其作为指针取消引用,从而导致AV。因此,将函数声明中的ALG_ID dwAlgId替换为PCSTR pszTimeStampAlgorithmOid。将szOID_NIST_sha256传递给it,应定义为“2.16.840.1.101.3.4.2.1” SignerTimeStampEx3()也不正确。pszTimeStampAlgorithmOid应声明为PCSTR,而不是PCWSTR 根据我的经验,如果在SIGNER\u file\u INFO结构中同时指定文件名和打开的Win32文件句柄,则代码签名和时间戳更加可靠
您是否真正获得SHA-256时间戳还取决于您使用的时间戳服务,并发布SHA-256时间戳。即使在请求SHA-256时间戳时,其他服务也可能发行SHA-1时间戳 我终于成功了。以下是时间戳类的完整代码:
公共静态类时间戳
{
[StructLayout(LayoutKind.Sequential)]
结构签名者\u主题\u信息
{
公共单位cbSize;
公共IntPtr pdwIndex;
公共信息主体选择;
公共主体选择工会1;
[StructLayoutAttribute(LayoutKind.Explicit)]
内部结构SubjectChoiceUnion
{
[FieldOffsetAttribute(0)]
公共IntPtr pSignerFileInfo;
[FieldOffsetAttribute(0)]
公共IntPtr pSignerBlobInfo;
}
}
[StructLayoutAttribute(LayoutKind.Sequential)]
结构签名者\u文件\u信息
{
公共单位cbSize;
公共IntPtr pwszFileName;
公共文件;
}
[DllImport(“Mssign32.dll”,CharSet=CharSet.Unicode,SetLastError=true)]
私有静态外部int SignerItemsTampEx2(
uint dwFlags,//DWORD
IntPtr pSubjectInfo,//签名者\主题\信息
字符串pwszHttpTimeStamp,//LPCWSTR
IntPtr pszTimeStampAlgorithmOid,//PCSTR
IntPtr psRequest,//PCRYPT\u属性
IntPtr pSipData,//LPVOID
out IntPtr ppSignerContext//SIGNER\u上下文
);
公共静态void TimestampSignedAssembly(字符串appPath、字符串tsaServer)
{
如果(tsaServer==null)抛出新的ArgumentNullException(“tsaServer”);
IntPtr psubectinfo=IntPtr.Zero;
尝试
{
psObjectInfo=CreateSignerSubjectInfo(appPath);
TimestampSignedAssembly(PSObjectInfo,tsaServer);
}
最后
{
if(PSObjectInfo!=IntPtr.Zero)
{
Marshal.DestroyStructure(psObjectInfo,typeof(SIGNER_SUBJECT_INFO));
}
}
}
私有静态IntPtr CreateSignerSubjectInfo(字符串路径到汇编)
{
签名者\主题\信息=新签名者\主题\信息
{
cbSize=(uint)Marshal.SizeOf(typeof(SIGNER\u SUBJECT\u INFO)),
pdwIndex=Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint)))
};
int指数=0;
Marshal.StructureToPtr(index,info.pdwIndex,false);
info.dwSubjectChoice=0x1;//签名者\主题\文件
IntPtr assemblyFilePtr=Marshal.StringToHGlobalUni(路径到assembly);
签名者文件信息文件信息=新签名者文件信息
{
cbSize=(uint)Marshal.SizeOf(typeof(SIGNER\u FILE\u INFO)),
pwszFileName=assemblyFilePtr,
hFile=IntPtr.Zero
};
info.Union1=新签名者\u主题\u info.SubjectChoiceUnion
{
pSignerFileInfo=Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SIGNER\u FILE\u INFO)))
};
Marshal.StructureToPtr(fileInfo,info.Union1.pSignerFileInfo,false);
IntPtr pSubjectInfo=Marshal.AllocHGlobal(Marshal.SizeOf(info));
Marshal.StructureToPtr(info,psubectinfo,false);
返回psubectinfo;
}
/*
这里调用了CryptoAPI函数SignerTimeStampEx2。
*/
私有静态void TimestampSignedAssembly(IntPtr psubectinfo,string tsaServer)
{
IntPtr上下文;
int hResult=SignerTimeStampEx2(
0x2,//签名者\u时间戳\u RFC3161
PSubectInfo,
TSA服务器,
Marshal.StringToHGlobalAnsi(“2.16.840.1.101.3.4.2.1”),//szOID\u NIST\u sha256常量,sha256哈希算法。
IntPtr.Zero,
IntPtr.Zero,
断章取义
);
如果(hResult!=0)
{
抛出新异常(string.Format(“添加时间戳时出错-错误代码:0x{0:X}”,hResult));
}
}
}
用法示例:
Timestamper.TimestampSignedAssembly("Assembly.exe", "http://timestamp.comodoca.com/?td=sha256");
+1.我认为您应该使用SIGNER\u TIMESTAMP\u RFC3161作为第一个标志。现在。。。我也不知道在哪里可以找到SIGNER\u TIMESTAMP\u rfc3116和SIGNER\u TIMESTAMP\u AUTHENTICODE值。。。在反汇编mssign32.dll时,我认为“1”意味着签名者\u时间戳\u身份验证码(因为SignerTimeStamp调用SignerTimeStampEx3,第一个参数值为1)。因此,您应该尝试使用0、2或3作为标志值。谢谢您的回答。我尝试将0、2和3作为标志值传递,并得到以下结果:0和3-发生0x80070057错误(一个或多个参数无效),2-crypt32.dll中的APPCRASH(错误代码-c0000005,访问Violat