了解如何使用SignerSignEx2函数对应用包进行签名。 如果要使用Packaging API以编程方式创建Windows应用商店应用包,则还需要在部署之前对应用包进行签名。Packaging API不提供用于签署应用程序包的专用方法。而是使用标准加密函数来签署您的应用程序包。

你需要知道什么

技术

  • 代码签名简介
  • Windows应用商店应用的打包,部署和查询
  • 密码学功能

先决条件

  • 您需要一个打包的Windows应用商店应用。有关创建应用程序包的信息,请参阅如何创建应用程序包。
  • 您需要具有适合签署应用程序包的代码签名证书。有关创建测试代码签名证书的信息,请参阅如何创建应用程序包签名证书。将此签名证书加载到CERT_CONTEXT结构中。例如,您可以使用PFXImportCertStore和CertFindCertificateInStore来加载签名证书。
  • Windows 8引入了SignerSignEx2功能。在Windows Store应用程序包签名时使用SignerSignEx2。

说明

第1步:为SignerSignEx2定义所需的结构

除了Wincrypt.h头之外,SignerSignEx2函数还依赖于许多SDK头文件中未定义的结构。要使用SignerSignEx2,您必须自己定义这些结构:

C ++复制
  1. typedef struct _SIGNER_FILE_INFO
  2. {
  3. DWORD cbSize;
  4. LPCWSTR pwszFileName;
  5. HANDLE hFile;
  6. }SIGNER_FILE_INFO, *PSIGNER_FILE_INFO;
  7.  
  8. typedef struct _SIGNER_BLOB_INFO
  9. {
  10. DWORD cbSize;
  11. GUID *pGuidSubject;
  12. DWORD cbBlob;
  13. BYTE *pbBlob;
  14. LPCWSTR pwszDisplayName;
  15. }SIGNER_BLOB_INFO, *PSIGNER_BLOB_INFO;
  16.  
  17. typedef struct _SIGNER_SUBJECT_INFO
  18. {
  19. DWORD cbSize;
  20. DWORD *pdwIndex;
  21. DWORD dwSubjectChoice;
  22. union
  23. {
  24. SIGNER_FILE_INFO *pSignerFileInfo;
  25. SIGNER_BLOB_INFO *pSignerBlobInfo;
  26. };
  27. }SIGNER_SUBJECT_INFO, *PSIGNER_SUBJECT_INFO;
  28.  
  29. // dwSubjectChoice should be one of the following:
  30. #define SIGNER_SUBJECT_FILE 0x01
  31. #define SIGNER_SUBJECT_BLOB 0x02
  32.  
  33. typedef struct _SIGNER_ATTR_AUTHCODE
  34. {
  35. DWORD cbSize;
  36. BOOL fCommercial;
  37. BOOL fIndividual;
  38. LPCWSTR pwszName;
  39. LPCWSTR pwszInfo;
  40. }SIGNER_ATTR_AUTHCODE, *PSIGNER_ATTR_AUTHCODE;
  41.  
  42. typedef struct _SIGNER_SIGNATURE_INFO
  43. {
  44. DWORD cbSize;
  45. ALG_ID algidHash;
  46. DWORD dwAttrChoice;
  47. union
  48. {
  49. SIGNER_ATTR_AUTHCODE *pAttrAuthcode;
  50. };
  51. PCRYPT_ATTRIBUTES psAuthenticated;
  52. PCRYPT_ATTRIBUTES psUnauthenticated;
  53. }SIGNER_SIGNATURE_INFO, *PSIGNER_SIGNATURE_INFO;
  54.  
  55. // dwAttrChoice should be one of the following:
  56. #define SIGNER_NO_ATTR 0x00
  57. #define SIGNER_AUTHCODE_ATTR 0x01
  58.  
  59. typedef struct _SIGNER_PROVIDER_INFO
  60. {
  61. DWORD cbSize;
  62. LPCWSTR pwszProviderName;
  63. DWORD dwProviderType;
  64. DWORD dwKeySpec;
  65. DWORD dwPvkChoice;
  66. union
  67. {
  68. LPWSTR pwszPvkFileName;
  69. LPWSTR pwszKeyContainer;
  70. };
  71. }SIGNER_PROVIDER_INFO, *PSIGNER_PROVIDER_INFO;
  72.  
  73. //dwPvkChoice should be one of the following:
  74. #define PVK_TYPE_FILE_NAME 0x01
  75. #define PVK_TYPE_KEYCONTAINER 0x02
  76.  
  77. typedef struct _SIGNER_SPC_CHAIN_INFO
  78. {
  79. DWORD cbSize;
  80. LPCWSTR pwszSpcFile;
  81. DWORD dwCertPolicy;
  82. HCERTSTORE hCertStore;
  83. }SIGNER_SPC_CHAIN_INFO, *PSIGNER_SPC_CHAIN_INFO;
  84.  
  85. typedef struct _SIGNER_CERT_STORE_INFO
  86. {
  87. DWORD cbSize;
  88. PCCERT_CONTEXT pSigningCert;
  89. DWORD dwCertPolicy;
  90. HCERTSTORE hCertStore;
  91. }SIGNER_CERT_STORE_INFO, *PSIGNER_CERT_STORE_INFO;
  92.  
  93. //dwCertPolicy can be a combination of the following flags:
  94. #define SIGNER_CERT_POLICY_STORE 0x01
  95. #define SIGNER_CERT_POLICY_CHAIN 0x02
  96. #define SIGNER_CERT_POLICY_SPC 0x04
  97. #define SIGNER_CERT_POLICY_CHAIN_NO_ROOT 0x08
  98.  
  99. typedef struct _SIGNER_CERT
  100. {
  101. DWORD cbSize;
  102. DWORD dwCertChoice;
  103. union
  104. {
  105. LPCWSTR pwszSpcFile;
  106. SIGNER_CERT_STORE_INFO *pCertStoreInfo;
  107. SIGNER_SPC_CHAIN_INFO *pSpcChainInfo;
  108. };
  109. HWND hwnd;
  110. }SIGNER_CERT, *PSIGNER_CERT;
  111.  
  112. //dwCertChoice should be one of the following
  113. #define SIGNER_CERT_SPC_FILE 0x01
  114. #define SIGNER_CERT_STORE 0x02
  115. #define SIGNER_CERT_SPC_CHAIN 0x03
  116.  
  117. typedef struct _SIGNER_CONTEXT
  118. {
  119. DWORD cbSize;
  120. DWORD cbBlob;
  121. BYTE *pbBlob;
  122. }SIGNER_CONTEXT, *PSIGNER_CONTEXT;
  123.  
  124. typedef struct _SIGNER_SIGN_EX2_PARAMS
  125. {
  126. DWORD dwFlags;
  127. PSIGNER_SUBJECT_INFO pSubjectInfo;
  128. PSIGNER_CERT pSigningCert;
  129. PSIGNER_SIGNATURE_INFO pSignatureInfo;
  130. PSIGNER_PROVIDER_INFO pProviderInfo;
  131. DWORD dwTimestampFlags;
  132. PCSTR pszAlgorithmOid;
  133. PCWSTR pwszTimestampURL;
  134. PCRYPT_ATTRIBUTES pCryptAttrs;
  135. PVOID pSipData;
  136. PSIGNER_CONTEXT *pSignerContext;
  137. PVOID pCryptoPolicy;
  138. PVOID pReserved;
  139. } SIGNER_SIGN_EX2_PARAMS, *PSIGNER_SIGN_EX2_PARAMS;
  140.  
  141. typedef struct _APPX_SIP_CLIENT_DATA
  142. {
  143. PSIGNER_SIGN_EX2_PARAMS pSignerParams;
  144. IUnknown* pAppxSipState;
  145. } APPX_SIP_CLIENT_DATA, *PAPPX_SIP_CLIENT_DATA;

