欢迎光临
我们一直在努力

茶器艺科智造HarmonyOS应用实战-07-build-profile把证书路径和口令写进仓库,换台电脑为何立刻失效:拆分签名引用与本机材料

茶器艺科智造HarmonyOS应用实战-07-build-profile把证书路径和口令写进仓库,换台电脑为何立刻失效:拆分签名引用与本机材料

同一份 HarmonyOS 工程在原开发机上可以选择默认签名,交给另一位同事后却立刻提示证书文件不存在,最容易被误判成 DevEco Studio 版本不同。真正需要先看的,是项目根目录的 build-profile.json5:如果这里同时保存了绝对文件路径、证书库口令、私钥口令、别名、Profile 与证书路径,工程就把“可复用构建配置”和“只属于某台机器的材料”焊在了一起。Git 能复制文本,却不会复制盘符、凭据、账号授权和设备关系。

本文以当前源码快照 master@f671fcd 为依据。源码事实只描述字段与引用;所有秘密值统一写成 [REDACTED_SECRET],本机路径改成示意路径。文中不会给出真实口令,也不会公布能定位当前证书材料的真实目录。

签名材料分层封面

本文解决四个具体问题:

  • 从根配置识别可移植规则与本机材料;
  • 解释换机失败发生在文件、解锁、身份还是用途层;
  • 用安全模板、本机注入和流水线秘密库划清提交边界;
  • 用不打印秘密的预检与验证矩阵留下可审计证据。

签名材料分层流程

签名材料工程结构

一、当前源码把四类本机条件集中在根配置

当前源码已存在的事实很明确:根 build-profile.json5 的 app.signingConfigs 数组包含名为 default 的 HarmonyOS 签名项;material 中出现 storeFile、storePassword、keyAlias、keyPassword、signAlg、profile、certpath。default 产品又通过 signingConfig 引用这个签名项。三条文件字段使用绝对路径,两个 password 字段在文件中有具体值。

下面只保留字段形态,不保留当前值:

{
"app": {
"signingConfigs": [{
"name": "default",
"type": "HarmonyOS",
"material": {
"storeFile": "D:/[LOCAL_CERT_DIR]/chaqi-signing.p12",
"storePassword": "[REDACTED_SECRET]",
"keyAlias": "local-signing-alias",
"keyPassword": "[REDACTED_SECRET]",
"signAlg": "SHA256withECDSA",
"profile": "D:/[LOCAL_CERT_DIR]/chaqi-debug-profile.p7b",
"certpath": "D:/[LOCAL_CERT_DIR]/chaqi-public-cert.cer"
}
}],
"products": [{
"name": "default",
"signingConfig": "default",
"targetSdkVersion": "6.0.2(22)",
"compatibleSdkVersion": "6.0.2(22)",
"runtimeOS": "HarmonyOS"
}]
}
}

这段结构能证明“配置引用已经存在”,不能证明另一台机器拥有相同材料,更不能证明这些材料适合 release。产品名、SDK 与签名项逻辑名属于工程规则;证书库、Profile、证书和口令则受机器、账号、设备、渠道与用途约束。

当前字段当前表现换机后的典型结果建议归属
signingConfig default 产品引用 default 名字仍可解析 可提交引用
storeFile 本机绝对路径 文件不存在或目录不同 本机/流水线材料
storePassword 文件中有具体值 即使复制证书库也不应扩散 秘密库
keyAlias 指向证书库条目 新证书库找不到同名项 环境元数据
keyPassword 文件中有具体值 私钥无法解锁 秘密库
profile 本机绝对路径 设备或应用身份可能不匹配 受控制品
certpath 本机绝对路径 文件缺失或证书链不一致 受控制品

二、换机失效是一条四层故障链

排查时不要只盯着第一条“file not found”。第一层是 定位失败:盘符与目录不一致,绝对路径只在原机器成立。第二层是 材料失败:复制 p12、p7b、cer 后,Profile 仍可能与新设备、应用标识或证书关系不符。第三层是 解锁失败:两个口令必须分别对应正确的证书库和私钥。第四层是 用途失败:能签本地 Debug 包的材料,不自动成为商店发布材料。

