验证文件数字签名
2011-11-30 16:51
218 查看
工作中碰到需要判断一个PE文件是否是所确认的文件,而不是被替换过的。直接判断文件名的话有些不保险,别人只要修改下文件名,就可以以假乱真。
因而需要判断额外的信息;由于文件有数字签名,判断数字签名因而是一个比较好的方法,但是如果只是判断数字签名是否有效也不够,别人只要用自己的证书重新签名就可以了,所以需要判断证书签名者信息。
验证文件数字签名是否有效可以使用函数 WinVerifyTrust
取得文件数字签名证书信息需要使用函数 CryptQueryObject。
下面是一段从网上搜到的获得文件数字签名证书信息的代码:
因而需要判断额外的信息;由于文件有数字签名,判断数字签名因而是一个比较好的方法,但是如果只是判断数字签名是否有效也不够,别人只要用自己的证书重新签名就可以了,所以需要判断证书签名者信息。
验证文件数字签名是否有效可以使用函数 WinVerifyTrust
取得文件数字签名证书信息需要使用函数 CryptQueryObject。
下面是一段从网上搜到的获得文件数字签名证书信息的代码:
1 #include <windows.h> 2 #include <wincrypt.h> 3 #include <wintrust.h> 4 #include <stdio.h> 5 #include <tchar.h> 6 #pragma comment(lib, "crypt32.lib") 7 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) 8 typedef struct { 9 LPWSTR lpszProgramName; 10 LPWSTR lpszPublisherLink; 11 LPWSTR lpszMoreInfoLink; 12 } SPROG_PUBLISHERINFO, *PSPROG_PUBLISHERINFO; 13 BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo, 14 PSPROG_PUBLISHERINFO Info); 15 BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st); 16 BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext); 17 BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo, 18 PCMSG_SIGNER_INFO *pCounterSignerInfo); 19 int _tmain(int argc, TCHAR *argv[]) 20 { 21 WCHAR szFileName[MAX_PATH]; 22 HCERTSTORE hStore = NULL; 23 HCRYPTMSG hMsg = NULL; 24 PCCERT_CONTEXT pCertContext = NULL; 25 BOOL fResult; 26 DWORD dwEncoding, dwContentType, dwFormatType; 27 PCMSG_SIGNER_INFO pSignerInfo = NULL; 28 PCMSG_SIGNER_INFO pCounterSignerInfo = NULL; 29 DWORD dwSignerInfo; 30 CERT_INFO CertInfo; 31 SPROG_PUBLISHERINFO ProgPubInfo; 32 SYSTEMTIME st; 33 ZeroMemory(&ProgPubInfo, sizeof(ProgPubInfo)); 34 __try 35 { 36 if (argc != 2) 37 { 38 _tprintf(_T("Usage: SignedFileInfo <filename>\n")); 39 return 0; 40 } 41 #ifdef UNICODE 42 lstrcpynW(szFileName, argv[1], MAX_PATH); 43 #else 44 if (mbstowcs(szFileName, argv[1], MAX_PATH) == -1) 45 { 46 printf("Unable to convert to unicode.\n"); 47 __leave; 48 } 49 #endif 50 // Get message handle and store handle from the signed file. 51 fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE, 52 szFileName, 53 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, 54 CERT_QUERY_FORMAT_FLAG_BINARY, 55 0, 56 &dwEncoding, 57 &dwContentType, 58 &dwFormatType, 59 &hStore, 60 &hMsg, 61 NULL); 62 if (!fResult) 63 { 64 _tprintf(_T("CryptQueryObject failed with %x\n"), GetLastError()); 65 __leave; 66 } 67 // Get signer information size. 68 fResult = CryptMsgGetParam(hMsg, 69 CMSG_SIGNER_INFO_PARAM, 70 0, 71 NULL, 72 &dwSignerInfo); 73 if (!fResult) 74 { 75 _tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError()); 76 __leave; 77 } 78 // Allocate memory for signer information. 79 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo); 80 if (!pSignerInfo) 81 { 82 _tprintf(_T("Unable to allocate memory for Signer Info.\n")); 83 __leave; 84 } 85 // Get Signer Information. 86 fResult = CryptMsgGetParam(hMsg, 87 CMSG_SIGNER_INFO_PARAM, 88 0, 89 (PVOID)pSignerInfo, 90 &dwSignerInfo); 91 if (!fResult) 92 { 93 _tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError()); 94 __leave; 95 } 96 // Get program name and publisher information from 97 // signer info structure. 98 if (GetProgAndPublisherInfo(pSignerInfo, &ProgPubInfo)) 99 { 100 if (ProgPubInfo.lpszProgramName != NULL) 101 { 102 wprintf(L"Program Name : %s\n", 103 ProgPubInfo.lpszProgramName); 104 } 105 if (ProgPubInfo.lpszPublisherLink != NULL) 106 { 107 wprintf(L"Publisher Link : %s\n", 108 ProgPubInfo.lpszPublisherLink); 109 } 110 if (ProgPubInfo.lpszMoreInfoLink != NULL) 111 { 112 wprintf(L"MoreInfo Link : %s\n", 113 ProgPubInfo.lpszMoreInfoLink); 114 } 115 } 116 _tprintf(_T("\n")); 117 // Search for the signer certificate in the temporary 118 // certificate store. 119 CertInfo.Issuer = pSignerInfo->Issuer; 120 CertInfo.SerialNumber = pSignerInfo->SerialNumber; 121 pCertContext = CertFindCertificateInStore(hStore, 122 ENCODING, 123 0, 124 CERT_FIND_SUBJECT_CERT, 125 (PVOID)&CertInfo, 126 NULL); 127 if (!pCertContext) 128 { 129 _tprintf(_T("CertFindCertificateInStore failed with %x\n"), 130 GetLastError()); 131 __leave; 132 } 133 // Print Signer certificate information. 134 _tprintf(_T("Signer Certificate:\n\n")); 135 PrintCertificateInfo(pCertContext); 136 _tprintf(_T("\n")); 137 // Get the timestamp certificate signerinfo structure. 138 if (GetTimeStampSignerInfo(pSignerInfo, &pCounterSignerInfo)) 139 { 140 // Search for Timestamp certificate in the temporary 141 // certificate store. 142 CertInfo.Issuer = pCounterSignerInfo->Issuer; 143 CertInfo.SerialNumber = pCounterSignerInfo->SerialNumber; 144 pCertContext = CertFindCertificateInStore(hStore, 145 ENCODING, 146 0, 147 CERT_FIND_SUBJECT_CERT, 148 (PVOID)&CertInfo, 149 NULL); 150 if (!pCertContext) 151 { 152 _tprintf(_T("CertFindCertificateInStore failed with %x\n"), 153 GetLastError()); 154 __leave; 155 } 156 // Print timestamp certificate information. 157 _tprintf(_T("TimeStamp Certificate:\n\n")); 158 PrintCertificateInfo(pCertContext); 159 _tprintf(_T("\n")); 160 // Find Date of timestamp. 161 if (GetDateOfTimeStamp(pCounterSignerInfo, &st)) 162 { 163 _tprintf(_T("Date of TimeStamp : %02d/%02d/%04d %02d:%02d\n"), 164 st.wMonth, 165 st.wDay, 166 st.wYear, 167 st.wHour, 168 st.wMinute); 169 } 170 _tprintf(_T("\n")); 171 } 172 } 173 __finally 174 { 175 // Clean up. 176 if (ProgPubInfo.lpszProgramName != NULL) 177 LocalFree(ProgPubInfo.lpszProgramName); 178 if (ProgPubInfo.lpszPublisherLink != NULL) 179 LocalFree(ProgPubInfo.lpszPublisherLink); 180 if (ProgPubInfo.lpszMoreInfoLink != NULL) 181 LocalFree(ProgPubInfo.lpszMoreInfoLink); 182 if (pSignerInfo != NULL) LocalFree(pSignerInfo); 183 if (pCounterSignerInfo != NULL) LocalFree(pCounterSignerInfo); 184 if (pCertContext != NULL) CertFreeCertificateContext(pCertContext); 185 if (hStore != NULL) CertCloseStore(hStore, 0); 186 if (hMsg != NULL) CryptMsgClose(hMsg); 187 } 188 return 0; 189 } 190 BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext) 191 { 192 BOOL fReturn = FALSE; 193 LPTSTR szName = NULL; 194 DWORD dwData; 195 __try 196 { 197 // Print Serial Number. 198 _tprintf(_T("Serial Number: ")); 199 dwData = pCertContext->pCertInfo->SerialNumber.cbData; 200 for (DWORD n = 0; n < dwData; n++) 201 { 202 _tprintf(_T("%02x "), 203 pCertContext->pCertInfo->SerialNumber.pbData[dwData - (n + 1)]); 204 } 205 _tprintf(_T("\n")); 206 // Get Issuer name size. 207 if (!(dwData = CertGetNameString(pCertContext, 208 CERT_NAME_SIMPLE_DISPLAY_TYPE, 209 CERT_NAME_ISSUER_FLAG, 210 NULL, 211 NULL, 212 0))) 213 { 214 _tprintf(_T("CertGetNameString failed.\n")); 215 __leave; 216 } 217 // Allocate memory for Issuer name. 218 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR)); 219 if (!szName) 220 { 221 _tprintf(_T("Unable to allocate memory for issuer name.\n")); 222 __leave; 223 } 224 // Get Issuer name. 225 if (!(CertGetNameString(pCertContext, 226 CERT_NAME_SIMPLE_DISPLAY_TYPE, 227 CERT_NAME_ISSUER_FLAG, 228 NULL, 229 szName, 230 dwData))) 231 { 232 _tprintf(_T("CertGetNameString failed.\n")); 233 __leave; 234 } 235 // print Issuer name. 236 _tprintf(_T("Issuer Name: %s\n"), szName); 237 LocalFree(szName); 238 szName = NULL; 239 // Get Subject name size. 240 if (!(dwData = CertGetNameString(pCertContext, 241 CERT_NAME_SIMPLE_DISPLAY_TYPE, 242 0, 243 NULL, 244 NULL, 245 0))) 246 { 247 _tprintf(_T("CertGetNameString failed.\n")); 248 __leave; 249 } 250 // Allocate memory for subject name. 251 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR)); 252 if (!szName) 253 { 254 _tprintf(_T("Unable to allocate memory for subject name.\n")); 255 __leave; 256 } 257 // Get subject name. 258 if (!(CertGetNameString(pCertContext, 259 CERT_NAME_SIMPLE_DISPLAY_TYPE, 260 0, 261 NULL, 262 szName, 263 dwData))) 264 { 265 _tprintf(_T("CertGetNameString failed.\n")); 266 __leave; 267 } 268 // Print Subject Name. 269 _tprintf(_T("Subject Name: %s\n"), szName); 270 fReturn = TRUE; 271 } 272 __finally 273 { 274 if (szName != NULL) LocalFree(szName); 275 } 276 return fReturn; 277 } 278 LPWSTR AllocateAndCopyWideString(LPCWSTR inputString) 279 { 280 LPWSTR outputString = NULL; 281 outputString = (LPWSTR)LocalAlloc(LPTR, 282 (wcslen(inputString) + 1) * sizeof(WCHAR)); 283 if (outputString != NULL) 284 { 285 lstrcpyW(outputString, inputString); 286 } 287 return outputString; 288 } 289 BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo, 290 PSPROG_PUBLISHERINFO Info) 291 { 292 BOOL fReturn = FALSE; 293 PSPC_SP_OPUS_INFO OpusInfo = NULL; 294 DWORD dwData; 295 BOOL fResult; 296 __try 297 { 298 // Loop through authenticated attributes and find 299 // SPC_SP_OPUS_INFO_OBJID OID. 300 for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++) 301 { 302 if (lstrcmpA(SPC_SP_OPUS_INFO_OBJID, 303 pSignerInfo->AuthAttrs.rgAttr .pszObjId) == 0) 304 { 305 // Get Size of SPC_SP_OPUS_INFO structure. 306 fResult = CryptDecodeObject(ENCODING, 307 SPC_SP_OPUS_INFO_OBJID, 308 pSignerInfo->AuthAttrs.rgAttr .rgValue[0].pbData, 309 pSignerInfo->AuthAttrs.rgAttr .rgValue[0].cbData, 310 0, 311 NULL, 312 &dwData); 313 if (!fResult) 314 { 315 _tprintf(_T("CryptDecodeObject failed with %x\n"), 316 GetLastError()); 317 __leave; 318 } 319 // Allocate memory for SPC_SP_OPUS_INFO structure. 320 OpusInfo = (PSPC_SP_OPUS_INFO)LocalAlloc(LPTR, dwData); 321 if (!OpusInfo) 322 { 323 _tprintf(_T("Unable to allocate memory for Publisher Info.\n")); 324 __leave; 325 } 326 // Decode and get SPC_SP_OPUS_INFO structure. 327 fResult = CryptDecodeObject(ENCODING, 328 SPC_SP_OPUS_INFO_OBJID, 329 pSignerInfo->AuthAttrs.rgAttr .rgValue[0].pbData, 330 pSignerInfo->AuthAttrs.rgAttr .rgValue[0].cbData, 331 0, 332 OpusInfo, 333 &dwData); 334 if (!fResult) 335 { 336 _tprintf(_T("CryptDecodeObject failed with %x\n"), 337 GetLastError()); 338 __leave; 339 } 340 // Fill in Program Name if present. 341 if (OpusInfo->pwszProgramName) 342 { 343 Info->lpszProgramName = 344 AllocateAndCopyWideString(OpusInfo->pwszProgramName); 345 } 346 else 347 Info->lpszProgramName = NULL; 348 // Fill in Publisher Information if present. 349 if (OpusInfo->pPublisherInfo) 350 { 351 switch (OpusInfo->pPublisherInfo->dwLinkChoice) 352 { 353 case SPC_URL_LINK_CHOICE: 354 Info->lpszPublisherLink = 355 AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszUrl); 356 break; 357 case SPC_FILE_LINK_CHOICE: 358 Info->lpszPublisherLink = 359 AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszFile); 360 break; 361 default: 362 Info->lpszPublisherLink = NULL; 363 break; 364 } 365 } 366 else 367 { 368 Info->lpszPublisherLink = NULL; 369 } 370 // Fill in More Info if present. 371 if (OpusInfo->pMoreInfo) 372 { 373 switch (OpusInfo->pMoreInfo->dwLinkChoice) 374 { 375 case SPC_URL_LINK_CHOICE: 376 Info->lpszMoreInfoLink = 377 AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszUrl); 378 break; 379 case SPC_FILE_LINK_CHOICE: 380 Info->lpszMoreInfoLink = 381 AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszFile); 382 break; 383 default: 384 Info->lpszMoreInfoLink = NULL; 385 break; 386 } 387 } 388 else 389 { 390 Info->lpszMoreInfoLink = NULL; 391 } 392 fReturn = TRUE; 393 break; // Break from for loop. 394 } // lstrcmp SPC_SP_OPUS_INFO_OBJID 395 } // for 396 } 397 __finally 398 { 399 if (OpusInfo != NULL) LocalFree(OpusInfo); 400 } 401 return fReturn; 402 } 403 BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st) 404 { 405 BOOL fResult; 406 FILETIME lft, ft; 407 DWORD dwData; 408 BOOL fReturn = FALSE; 409 // Loop through authenticated attributes and find 410 // szOID_RSA_signingTime OID. 411 for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++) 412 { 413 if (lstrcmpA(szOID_RSA_signingTime, 414 pSignerInfo->AuthAttrs.rgAttr .pszObjId) == 0) 415 { 416 // Decode and get FILETIME structure. 417 dwData = sizeof(ft); 418 fResult = CryptDecodeObject(ENCODING, 419 szOID_RSA_signingTime, 420 pSignerInfo->AuthAttrs.rgAttr .rgValue[0].pbData, 421 pSignerInfo->AuthAttrs.rgAttr .rgValue[0].cbData, 422 0, 423 (PVOID)&ft, 424 &dwData); 425 if (!fResult) 426 { 427 _tprintf(_T("CryptDecodeObject failed with %x\n"), 428 GetLastError()); 429 break; 430 } 431 // Convert to local time. 432 FileTimeToLocalFileTime(&ft, &lft); 433 FileTimeToSystemTime(&lft, st); 434 fReturn = TRUE; 435 break; // Break from for loop. 436 } //lstrcmp szOID_RSA_signingTime 437 } // for 438 return fReturn; 439 } 440 BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo, PCMSG_SIGNER_INFO *pCounterSignerInfo) 441 { 442 PCCERT_CONTEXT pCertContext = NULL; 443 BOOL fReturn = FALSE; 444 BOOL fResult; 445 DWORD dwSize; 446 __try 447 { 448 *pCounterSignerInfo = NULL; 449 // Loop through unathenticated attributes for 450 // szOID_RSA_counterSign OID. 451 for (DWORD n = 0; n < pSignerInfo->UnauthAttrs.cAttr; n++) 452 { 453 if (lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr .pszObjId, 454 szOID_RSA_counterSign) == 0) 455 { 456 // Get size of CMSG_SIGNER_INFO structure. 457 fResult = CryptDecodeObject(ENCODING, 458 PKCS7_SIGNER_INFO, 459 pSignerInfo->UnauthAttrs.rgAttr .rgValue[0].pbData, 460 pSignerInfo->UnauthAttrs.rgAttr .rgValue[0].cbData, 461 0, 462 NULL, 463 &dwSize); 464 if (!fResult) 465 { 466 _tprintf(_T("CryptDecodeObject failed with %x\n"), 467 GetLastError()); 468 __leave; 469 } 470 // Allocate memory for CMSG_SIGNER_INFO. 471 *pCounterSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSize); 472 if (!*pCounterSignerInfo) 473 { 474 _tprintf(_T("Unable to allocate memory for timestamp info.\n")); 475 __leave; 476 } 477 // Decode and get CMSG_SIGNER_INFO structure 478 // for timestamp certificate. 479 fResult = CryptDecodeObject(ENCODING, 480 PKCS7_SIGNER_INFO, 481 pSignerInfo->UnauthAttrs.rgAttr .rgValue[0].pbData, 482 pSignerInfo->UnauthAttrs.rgAttr .rgValue[0].cbData, 483 0, 484 (PVOID)*pCounterSignerInfo, 485 &dwSize); 486 if (!fResult) 487 { 488 _tprintf(_T("CryptDecodeObject failed with %x\n"), 489 GetLastError()); 490 __leave; 491 } 492 fReturn = TRUE; 493 break; // Break from for loop. 494 } 495 } 496 } 497 __finally 498 { 499 // Clean up. 500 if (pCertContext != NULL) CertFreeCertificateContext(pCertContext); 501 } 502 return fReturn; 503 }
相关文章推荐
- 怎样使用.sig文件生成/验证数字签名?
- 验证文件数字签名
- 验证pe文件数字签名
- 验证 PE 文件的数字签名
- 使用数字签名验证文件是否被修改
- 阻止了此文件,因为它没有有效的数字签名以验证其发行者怎么解决方案
- Java代码实现文件添加数字签名、验证数字签名
- Windows 无法验证此文件的数字签名
- Win7系统无法验证文件数字签名(0xcoooo428)最佳解决方法
- delphi数字签名验证及能够获取数字签名文件信息(利用wintrust.dll的导出函数,翻译一下)
- 验证pe文件数字签名
- Win7阻止了此文件,因为它没有有效的数字签名以验证其发布者
- 文件上传验证绕过技术总结
- 验证编辑器出现:arm-linux-gcc: 没有那个文件或目录
- RMAN 验证 数据文件 和 备份 的有效性
- 在Linux上使用PGP签名验证文件完整性
- 利用xmlbeans工具对xml格式进行验证(需要xsd文件)
- EXCEL文件上传,内容格式验证(POI)
- js验证上传的文件是否为JPEG,PNG,JPG,GIF格式
- 基于RSA的数字签名和验证C#源码