如何以编程方式签署应用程序包(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 ...
随机推荐
- http请求 405错误 方法不被允许 (Method not allowed)
由于自己疏忽,导致请求错误405,然后前端数据传输没错,百度大都说跟post提交方式有关,改成get还是报错,检查才知道,controller中忘记写@requestMapping("/XX ...
- jQuery学习之旅 Item5 $与jQuery对象
1.$符号的由来 $符号本质就是函数的名字. jquery源码分析 通过分析我们知道,在jquery里边不只可以使用$符号,还可以使用jQuery标志 解决冲突问题 有的项目是中间过渡项目(proto ...
- 那些年我们一起清除过的浮动float与clearfix
浮动(float),一个我们即爱又恨的属性.爱,因为通过浮动,我们能很方便地布局: 恨,浮动之后遗留下来太多的问题需要解决,特别是IE6-7(以下无特殊说明均指 windows 平台的 IE浏览器). ...
- 学习ASP.NET Core Razor 编程系列十——添加新字段
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- 拯救莫莉斯 状压dp
题目大意:每个点有费用,要求选出花费最少的一些点,使得全部点都满足:他被选或与他相邻的任意点被选. 没看清数据范围233333 和翻格子游戏一样,考虑上中下三行,可行才能转移 f[i][j][k]表示 ...
- BZOJ_1654_[Usaco2007 Open]City Horizon 城市地平线_扫描线
BZOJ_1654_[Usaco2007 Open]City Horizon 城市地平线_扫描线 Description N个矩形块,交求面积并. Input * Line 1: A single i ...
- BZOJ_2795_[Poi2012]A Horrible Poem_hash+暴力
Description 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节. 如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. Input 第一行一个正 ...
- 在openjdk8下看Unsafe源码
尽管有传言JAVA9可能会移除Unsafe类,但不妨碍我们理解它的原理.因为类不在了,native方法还在那里.就像菜换样了,食材就那些没变.一个好厨师不仅仅需要会做菜,还需要能识别食材特性...来吧 ...
- Python的list用法笔记
今天做leetcode的str反转,学到了不少python的用法,这里做个笔记: str和list互相转换 str转list >>> a='apple' >>> l ...
- webpack下css/js/html引用图片的正确方式
在webpack的处理下,为了使引用的图片被打包编译(以把src的图片文件编译到dist中或者对src的文件进行base64编码),应使用如下引用方式: 1. 在html/ejs等中引用图片: 借助r ...