建议先定义一个不含秘密的预检回执:

type SigningPreflightCode =
| 'CONFIG_REFERENCE_MISSING'
| 'STORE_FILE_MISSING'
| 'PROFILE_FILE_MISSING'
| 'CERT_FILE_MISSING'
| 'SECRET_NOT_INJECTED'
| 'READY_FOR_BUILD';

interface SigningPreflightReceipt {
code: SigningPreflightCode;
signingConfigName: string;
checkedFileKinds: string[];
secretsReady: boolean;
// message 只能写问题类别,不能拼入口令或真实路径
message: string;
}

构建日志需要知道哪类输入没准备好,不需要知道输入值。发布台账需要知道使用了哪个逻辑签名策略,不应保存可直接解锁私钥的材料。这两个边界一旦混在一起,错误处理本身就可能成为第二条泄露通道。

三、仓库保存规则,本机保存可直接使用的材料

可提交内容的判断标准,是团队成员能否在不接触个人秘密时理解工程。modules、products、buildModeSet、SDK、签名算法要求、占位字段、准备脚本和操作说明都属于可复用规则。真实 p12、口令、账号约束的 Profile、机器绝对路径不属于这一层。

内容Git 中是否保留理由
modules、products、buildModeSet 决定工程结构和模式
签名项逻辑名称 让产品引用稳定
安全模板与占位符 让缺失项可读、可阻断
真实 p12 与两个口令 具有直接签名能力
真实 p7b、cer 默认否 与账号、设备、证书链及流程有关
绝对本机目录 不可移植,还暴露环境结构
预检脚本 在进入构建前阻断错误
制品摘要与 commit 是或进入受控台账 可追溯且不含秘密

本文建议把本机生成结果和材料目录加入忽略清单。它不是当前源码已经具备的方案,落地前应先确认 DevEco Studio 与流水线究竟读取哪个配置文件。

#本文建议:本机渲染结果与材料目录
build-profile.local.json5
.local-signing/
*.p12
*.p7b

#cer 是否进入仓库取决于组织证书策略。
#若不提交,应由受控制品库分发。

忽略规则只阻止新的未跟踪文件加入,不能清除历史提交。若秘密曾进入 Git,简单删除当前行不足以完成处置;需要由账号和证书负责人判断吊销、轮换、历史治理与协作者重新同步范围。

四、安全模板只表达字段契约

一种可执行的迁移路径,是保留 build-profile.safe.json5 作为规则源,用明显占位符表达环境输入;准备脚本再生成只属于当前作业的工作副本。团队必须明确实际构建如何消费工作副本,不能假定 Hvigor 会自动读取任意文件名。

{
"app": {
"signingConfigs": [{
"name": "local",
"type": "HarmonyOS",
"material": {
"storeFile": "@@STORE_FILE@@",
"storePassword": "@@STORE_PASSWORD@@",
"keyAlias": "@@KEY_ALIAS@@",
"keyPassword": "@@KEY_PASSWORD@@",
"signAlg": "SHA256withECDSA",
"profile": "@@PROFILE_FILE@@",
"certpath": "@@CERT_FILE@@"
}
}],
"products": [{
"name": "default",
"signingConfig": "local",
"targetSdkVersion": "6.0.2(22)",
"compatibleSdkVersion": "6.0.2(22)",
"runtimeOS": "HarmonyOS"
}]
}
}

占位符不应换成空字符串。空值会把“输入缺失”拖到更晚的签名阶段,使错误远离根因。模板还要完整保留当前 modules 和 buildModeSet;示例为突出签名边界而省略的部分,不能在真实迁移时顺手删除。

五、输入脚本在写文件前失败,而且不回显值

本机可以从进程环境、Windows 凭据设施或团队允许的秘密管理方案读取值。无论来源是什么,脚本都应先核对键是否齐全,再核对三类文件是否存在,最后才渲染工作副本。

