Advertisement
Guest User

Untitled

a guest
Oct 9th, 2018
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.79 KB | None | 0 0
  1. #include <windows.h>
  2. #include <cryptuiapi.h>
  3. #include <iostream>
  4. #include <string>
  5.  
  6. /* Signs any binary with a certificate exported from the USB-Token.
  7.  *
  8.  * The PIN is now a command line argument so that batch signing becomes possible.
  9.  *
  10.  * The Token must be plugged in!
  11.  *
  12.  * Based upon https://stackoverflow.com/questions/17927895/automate-extended-validation-ev-code-signing
  13.  */
  14.  
  15. const std::wstring ETOKEN_BASE_CRYPT_PROV_NAME = L"eToken Base Cryptographic Provider";
  16.  
  17. std::string utf16_to_utf8(const std::wstring& str)
  18. {
  19.   if (str.empty())
  20.   {
  21.     return "";
  22.   }
  23.  
  24.   int utf8len = ::WideCharToMultiByte(CP_UTF8, 0, str.data(), str.size(), NULL, 0, NULL, NULL);
  25.   if (utf8len == 0)
  26.   {
  27.     return "";
  28.   }
  29.  
  30.   std::string utf8Str;
  31.   utf8Str.resize(utf8len);
  32.   ::WideCharToMultiByte(CP_UTF8, 0, str.data(), str.size(), &utf8Str[0], utf8Str.size(), NULL, NULL);
  33.  
  34.   return utf8Str;
  35. }
  36.  
  37. struct CryptProvHandle
  38. {
  39.   HCRYPTPROV Handle;
  40.   CryptProvHandle(HCRYPTPROV handle = NULL) : Handle(handle) {}
  41.   ~CryptProvHandle() { if (Handle) ::CryptReleaseContext(Handle, 0); }
  42. };
  43.  
  44. HCRYPTPROV token_logon(const std::wstring& containerName, const std::string& tokenPin)
  45. {
  46.   CryptProvHandle cryptProv;
  47.   if (!::CryptAcquireContext(&cryptProv.Handle, containerName.c_str(), ETOKEN_BASE_CRYPT_PROV_NAME.c_str(), PROV_RSA_FULL, CRYPT_SILENT))
  48.   {
  49.     std::wcerr << L"CryptAcquireContext failed, error " << std::hex << std::showbase << ::GetLastError() << L"\n";
  50.     return NULL;
  51.   }
  52.  
  53.   if (!::CryptSetProvParam(cryptProv.Handle, PP_SIGNATURE_PIN, reinterpret_cast<const BYTE*>(tokenPin.c_str()), 0))
  54.   {
  55.     std::wcerr << L"CryptSetProvParam failed, error " << std::hex << std::showbase << ::GetLastError() << L"\n";
  56.     return NULL;
  57.   }
  58.  
  59.   HCRYPTPROV result = cryptProv.Handle;
  60.   cryptProv.Handle = NULL;
  61.   return result;
  62. }
  63.  
  64. int wmain(int argc, wchar_t** argv)
  65. {
  66.   if (argc < 6)
  67.   {
  68.     std::wcerr << L"usage: etokensign.exe <certificate file path> <private key container name> <token PIN> <timestamp URL> <path to file to sign>\n";
  69.     return 1;
  70.   }
  71.  
  72.   const std::wstring certFile = argv[1];
  73.   const std::wstring containerName = argv[2];
  74.   const std::wstring tokenPin = argv[3];
  75.   const std::wstring timestampUrl = argv[4];
  76.   const std::wstring fileToSign = argv[5];
  77.  
  78.   CryptProvHandle cryptProv = token_logon(containerName, utf16_to_utf8(tokenPin));
  79.   if (!cryptProv.Handle)
  80.   {
  81.     return 1;
  82.   }
  83.  
  84.   CRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO extInfo = {};
  85.   extInfo.dwSize = sizeof(extInfo);
  86.   extInfo.pszHashAlg = szOID_NIST_sha256; // Use SHA256 instead of default SHA1
  87.  
  88.   CRYPT_KEY_PROV_INFO keyProvInfo = {};
  89.   keyProvInfo.pwszContainerName = const_cast<wchar_t*>(containerName.c_str());
  90.   keyProvInfo.pwszProvName = const_cast<wchar_t*>(ETOKEN_BASE_CRYPT_PROV_NAME.c_str());
  91.   keyProvInfo.dwProvType = PROV_RSA_FULL;
  92.  
  93.   CRYPTUI_WIZ_DIGITAL_SIGN_CERT_PVK_INFO pvkInfo = {};
  94.   pvkInfo.dwSize = sizeof(pvkInfo);
  95.   pvkInfo.pwszSigningCertFileName = const_cast<wchar_t*>(certFile.c_str());
  96.   pvkInfo.dwPvkChoice = CRYPTUI_WIZ_DIGITAL_SIGN_PVK_PROV;
  97.   pvkInfo.pPvkProvInfo = &keyProvInfo;
  98.  
  99.   CRYPTUI_WIZ_DIGITAL_SIGN_INFO signInfo = {};
  100.   signInfo.dwSize = sizeof(signInfo);
  101.   signInfo.dwSubjectChoice = CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE;
  102.   signInfo.pwszFileName = fileToSign.c_str();
  103.   signInfo.dwSigningCertChoice = CRYPTUI_WIZ_DIGITAL_SIGN_PVK;
  104.   signInfo.pSigningCertPvkInfo = &pvkInfo;
  105.   signInfo.pwszTimestampURL = timestampUrl.c_str();
  106.   signInfo.pSignExtInfo = &extInfo;
  107.  
  108.   if (!::CryptUIWizDigitalSign(CRYPTUI_WIZ_NO_UI, NULL, NULL, &signInfo, NULL))
  109.   {
  110.     std::wcerr << L"CryptUIWizDigitalSign failed, error " << std::hex << std::showbase << ::GetLastError() << L"\n";
  111.     return 1;
  112.   }
  113.  
  114.   std::wcout << L"Successfully signed " << fileToSign << L"\n";
  115.   return 0;
  116. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement