同步操作将从 OpenHarmony/docs 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
当需要验证调试应用、发布应用,OpenHarmony自签名应用的完整性是否被破坏时,可以调用验签组件的接口进行验证。如有需要还可通过验签接口获取部分描述文件信息,如appid。对于调试应用,还可通过验签接口验证应用和设备的UDID是否匹配,确保应用安装在了正确的设备上。
未经签名的Hap包的压缩方式是ZIP格式,简单分为文件块,中心目录(Central directory)块,中心目录结尾(EOCD,End of central directory record)块。
经过签名的Hap包,在文件块,和中心目录块之间,插入了签名块。签名块由文件签名数据块(data sign block)、描述文件签名数据块(profile sign block)和签名头(sign head)组成,如下图所示。
整个验签流程,主要分为三部分:整包验签、描述文件签名块验签,以及描述文件内容校验。
整包验签
用设备的预置根证书,通过证书链来证明叶子证书本身是可信的,然后用叶子证书的公钥解密出的摘要证明整包是未篡改的。
具体操作步骤如下:
描述文件签名块验签
首先判断文件签名的签发单位,如果是应用市场签发的发布应用,则无需对描述文件进行验签,直接信任,否则要对其验签。先取出整个描述文件签名块,然后验证证书链,最后用叶子证书对描述文件数据块验签,证明其未被篡改。
描述文件内容校验
取出描述文件,并对其内容进行合法性检查。其中若hap包为调试应用,则会比对本机UDID与描述文件中包含的UDID列表,如果本机UDID在描述文件的UDID列表中包含,则验证通过。比较描述文件中包含的证书(如果是应用市场发布应用或OpenHarmony自签名则无需比较),和整包校验时使用的叶子证书,如果相同,认为整个验签流程完成。
验签组件当前提供innerkits接口,仅供系统应用调用,相关接口及功能描述如下:
表 1 验签组件API接口功能介绍
int APPVERI_AppVerify(const char *filePath, VerifyResult *verifyRst) |
|
设置测试模式,设置mode为true,则支持基于测试根密钥的证书链校验,设置mode为false,则关闭基于测试根密钥的证书链校验。 |
|
对应用市场发布应用、基于应用市场调试证书签发的调试应用、OpenHarmony自签名应用的校验。
定义出参结构体变量VerifyResult;
VerifyResult verifyResult = {0};
以文件路径及VerifyResult为入参,调用APPVERI_AppVerify进行文件校验;
int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult);
判断返回结果,如果校验通过的话,获取VerifyResult中的数据,进行业务处理;
signatureInfo.appId = verifyResult.profile.appid;
signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName;
调用APPVERI_FreeVerifyRst,释放VerifyResult中申请的内存。
APPVERI_FreeVerifyRst(&verifyResult);
如果是OpenHarmony自签名应用的校验,开发者可通过以下方式生成OpenHarmony自签名应用。
材料备齐。
生成自签名应用需要的材料有:签名工具、系统应用hap包、系统应用profile文件(*.p7b)、签名证书(*.cer)、签名公私钥对(*.jks)。
将所有材料放在同一个目录下,打开shell。
根据应用、描述文件的实际名称修改指令,并在shell中输入,完成签名。
java -jar hapsigntoolv2.jar sign -mode localjks -privatekey "OpenHarmony Software Signature" -inputFile camera.hap -outputFile signed_camera.hap -signAlg SHA256withECDSA -keystore OpenHarmony.jks -keystorepasswd 123456 -keyaliaspasswd 123456 -profile camera_release.p7b -certpath OpenHarmony.cer -profileSigned 1
关键字段说明:
-jar:签名工具,hapsigntool
-mode:本地签名标记位,固定为localjks
-privatekey:密钥对别名,签名公私钥对的别名为OpenHarmony Software Signature
-inputFile:待签名应用,通过编译产生
-outputFile:签名后应用,最终输出
-signAlg:签名算法,当前固定为SHA256withECDSA
-keystore:公私钥对,使用签名公私钥对,位于开源库security_services_app_verify仓中OpenHarmonyCer目录下,OpenHarmony.jks。默认密码为123456 ,用户可采用工具(例如keytool)更改默认密码
-keystorepasswd:公私钥对密码,默认签名公私钥对密码为123456
-keyaliaspasswd:公私钥对别名密码,默认签名公私钥对别名密码为123456
-profile:描述文件,应用的描述文件位于对应源代码目录中
-certpath:使用签名证书,位于开源库security_services_app_verify仓中OpenHarmonyCer目录下,OpenHarmony.cer
-profileSigned:签名块中是否包含描述文件(profile)。固定为1(包含)
以应用管理框架组件在应用安装时进行验签的实际调用为例:
uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo)
{
bool mode = ManagerService::GetInstance().IsDebugMode();
HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode);
// 定义结果结构体
VerifyResult verifyResult = {0};
// 输入待验签文件路径进行验签
int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult);
uint8_t errorCode = SwitchErrorCode(ret);
if (errorCode != ERR_OK) {
return errorCode;
}
// 从结果结构体中获取appid
signatureInfo.appId = verifyResult.profile.appid;
// 从结果结构体中获取描述文件中书写的应用名
signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName;
int32_t restricNum = verifyResult.profile.permission.restricNum;
for (int32_t i = 0; i < restricNum; i++) {
signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]);
}
// 释放结果结构体中申请的内存
APPVERI_FreeVerifyRst(&verifyResult);
return ERR_OK;
}
对采用基于测试根密钥证书签名的应用的校验。
调用APPVERI_SetDebugMode(true)开启测试模式;
ManagerService::SetDebugMode(true);
...
uint8_t ManagerService::SetDebugMode(bool enable)
{
int32_t ret = APPVERI_SetDebugMode(enable);
if (ret < 0) {
HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed");
return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR;
}
isDebugMode_ = enable;
HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_);
return ERR_OK;
}
同场景一中步骤一至四,定义结构体,校验、释放结构体;
调用APPVERI_SetDebugMode(false)关闭测试模式。
ManagerService::SetDebugMode(false);
完整开发示例如下(在场景一代码示例的基础上进行补充):
uint8_t ManagerService::SetDebugMode(bool enable)
{
int32_t ret = APPVERI_SetDebugMode(enable);
if (ret < 0) {
HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed");
return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR;
}
isDebugMode_ = enable;
HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_);
return ERR_OK;
}
uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo)
{
// 开启支持测试服务器签名应用验证
ManagerService::SetDebugMode(true);
bool mode = ManagerService::GetInstance().IsDebugMode();
HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode);
// 定义结果结构体
VerifyResult verifyResult = {0};
// 输入待验签文件路径进行验签
int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult);
uint8_t errorCode = SwitchErrorCode(ret);
if (errorCode != ERR_OK) {
return errorCode;
}
// 从结果结构体中获取appid
signatureInfo.appId = verifyResult.profile.appid;
// 从结果结构体中获取描述文件中书写的应用名
signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName;
int32_t restricNum = verifyResult.profile.permission.restricNum;
for (int32_t i = 0; i < restricNum; i++) {
signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]);
}
// 释放结果结构体中申请的内存
APPVERI_FreeVerifyRst(&verifyResult);
// 关闭支持测试服务器签名应用验证
ManagerService::SetDebugMode(false);
return ERR_OK;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。