第2步:调用SignerSignEx2签署应用程序包

定义上一步中指定的所需结构后,可以使用SignerSignEx2函数上的任何可用选项对应用程序包进行签名。将SignerSignEx2与Windows Store应用程序包一起使用时,这些限制适用:

  • 在签署应用程序包时,必须提供指向APPX_SIP_CLIENT_DATA结构的指针作为pSipData参数。您必须填充pSignerParams成员APPX_SIP_CLIENT_DATA与您用来签署应用程序包相同的参数。为此,在SIGNER_SIGN_EX2_PARAMS结构上定义所需的参数,将此结构的地址分配给pSignerParams,然后在调用SignerSignEx2时直接引用结构的成员。
  • 你打电话后SignerSignEx2,你必须释放pAppxSipState上pSipData通过调用的IUnknown ::发布上pAppxSipState如果它不是空。
  • SIGNER_SIGNATURE_INFO结构的algidHash成员必须与创建应用程序包时使用的哈希算法相同。有关如何从应用程序包中确定哈希算法的信息,请参阅如何使用SignTool对应用程序包进行签名。MakeAppx和Visual Studio用于创建应用程序包的Windows 8默认算法是“algidHash = CALG_SHA_256”。
  • 如果您还要在应用程序包上标记签名,则必须通过提供SignerSignEx2的可选时间戳参数(dwTimestampFlags,pszTimestampAlgorithmOid,pwszHttpTimeStamp,psRequest)在调用SignerSignEx2期间执行此操作。不支持在已签名的应用程序包上调用SignerTimeStampEx3或其变体。

下面是一些示例代码,演示如何调用SignerSignEx2:

C ++复制
  1. HRESULT SignAppxPackage(
  2. _In_ PCCERT_CONTEXT signingCertContext,
  3. _In_ LPCWSTR packageFilePath)
  4. {
  5. HRESULT hr = S_OK;
  6.  
  7. // Initialize the parameters for SignerSignEx2
  8. DWORD signerIndex = 0;
  9.  
  10. SIGNER_FILE_INFO fileInfo = {};
  11. fileInfo.cbSize = sizeof(SIGNER_FILE_INFO);
  12. fileInfo.pwszFileName = packageFilePath;
  13.  
  14. SIGNER_SUBJECT_INFO subjectInfo = {};
  15. subjectInfo.cbSize = sizeof(SIGNER_SUBJECT_INFO);
  16. subjectInfo.pdwIndex = &signerIndex;
  17. subjectInfo.dwSubjectChoice = SIGNER_SUBJECT_FILE;
  18. subjectInfo.pSignerFileInfo = &fileInfo;
  19.  
  20. SIGNER_CERT_STORE_INFO certStoreInfo = {};
  21. certStoreInfo.cbSize = sizeof(SIGNER_CERT_STORE_INFO);
  22. certStoreInfo.dwCertPolicy = SIGNER_CERT_POLICY_CHAIN_NO_ROOT;
  23. certStoreInfo.pSigningCert = signingCertContext;
  24.  
  25. SIGNER_CERT cert = {};
  26. cert.cbSize = sizeof(SIGNER_CERT);
  27. cert.dwCertChoice = SIGNER_CERT_STORE;
  28. cert.pCertStoreInfo = &certStoreInfo;
  29.  
  30. // The algidHash of the signature to be created must match the
  31. // hash algorithm used to create the app package
  32. SIGNER_SIGNATURE_INFO signatureInfo = {};
  33. signatureInfo.cbSize = sizeof(SIGNER_SIGNATURE_INFO);
  34. signatureInfo.algidHash = CALG_SHA_256;
  35. signatureInfo.dwAttrChoice = SIGNER_NO_ATTR;
  36.  
  37. SIGNER_SIGN_EX2_PARAMS signerParams = {};
  38. signerParams.pSubjectInfo = &subjectInfo;
  39. signerParams.pSigningCert = &cert;
  40. signerParams.pSignatureInfo = &signatureInfo;
  41.  
  42. APPX_SIP_CLIENT_DATA sipClientData = {};
  43. sipClientData.pSignerParams = &signerParams;
  44. signerParams.pSipData = &sipClientData;
  45.  
  46. // Type definition for invoking SignerSignEx2 via GetProcAddress
  47. typedef HRESULT (WINAPI *SignerSignEx2Function)(
  48. DWORD,
  49. PSIGNER_SUBJECT_INFO,
  50. PSIGNER_CERT,
  51. PSIGNER_SIGNATURE_INFO,
  52. PSIGNER_PROVIDER_INFO,
  53. DWORD,
  54. PCSTR,
  55. PCWSTR,
  56. PCRYPT_ATTRIBUTES,
  57. PVOID,
  58. PSIGNER_CONTEXT *,
  59. PVOID,
  60. PVOID);
  61.  
  62. // Load the SignerSignEx2 function from MSSign32.dll
  63. HMODULE msSignModule = LoadLibraryEx(
  64. L"MSSign32.dll",
  65. NULL,
  66. LOAD_LIBRARY_SEARCH_SYSTEM32);
  67.  
  68. if (msSignModule)
  69. {
  70. SignerSignEx2Function SignerSignEx2 = reinterpret_cast<SignerSignEx2Function>(
  71. GetProcAddress(msSignModule, "SignerSignEx2"));
  72. if (SignerSignEx2)
  73. {
  74. hr = SignerSignEx2(
  75. signerParams.dwFlags,
  76. signerParams.pSubjectInfo,
  77. signerParams.pSigningCert,
  78. signerParams.pSignatureInfo,
  79. signerParams.pProviderInfo,
  80. signerParams.dwTimestampFlags,
  81. signerParams.pszAlgorithmOid,
  82. signerParams.pwszTimestampURL,
  83. signerParams.pCryptAttrs,
  84. signerParams.pSipData,
  85. signerParams.pSignerContext,
  86. signerParams.pCryptoPolicy,
  87. signerParams.pReserved);
  88. }
  89. else
  90. {
  91. DWORD lastError = GetLastError();
  92. hr = HRESULT_FROM_WIN32(lastError);
  93. }
  94.  
  95. FreeLibrary(msSignModule);
  96. }
  97. else
  98. {
  99. DWORD lastError = GetLastError();
  100. hr = HRESULT_FROM_WIN32(lastError);
  101. }
  102.  
  103. // Free any state used during app package signing
  104. if (sipClientData.pAppxSipState)
  105. {
  106. sipClientData.pAppxSipState->Release();
  107. }
  108.  
  109. return hr;
  110. }