$required = @{
STORE_FILE = $env:CHAQI_STORE_FILE
STORE_PASSWORD = $env:CHAQI_STORE_PASSWORD
KEY_ALIAS = $env:CHAQI_KEY_ALIAS
KEY_PASSWORD = $env:CHAQI_KEY_PASSWORD
PROFILE_FILE = $env:CHAQI_PROFILE_FILE
CERT_FILE = $env:CHAQI_CERT_FILE
}

$missing = @($required.Keys | Where-Object {
[string]::IsNullOrWhiteSpace($required[$_])
})
if ($missing.Count -gt 0) {
throw "Signing inputs are missing: $($missing -join ', ')"
}

foreach ($fileKey in 'STORE_FILE', 'PROFILE_FILE', 'CERT_FILE') {
if (-not (Test-Path LiteralPath $required[$fileKey] PathType Leaf)) {
throw "Signing file is unavailable: $fileKey"
}
}
Write-Host 'Signing inputs are present; values are not printed.'

这段示例只证明输入存在,不证明口令正确、证书有效或用途匹配。真实渲染还应给临时文件设置合适权限,异常时删除半成品,并在作业结束后清理。绝不能为排错把 $required 整个输出。

六、路径只在边界处规范化,仓库不猜盘符

路径注入要处理三个细节:通过 GetFullPath 固定语义;只允许落在团队约定的本机材料根或作业临时目录;用 LiteralPath 读取,避免方括号等字符被解释成通配符。

$repoRoot = [IO.Path]::GetFullPath((Get-Location).Path)
$materialRoot = [IO.Path]::GetFullPath($env:CHAQI_SIGNING_HOME)
$storeFile = [IO.Path]::GetFullPath($env:CHAQI_STORE_FILE)

if (-not $storeFile.StartsWith(
$materialRoot,
[StringComparison]::OrdinalIgnoreCase
)) {
throw 'STORE_FILE must stay inside CHAQI_SIGNING_HOME.'
}

if ($storeFile.StartsWith(
$repoRoot,
[StringComparison]::OrdinalIgnoreCase
)) {
throw 'Signing material must not be stored inside the repository.'
}

目标不是让所有同事使用相同盘符,而是让 CHAQI_SIGNING_HOME 成为每台机器自己的契约。仓库认识环境键和材料类别,不认识某位开发者的磁盘布局。路径可以变化,产品对签名策略的逻辑引用保持稳定。

七、提交前同时扫描具体值、绝对路径与材料文件

只搜索 password 不够,绝对路径同样会破坏可移植性。建议的提交前扫描至少覆盖:敏感字段出现非占位值;签名文件字段含 Windows 盘符;p12、p7b 被加入暂存区;脚本日志打印完整 material 对象。

$profile = Get-Content LiteralPath '.\\build-profile.safe.json5' Raw
$problems = [System.Collections.Generic.List[string]]::new()

if ($profile -match '"(storePassword|keyPassword)"\\s*:\\s*"(?!@@)[^"]+"') {
$problems.Add('A password field contains a concrete value.')
}
if ($profile -match '"(storeFile|profile|certpath)"\\s*:\\s*"[A-Za-z]:[/\\\\]') {
$problems.Add('A signing path is machine absolute.')
}

$staged = git diff cached name-only
if ($staged -match '\\.(p12|p7b)$') {
$problems.Add('A signing material file is staged.')
}

if ($problems.Count -gt 0) {
$problems | ForEach-Object { Write-Error $_ }
exit 1
}
Write-Host 'Repository signing boundary is clean.'

扫描输出只列问题类别。不要为了方便而打印匹配行,因为匹配行可能正是秘密。还要记住:看起来像长串编码的 password 字段,只要能被当前工具直接使用,就仍应按秘密处理;不能以“肉眼不可读”为公开理由。

八、流水线材料必须有完整生命周期

CI 与开发机的差别只是材料来源,安全边界相同。流水线从秘密管理服务读取口令,从受控制品库取证书文件,写入作业专属临时目录,构建结束后清理。不要把 Base64 证书写回仓库变量文件,也不要把渲染后的完整 build-profile 当作普通制品上传。

steps:
name: preparesigning
run: |
create-job-private-directory
fetch-signing-files-with-access-control
inject-signing-secrets-with-masking
render-local-build-profile
run-signing-preflight

name: buildreleasecandidate
run: |
invoke-approved-hvigor-command

name: collectsafeevidence
run: |
record-commit-and-artifact-digest
record-signing-config-logical-name

name: cleanup
if: always()
run: |
remove-job-private-directory
remove-rendered-local-profile

这是平台无关的流程骨架,并未声称这些伪命令能直接运行。不同 CI 的秘密遮罩、临时目录和失败回调语义不同,需要在自己的平台核对。安全证据包含 commit、模式、SDK、逻辑签名名、制品 SHA-256 和时间;不包含口令、私钥或完整配置。

九、验证矩阵同时守住可移植性与保密性

迁移分支至少要覆盖以下场景。每项只保存通过状态或阻断原因,不保存输入值。

场景准备条件预期可保存证据
原开发机输入齐全 本机材料可读 预检通过,进入构建命令 commit、逻辑签名名、退出码
新机器没有材料 只克隆仓库 构建前明确阻断 缺失键名
新机器路径写错 环境键指向不存在文件 报文件类别缺失 STORE/PROFILE/CERT 类别
口令未注入 文件存在,secret 为空 渲染前阻断 SECRET_NOT_INJECTED
模板出现绝对路径 人为写入盘符 提交前扫描失败 规则编号与文件名
暂存 p12/p7b 材料进入暂存区 提交前扫描失败 扩展名与暂存项
Debug 材料用于 release 用途选择错误 发布门禁阻断 用途策略编号
作业异常退出 构建中断 cleanup 仍执行 临时目录已移除
制品归档 构建完成 只归档安全摘要 SHA-256、模式、commit

若没有第二台干净机器,可先用新的 Windows 账户或隔离目录模拟“没有原盘符与缓存”,但这仍不等价于真实协作者环境。可移植性最终要由独立机器实际跑通准备链路来确认。

十、排查表与证据边界

现象优先核对常见根因处理方向
storeFile 不存在 环境键与文件存在性 路径来自原机器 设置本机材料根,不改安全模板
证书库存在但不能签 秘密来源是否对应 两个口令或证书库不匹配 由材料负责人重新注入,日志不打印
找不到 keyAlias 受控别名元数据 别名与证书库不一致 核对正确材料,避免公开遍历结果
Profile 不接受设备 Profile 用途与设备关系 复制他人的 Debug Profile 为当前账号与设备准备
模板仍被扫描阻断 占位格式、绝对路径 遗留具体值 逐字段替换并复核 Git diff
新机器仍需改跟踪文件 工作副本未接入构建入口 只拆文件,没统一命令 固定 prepare 与 build 入口
CI 日志出现秘密 命令回显与异常对象 未遮罩或输出完整配置 停止扩散并轮换相关凭据
删除当前值仍有风险 Git 历史与旧制品 只清理工作树 走吊销、轮换和历史治理

当前源码已存在: master@f671fcd 的根 build-profile.json5 包含 default 签名项;material 同时出现三条绝对文件路径、两个具体口令字段、别名与算法;default 产品引用该签名项。根配置还声明 API 22、HarmonyOS runtime、debug/release 模式以及 entry、libraryhsp、libraryhar 三个模块。

本文建议: 安全模板、本机或流水线注入、提交前扫描、临时材料目录与发布证据台账。示例没有写回项目。

尚未证明: 本文未修改项目源码,未运行 hvigorw,未验证任何口令,未生成 HAP/APP,未在真机安装,也未提交 AppGallery。静态源码核对只能证明风险形态,不能证明某套签名材料当前有效。真正改造时,应先由有权限的负责人处理凭据,再在独立机器按矩阵复核。

签名配置可移植的标志,是仓库在没有秘密时仍能完整表达规则,每个环境只在受控边界内补齐自己的材料,并且失败信息不会把秘密带进日志。

赞(0)
未经允许不得转载:171主机测评 » 茶器艺科智造HarmonyOS应用实战-07-build-profile把证书路径和口令写进仓库,换台电脑为何立刻失效:拆分签名引用与本机材料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址