C# 코드의 CryptoAPI를 사용하여 SHA256 타임 스탬프를 서명 된 어셈블리에 추가하려고합니다.CryptoAPI의 SignerTimeStampEx2 (PInvoke 사용)
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 매개 변수는 무엇입니까?
미리 감사드립니다.
+1. 첫 번째 플래그로 SIGNER_TIMESTAMP_RFC3161을 사용해야한다고 생각합니다. 이제 ... SIGNER_TIMESTAMP_RFC3161 및 SIGNER_TIMESTAMP_AUTHENTICODE 값을 찾을 수있는 위치를 모르겠습니다 ... mssign32.dll을 디스 어셈블 할 때 '1'은 SIGNER_TIMESTAMP_AUTHENTICODE를 의미한다고 생각합니다 (SignerTimeStamp는 첫 번째 매개 변수 값으로 1을 사용하여 SignerTimeStampEx3을 호출하기 때문에). 따라서 플래그 값으로 0, 2 또는 3을 시도해야합니다. –
답변 주셔서 감사합니다. 0, 2, 3을 플래그 값으로 전달하려고 시도하고 다음 결과가 나타납니다. 0과 3 - 0x80070057 오류 발생 (하나 이상의 인수가 유효하지 않음), 2 - APPCRASH in crypt32.dll (오류 코드 - c0000005, 액세스 위반 ?) – ruslangil
진행 상황 :-) SIGNER_FILE_INFO에서 pwszFileName을 수정할 수도 있습니다. 문자열을 사용하고 CharSet = CharSet.Unicode를 구조체 정의에 추가하면됩니다. –