备注

签署应用程序包后,您还可以尝试使用WINVUST_ACTION_GENERIC_VERIFY_V2的WinVerifyTrust函数以编程方式验证签名。对于在Windows Store应用程序包中使用WinVerifyTrust,在这种情况下没有特别注意事项。

如何以编程方式签署应用程序包(C ++)的更多相关文章

  1. ASP.NET MVC下的四种验证编程方式[续篇]

    在<ASP.NET MVC下的四种验证编程方式>一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式("手工验证"."标注Validation ...

  2. ASP.NET MVC下的四种验证编程方式

    ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效性,我们将针对参数的验证成为Model绑定 ...

  3. [转]Windows网络编程学习-面向连接的编程方式

    直接附上原文链接:windows 网络编程学习-面向连接的编程方式

  4. C#通过编程方式实现Ping

    代码是照着书敲的,贴出来方便平时参考 using System; using System.Collections.Generic; using System.Linq; using System.T ...

  5. ASP.NET MVC下的四种验证编程方式[续篇]【转】

    在<ASP.NET MVC下的四种验证编程方式> 一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式(“手工验证”.“标注ValidationAttribute特性”.“ ...

  6. ASP.NET MVC下的四种验证编程方式【转】

    ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效 性,我们将针对参数的验证成为Model绑 ...

  7. WCF编程系列(六)以编程方式配置终结点

    WCF编程系列(六)以编程方式配置终结点   示例一中我们的宿主程序非常简单:只是简单的实例化了一个ServiceHost对象,然后调用open方法来启动服务.而关于终结点的配置我们都是通过配置文件来 ...

  8. CodeFirst 的编程方式

    第一步:创建控制台项目第二步:添加新建项目→Ado.Net空实体模型第三步:添加实体:Customer,添加几个必要的测试字段第四步:添加实体之间的联系第五步:根据模型生成数据库脚本,并执行sql脚本 ...

  9. uglifyjs压缩js文件(指令压缩/ 批量压缩/ 编程方式压缩)

    一.指令压缩 1.安装node,npm——详细见nodejs安装与使用入门 2.安装 uglifyjs——npm install -g uglify-js 3.压缩例子:1)uglifyjs  mai ...

随机推荐

  1. Spring Security-- 验证码功能的实现

    spring security4 添加验证码 http://www.itwendao.com/article/detail/165400.html http://www.itdadao.com/art ...

  2. aliyun TableStore相关操作汇总

    总结:这个东西本身可能技术还不成熟,使用的人少,有问题很验证解决 遇到的问题:(1)没有一个GUI工具,使用门槛高(2)查询的GetRange不方便,把查询出来的数据使用System.out.prin ...

  3. 关于新建Eclipse新建一个WEB项目后创建一个jsp文件头部报错问题?

    点击项目右键→Build Path→Libraries→AddLibrary→Server Runtime→Apache Tomcat v7.0→Finsh  操作步骤如上! http://jingy ...

  4. 优雅地实现CSS Animation delay心得

    话不多说直接开讲: 1.需求: 等待元素A的动画加载完,再加载B元素的动画(下图中A为大熊猫,B为下方卡片) 先来看下最后的效果啦: 2.初始思路: 在B元素的动画属性上加上delay(延迟,使得这个 ...

  5. Win7 系统记事本乱码及cmd闪退解决办法

    打开控制面板,点击时钟.语言和区域               中文(简体)改为英语(英国),然后重启电脑,重启电脑之后,继续此操作,在把英语(英国)改为中文(简体),再次重启电脑,就OK了.

  6. 高德地图 地铁图adcode 城市代码

    北京 1100天津 1200石家庄 1301沈阳 2101大连 2102长春 2201哈尔滨 2301上海 3100南京 3201无锡 3202苏州 3205杭州 3301宁波 3302合肥 3401 ...

  7. I/O-----字符输入流

    今天学习了字符流  ,果不其然又和以前的搞混了 package io.day04; import java.io.FileReader; import java.io.FileWriter; impo ...

  8. 【cogs 775】山海经 ——Segment Tree

    题目链接:      TP 题解:   我数据结构真心是弱啊= =. 线段树好厉害啊,一直不会区间最大连续和,今天刚学习了一下233. 维护前缀最大和后缀最大,越界最大(?),再维护一个区间最大,瞎搞 ...

  9. Java的LockSupport.park()实现分析(转载)

    LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际上是调用了Unsafe类里的函数,归结到Unsafe里,只有两个函数: p ...

  10. 一种非常巧妙的读取串口数据的方法--C#

    读取不完就一直等待,读完了就立刻走,之前都是设置一个溢出时间,不管是不是早就读取完了都要在这等着,有一定的时间浪费. 注意,用之前要设置好SerialPort类的TimeOut属性: