如何以编程方式签署应用程序包(C ++)
了解如何使用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,您必须自己定义这些结构:
typedef struct _SIGNER_FILE_INFO { DWORD cbSize; LPCWSTR pwszFileName; HANDLE hFile; }SIGNER_FILE_INFO, *PSIGNER_FILE_INFO; typedef struct _SIGNER_BLOB_INFO { DWORD cbSize; GUID *pGuidSubject; DWORD cbBlob; BYTE *pbBlob; LPCWSTR pwszDisplayName; }SIGNER_BLOB_INFO, *PSIGNER_BLOB_INFO; typedef struct _SIGNER_SUBJECT_INFO { DWORD cbSize; DWORD *pdwIndex; DWORD dwSubjectChoice; union { SIGNER_FILE_INFO *pSignerFileInfo; SIGNER_BLOB_INFO *pSignerBlobInfo; }; }SIGNER_SUBJECT_INFO, *PSIGNER_SUBJECT_INFO; // dwSubjectChoice should be one of the following: #define SIGNER_SUBJECT_FILE 0x01 #define SIGNER_SUBJECT_BLOB 0x02 typedef struct _SIGNER_ATTR_AUTHCODE { DWORD cbSize; BOOL fCommercial; BOOL fIndividual; LPCWSTR pwszName; LPCWSTR pwszInfo; }SIGNER_ATTR_AUTHCODE, *PSIGNER_ATTR_AUTHCODE; typedef struct _SIGNER_SIGNATURE_INFO { DWORD cbSize; ALG_ID algidHash; DWORD dwAttrChoice; union { SIGNER_ATTR_AUTHCODE *pAttrAuthcode; }; PCRYPT_ATTRIBUTES psAuthenticated; PCRYPT_ATTRIBUTES psUnauthenticated; }SIGNER_SIGNATURE_INFO, *PSIGNER_SIGNATURE_INFO; // dwAttrChoice should be one of the following: #define SIGNER_NO_ATTR 0x00 #define SIGNER_AUTHCODE_ATTR 0x01 typedef struct _SIGNER_PROVIDER_INFO { DWORD cbSize; LPCWSTR pwszProviderName; DWORD dwProviderType; DWORD dwKeySpec; DWORD dwPvkChoice; union { LPWSTR pwszPvkFileName; LPWSTR pwszKeyContainer; }; }SIGNER_PROVIDER_INFO, *PSIGNER_PROVIDER_INFO; //dwPvkChoice should be one of the following: #define PVK_TYPE_FILE_NAME 0x01 #define PVK_TYPE_KEYCONTAINER 0x02 typedef struct _SIGNER_SPC_CHAIN_INFO { DWORD cbSize; LPCWSTR pwszSpcFile; DWORD dwCertPolicy; HCERTSTORE hCertStore; }SIGNER_SPC_CHAIN_INFO, *PSIGNER_SPC_CHAIN_INFO; typedef struct _SIGNER_CERT_STORE_INFO { DWORD cbSize; PCCERT_CONTEXT pSigningCert; DWORD dwCertPolicy; HCERTSTORE hCertStore; }SIGNER_CERT_STORE_INFO, *PSIGNER_CERT_STORE_INFO; //dwCertPolicy can be a combination of the following flags: #define SIGNER_CERT_POLICY_STORE 0x01 #define SIGNER_CERT_POLICY_CHAIN 0x02 #define SIGNER_CERT_POLICY_SPC 0x04 #define SIGNER_CERT_POLICY_CHAIN_NO_ROOT 0x08 typedef struct _SIGNER_CERT { DWORD cbSize; DWORD dwCertChoice; union { LPCWSTR pwszSpcFile; SIGNER_CERT_STORE_INFO *pCertStoreInfo; SIGNER_SPC_CHAIN_INFO *pSpcChainInfo; }; HWND hwnd; }SIGNER_CERT, *PSIGNER_CERT; //dwCertChoice should be one of the following #define SIGNER_CERT_SPC_FILE 0x01 #define SIGNER_CERT_STORE 0x02 #define SIGNER_CERT_SPC_CHAIN 0x03 typedef struct _SIGNER_CONTEXT { DWORD cbSize; DWORD cbBlob; BYTE *pbBlob; }SIGNER_CONTEXT, *PSIGNER_CONTEXT; typedef struct _SIGNER_SIGN_EX2_PARAMS { DWORD dwFlags; PSIGNER_SUBJECT_INFO pSubjectInfo; PSIGNER_CERT pSigningCert; PSIGNER_SIGNATURE_INFO pSignatureInfo; PSIGNER_PROVIDER_INFO pProviderInfo; DWORD dwTimestampFlags; PCSTR pszAlgorithmOid; PCWSTR pwszTimestampURL; PCRYPT_ATTRIBUTES pCryptAttrs; PVOID pSipData; PSIGNER_CONTEXT *pSignerContext; PVOID pCryptoPolicy; PVOID pReserved; } SIGNER_SIGN_EX2_PARAMS, *PSIGNER_SIGN_EX2_PARAMS; typedef struct _APPX_SIP_CLIENT_DATA { PSIGNER_SIGN_EX2_PARAMS pSignerParams; IUnknown* pAppxSipState; } 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:
HRESULT SignAppxPackage( _In_ PCCERT_CONTEXT signingCertContext, _In_ LPCWSTR packageFilePath) { HRESULT hr = S_OK; // Initialize the parameters for SignerSignEx2 DWORD signerIndex = 0; SIGNER_FILE_INFO fileInfo = {}; fileInfo.cbSize = sizeof(SIGNER_FILE_INFO); fileInfo.pwszFileName = packageFilePath; SIGNER_SUBJECT_INFO subjectInfo = {}; subjectInfo.cbSize = sizeof(SIGNER_SUBJECT_INFO); subjectInfo.pdwIndex = &signerIndex; subjectInfo.dwSubjectChoice = SIGNER_SUBJECT_FILE; subjectInfo.pSignerFileInfo = &fileInfo; SIGNER_CERT_STORE_INFO certStoreInfo = {}; certStoreInfo.cbSize = sizeof(SIGNER_CERT_STORE_INFO); certStoreInfo.dwCertPolicy = SIGNER_CERT_POLICY_CHAIN_NO_ROOT; certStoreInfo.pSigningCert = signingCertContext; SIGNER_CERT cert = {}; cert.cbSize = sizeof(SIGNER_CERT); cert.dwCertChoice = SIGNER_CERT_STORE; cert.pCertStoreInfo = &certStoreInfo; // The algidHash of the signature to be created must match the // hash algorithm used to create the app package SIGNER_SIGNATURE_INFO signatureInfo = {}; signatureInfo.cbSize = sizeof(SIGNER_SIGNATURE_INFO); signatureInfo.algidHash = CALG_SHA_256; signatureInfo.dwAttrChoice = SIGNER_NO_ATTR; SIGNER_SIGN_EX2_PARAMS signerParams = {}; signerParams.pSubjectInfo = &subjectInfo; signerParams.pSigningCert = &cert; signerParams.pSignatureInfo = &signatureInfo; APPX_SIP_CLIENT_DATA sipClientData = {}; sipClientData.pSignerParams = &signerParams; signerParams.pSipData = &sipClientData; // Type definition for invoking SignerSignEx2 via GetProcAddress typedef HRESULT (WINAPI *SignerSignEx2Function)( DWORD, PSIGNER_SUBJECT_INFO, PSIGNER_CERT, PSIGNER_SIGNATURE_INFO, PSIGNER_PROVIDER_INFO, DWORD, PCSTR, PCWSTR, PCRYPT_ATTRIBUTES, PVOID, PSIGNER_CONTEXT *, PVOID, PVOID); // Load the SignerSignEx2 function from MSSign32.dll HMODULE msSignModule = LoadLibraryEx( L"MSSign32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); if (msSignModule) { SignerSignEx2Function SignerSignEx2 = reinterpret_cast<SignerSignEx2Function>( GetProcAddress(msSignModule, "SignerSignEx2")); if (SignerSignEx2) { hr = SignerSignEx2( signerParams.dwFlags, signerParams.pSubjectInfo, signerParams.pSigningCert, signerParams.pSignatureInfo, signerParams.pProviderInfo, signerParams.dwTimestampFlags, signerParams.pszAlgorithmOid, signerParams.pwszTimestampURL, signerParams.pCryptAttrs, signerParams.pSipData, signerParams.pSignerContext, signerParams.pCryptoPolicy, signerParams.pReserved); } else { DWORD lastError = GetLastError(); hr = HRESULT_FROM_WIN32(lastError); } FreeLibrary(msSignModule); } else { DWORD lastError = GetLastError(); hr = HRESULT_FROM_WIN32(lastError); } // Free any state used during app package signing if (sipClientData.pAppxSipState) { sipClientData.pAppxSipState->Release(); } return hr; }
备注
签署应用程序包后,您还可以尝试使用WINVUST_ACTION_GENERIC_VERIFY_V2的WinVerifyTrust函数以编程方式验证签名。对于在Windows Store应用程序包中使用WinVerifyTrust,在这种情况下没有特别注意事项。
如何以编程方式签署应用程序包(C ++)的更多相关文章
- ASP.NET MVC下的四种验证编程方式[续篇]
在<ASP.NET MVC下的四种验证编程方式>一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式("手工验证"."标注Validation ...
- ASP.NET MVC下的四种验证编程方式
ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效性,我们将针对参数的验证成为Model绑定 ...
- [转]Windows网络编程学习-面向连接的编程方式
直接附上原文链接:windows 网络编程学习-面向连接的编程方式
- C#通过编程方式实现Ping
代码是照着书敲的,贴出来方便平时参考 using System; using System.Collections.Generic; using System.Linq; using System.T ...
- ASP.NET MVC下的四种验证编程方式[续篇]【转】
在<ASP.NET MVC下的四种验证编程方式> 一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式(“手工验证”.“标注ValidationAttribute特性”.“ ...
- ASP.NET MVC下的四种验证编程方式【转】
ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效 性,我们将针对参数的验证成为Model绑 ...
- WCF编程系列(六)以编程方式配置终结点
WCF编程系列(六)以编程方式配置终结点 示例一中我们的宿主程序非常简单:只是简单的实例化了一个ServiceHost对象,然后调用open方法来启动服务.而关于终结点的配置我们都是通过配置文件来 ...
- CodeFirst 的编程方式
第一步:创建控制台项目第二步:添加新建项目→Ado.Net空实体模型第三步:添加实体:Customer,添加几个必要的测试字段第四步:添加实体之间的联系第五步:根据模型生成数据库脚本,并执行sql脚本 ...
- uglifyjs压缩js文件(指令压缩/ 批量压缩/ 编程方式压缩)
一.指令压缩 1.安装node,npm——详细见nodejs安装与使用入门 2.安装 uglifyjs——npm install -g uglify-js 3.压缩例子:1)uglifyjs mai ...
随机推荐
- How nginx "location if" works
Nginx's if directive does have some weirdness in practice. And people may misuse it when they do not ...
- box-shadow 详解及示例
box-shadow [bɑks] - [ˈʃædoʊ] 英文示意: box:盒,包厢 shadow:阴影,渐变 定义: box-shadow: none | <shadow> ...
- python如何优雅的打飞机
这是一个打飞机的游戏,结构如下: 其中images中包含的素材为 命名为alien.png 命名为ship.png 游戏效果运行是这样的: 敌军,也就是体型稍微大点的,在上方左 ...
- SimpleDateFormat安全的时间格式化
SimpleDateFormat安全的时间格式化 想必大家对SimpleDateFormat并不陌生.SimpleDateFormat 是 Java 中一个非常常用的类,该类用来对日期字符串进行解析和 ...
- backend_queue.go
package nsqd // BackendQueue represents the behavior for the secondary message // storage system typ ...
- 【LOJ #6094. 「Codeforces Round #418」归乡迷途】
题目大意: 传送门. lca说的很明白就不重复了. 题解: 先膜一发lca. 大体读完题以后我们可以知道对于第i个节点最短路一定是连向1到i-1中的某个点. 然后我们考虑将到1距离(这里及以下均是最短 ...
- Linux vim常用命令
什么是 vim? Vim是从 vi 发展出来的一个文本编辑器.代码补完.编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用. 简单的来说, vi 是老式的字处理器,不过功能已经很齐全了,但是 ...
- Java基础-递归调用
意义: 递归算法是一种直接或间接地调用自身的算法.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 所以在工作中我们经常用递归 来进行一些算法操作 比如 ...
- HTML——元素
HTML 元素 HTML 文档由 HTML 元素定义. HTML 元素 开始标签 * 元素内容 结束标签 * <p> 这是一个段落 </p> <a href=" ...
- 计算机17-1,2作业D
D.环形矩阵 Description 给定一个整数m,按m形成一个环形矩阵.如m=5,则环形矩阵为: 1 1 1 1 1 1 1 1 1 1 2 2 ...