Tauri 自动更新签名密钥:它到底有什么用?怎么生成?以及一次真实踩坑复盘

5 阅读4分钟

适用场景:你在 Tauri 项目里启用了自动更新(updater),然后在 npm run tauri build 时遇到类似报错:
A public key has been found, but no private key. Make sure to set TAURI_SIGNING_PRIVATE_KEY environment variable.

本文会把事情讲清楚:

  • 为什么需要密钥(公钥/私钥)
  • 密钥怎么生成
  • pubkey 配在哪
  • 为什么会出现“有公钥没私钥”的构建报错
  • 如何用 PowerShell 正确构建
  • 一些最佳实践(密钥是否每次都要生成?怎么保存?怎么脚本化)

1. Tauri 自动更新的签名密钥是做什么的?

Tauri 的自动更新流程里,核心安全问题只有一个:

客户端下载到的更新包必须可信,不能被中间人篡改。

因此 Tauri 采用“签名验证”模型:

  • 发布者(你)用私钥(private key)对更新产物进行签名(生成 .sig 等签名文件)
  • 客户端(用户安装的 App)内置公钥(public key / pubkey)
  • 客户端下载更新后,用内置公钥验证签名:
    • 验证通过:允许安装更新
    • 验证失败:拒绝更新(防止被替换成木马包)

一句话总结:

  • 私钥:用来签名更新包(必须保密)
  • 公钥:打包进 App,用来验证更新包(可以公开)

2. 哪些配置会触发“构建时必须要私钥”?

当你同时满足以下条件时:

Tauri 在 tauri build 阶段会尝试生成“自动更新需要的产物”,同时会去做签名工作。

如果它发现:

  • 配了 pubkey(说明你要验证签名)
  • 但构建时没有拿到 private key

就会直接报错:

A public key has been found, but no private key. Make sure to set TAURI_SIGNING_PRIVATE_KEY environment variable.

这其实是一个“防呆保护”:你都声明要验证签名了,那构建产物就必须有签名


3. 密钥怎么生成?(一次生成,长期使用)

在项目根目录执行(PowerShell):

mkdir .tauri -Force | Out-Null

# 生成私钥文件:.tauri/update.key
# 过程会提示你输入密码(请记住)
npx tauri signer generate -w .tauri\update.key

# 输出对应公钥(复制结果,填到 tauri.conf.json 的 pubkey)
npx tauri signer public-key -f .tauri\update.key

重要结论:

  • 密钥只需要生成一次
  • 不需要每次打包都生成新的
  • 不建议频繁换密钥(换了密钥,旧版本内置的公钥就无法验证新签名,自动更新链可能断掉)

4. pubkey 配在哪?

位置:src-tauri/tauri.conf.json

常见结构如下(仅示意):

{
  "bundle": {
    "createUpdaterArtifacts": true
  },
  "plugins": {
    "updater": {
      "pubkey": "你刚生成的公钥字符串",
      "endpoints": [
        "https://xxx/latest.json"
      ]
    }
  }
}

5. 我遇到的情况:为什么会报“有公钥没私钥”?

我当时的配置已经有:

  • plugins.updater.pubkey(公钥)
  • bundle.createUpdaterArtifacts: true

因此 Tauri 构建时必须进行签名。

但我的构建环境里没有提供私钥内容(也就是没设置环境变量),所以构建直接失败。


6. 解决方案:构建前设置签名环境变量(PowerShell)

关键点:

  • TAURI_SIGNING_PRIVATE_KEY 不是填路径,而是私钥文件内容
  • 建议用 -Raw,确保读取为完整字符串(避免换行导致读取成数组)
$env:TAURI_SIGNING_PRIVATE_KEY = Get-Content .tauri\update.key -Raw
$env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD = "xxxxx"

npm run tauri build

这样构建就能成功,并且你会在构建产物中看到类似:

  • xxx-setup.exe
  • xxx-setup.exe.sig

.sig 就是用于自动更新校验的签名文件。


7. 最佳实践:如何管理密钥(别翻车)

7.1 私钥绝对不要提交到 git

.gitignore 建议至少包含:

.tauri/update.key
.tauri/*.key

公钥可以公开,但一般也无需提交 .pub 文件,真正用到的是 tauri.conf.json 里的 pubkey 字符串。

7.2 密钥不要每次生成新的

  • 同一条更新链必须使用同一套密钥
  • 换钥意味着客户端内置的公钥也要更新
    而“更新公钥”本身又依赖自动更新链能跑通 —— 容易形成死锁

7.3 别把密码硬编码进仓库

你可以在本机 PowerShell 会话里临时设置(窗口关了就消失),更安全。


8. 进阶:把构建命令脚本化(Windows 推荐 ps1,不要用 sh)

有些同学会写 build.sh 然后 sh build.sh,但在 Windows 上通常没有 sh 环境,容易报:

sh : 无法将“sh”项识别为 cmdlet...

更推荐用 build.ps1(并把它加入 .gitignore)。

示例 build.ps1

$env:TAURI_SIGNING_PRIVATE_KEY = Get-Content .tauri\update.key -Raw
$env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD = "xxxxx"
npm run tauri build

执行:

.\build.ps1

结语

启用 Tauri 自动更新后,“签名密钥”不是可选项,而是安全链路的核心组成部分:

  • 公钥写进 App:用于校验更新
  • 私钥留在发布端:用于签名更新包
  • 构建时没给私钥:就会报“有公钥没私钥”的错误

按本文步骤生成一次密钥,并在每次构建前提供私钥环境变量,就能稳定产出带签名的更新构建产物。