# ITMS-90034 签名缺失或无效：修复方法

> ITMS-90034 表示你的 build 没有用有效的分发证书签名。先用 codesign 查看签名，再用 EAS 重新构建 store build。

原始页面：[ITMS-90034 签名缺失或无效：修复方法](https://devoria.fr/zh-hans/blog/itms-90034-missing-or-invalid-signature-fix)
作者：[Mehdi Azizi](https://devoria.fr/zh-hans/mehdi-azizi)
发布：2026-11-04
内容最后修订：2026-11-04


ITMS-90034 出现在你把 build 上传到 App Store Connect 的时候。它的意思是：你的 app，或者其中某个组件，没有用 Apple 提交证书签名，也就是没有用有效的分发证书。**解决办法：找出是哪个 bundle 签错了、为什么签错，然后重新构建一个用于 App Store 的签名 build。**

这篇指南只讲这个错误。如果你对证书和描述文件这些概念还比较模糊，先读 [iOS 开发者证书和 provisioning profile](https://devoria.fr/zh-hans/blog/ios-certificate-provisioning-profile-expo)。这里你会看到：要读的报错信息、一棵决策树、检查 IPA 的命令，以及用 EAS 托管凭据的修复方法。EAS 这部分，我读过 EAS CLI 24.10.0 里选择证书的代码。

## ITMS-90034 错误是什么意思？

它的典型形式如下（名称是示例）：

> ITMS-90034: Missing or invalid signature. The bundle 'com.example.myapp' at bundle path 'Payload/MyApp.app' is not signed using an Apple submission certificate.

2026 年，在 Apple 论坛上，它也会以 "Validation failed (409) Missing or invalid signature" 的形式出现，后面跟着同样的文字和 "(ID: 90034)"。

所谓"提交证书"，就是分发证书。[Apple 关于证书的帮助文档](https://developer.apple.com/help/account/certificates/certificates-overview)写得很清楚：开发证书用来在你自己的设备上运行 app，分发证书用来分发 app 或上传到 App Store Connect。

**看报错里引用的路径：它指出了出问题的 bundle。** `Payload/MyApp.app` 指的是 app 本身。以 `.appex` 结尾的路径指的是扩展，比如小组件。以 `.framework` 结尾的路径指的是内嵌的库。

这不是审核员的拒绝。校验发生在上传时或 build 处理过程中，在 TestFlight 之前：这个 build 永远到不了你的测试人员手里。

## 决策树：从报错到修复

每一行对应一个线索，你可以在报错信息、下一节的命令或 EAS 日志里看到。按顺序看：第一条对上的就是你的方向。

| 你看到的现象              | 可能原因             | 修复方法          |
| ------------------------- | -------------------- | ----------------- |
| 路径以 `.appex` 结尾      | 扩展签名错误         | 声明该扩展        |
| `Signature=adhoc`         | build 未签名         | 用 store 配置构建 |
| `Apple Development`       | 开发 build           | 用 store 配置构建 |
| 读到 `ProvisionedDevices` | 内部 build（ad hoc） | 用 store 配置构建 |
| `sealed resource`         | IPA 构建后被改动     | 重新构建          |
| EAS："no longer valid"    | 证书已被吊销         | 新建证书          |
| 一切都有效                | Apple 那边的故障     | 重新上传，再反馈  |

## 用四条命令检查你的 IPA

从 expo.dev 上该 build 的页面下载 IPA，然后在你的 Mac 上打开终端。

**1. 是谁签的这个 app？**

```bash
unzip -q MyApp.ipa -d ipa
codesign -dv --verbose=4 ipa/Payload/*.app 2>&1 | grep -E "^(Identifier|Authority|Signature|TeamIdentifier)="
```

`codesign` 输出到标准错误，所以要加 `2>&1`。根据 [Apple 技术说明 TN3161](https://developer.apple.com/documentation/technotes/tn3161-inside-code-signing-certificates)，每一行 `Authority` 都是信任链中的一环。第一行应该以 `Apple Distribution:` 或 `iPhone Distribution:` 开头，后面是你团队的名称。第二种写法是旧的 iOS Distribution 类型：从代码来看，EAS CLI 24.10.0 仍然会创建这种类型的证书。如果你看到 `Apple Development:`，那就是开发 build。如果你看到 `Signature=adhoc` 而且没有任何 `Authority` 行，说明这个二进制没有被任何证书签名。

**2. app 签名之后被改过吗？**

```bash
codesign --verify --deep --strict -vv ipa/Payload/*.app
```

你希望看到 `valid on disk`，然后是 `satisfies its Designated Requirement`。TN3161 说明了这项检查保证什么：所有预期的文件都在，没有新增文件，也没有文件被修改。我拿一个测试 bundle 签名后再改动，这条命令返回 `a sealed resource is missing or invalid`，接着是 `file modified:` 加上被改的文件。这里的 `--deep` 选项只用来校验，绝不要用来签名：在 Apple 论坛上，一位技术支持团队的工程师就不建议用它签名。

**3. 内嵌的是哪个描述文件？**

```bash
security cms -D -i ipa/Payload/*.app/embedded.mobileprovision -o profil.plist
plutil -extract ProvisionedDevices xml1 -o - profil.plist
plutil -extract ExpirationDate raw profil.plist
```

这些命令来自 [关于描述文件的技术说明 TN3125](https://developer.apple.com/documentation/technotes/tn3125-inside-code-signing-provisioning-profiles)。App Store 描述文件不包含任何设备列表：第二行应该返回 `Could not extract value`。如果它显示了设备标识符，那就是 ad hoc 描述文件，也就是内部 build 用的。第三行给出描述文件的过期日期。

**4. 扩展和框架的签名一致吗？**

```bash
find ipa/Payload/*.app \( -name "*.appex" -o -name "*.framework" \) \
  -exec sh -c 'echo "$1"; codesign -dvv "$1" 2>&1 | grep -m1 "^Authority="' _ {} \;
```

每个组件都应该显示和 app 相同的 `Authority` 行。哪个不一样，报错里提到的就是它。

如果你想在上传前检查，TN3161 推荐用 `altool`，它和 Xcode 里 Validate App 按钮做的是同一项检查。它需要一个 App Store Connect API 密钥，密钥文件 `AuthKey_<KEY_ID>.p8` 要放在 `~/.appstoreconnect/private_keys` 里：

```bash
xcrun altool --validate-app -f MyApp.ipa -t ios --api-key <KEY_ID> --api-issuer <ISSUER_ID>
```

## 用 EAS 逐个原因修复

### 把内部 build 或开发 build 传给了 Apple

根据 [Expo 关于 eas.json 的文档](https://docs.expo.dev/build/eas-json/)，`"distribution": "internal"` 的 build 不是为商店签名的：它们用的是 ad hoc 描述文件。只有分发方式为 `store`（默认值）的配置才能生成可上传的 build。**最稳妥的做法是直接上传你刚构建好的 build，不要手动去挑**：

```bash
eas build --platform ios --profile production --auto-submit
```

如果你用 `eas submit --path`，确认这个文件确实是你最新的 store build。在 Apple 论坛上，有个团队发现他们的上传工具每次都传了一个放在 git 里的旧 IPA。

### 漏掉了某个扩展

每个扩展都是独立的 bundle，有自己的标识符和自己的描述文件。在使用原生代码生成的 Expo 项目里，[Expo 关于 iOS 扩展的页面](https://docs.expo.dev/build-reference/app-extensions/)要求在 `extra.eas.build.experimental.ios.appExtensions` 中声明它们。这样 EAS CLI 在构建前就知道它们，并会创建或校验它们的凭据。大多数会添加扩展的库都会通过自己的插件帮你写好这段声明。

Solys 是我做的小游戏闹钟，里面有四个扩展：一个小组件和三个 Screen Time（屏幕使用时间）扩展。四个都在配置里声明了，EAS 为每个都准备了描述文件。**如果某个扩展是在 Xcode 里手动加的，没有做这个声明，那它就是报错里出现 `.appex` 路径的头号嫌疑。**

### 证书被吊销或已过期

[Apple 关于证书的页面](https://developer.apple.com/support/certificates/)说得很明确：用过期或被吊销的证书签名的 build 不能再上传。一个已经上传但还没提交审核的 build，如果它的证书被吊销，甚至可能变成 Invalid Binary 状态。

EAS CLI 24.10.0 的代码显示了这种情况什么时候会被漏掉：

- **交互式构建，已连接 Apple**：EAS 会把它的证书和 Apple 那边仍然有效的证书对比。如果对不上，它会显示 "Current distribution certificate is no longer valid in Apple Dev Portal"，并让你选择或新建一个。
- **交互式构建，未连接**：EAS 只检查日期，并提示它跳过了 Apple 端的校验。
- **非交互式构建，在持续集成中**：EAS 显示 "Distribution Certificate is not validated for non-interactive builds"，然后照样签名。

**在持续集成里，EAS 不会再次校验证书本身：证书被吊销可能要到上传时才暴露。** 解决方法：运行一次连接你 Apple 账号的交互式构建，或者用 `eas credentials --platform ios`，进入 Build Credentials 菜单，再选 "Distribution Certificate: Add a new one to your account"。包含旧证书的描述文件会失效：EAS 会在下一次构建时检查并重新生成它们。Apple 对证书数量的限制，详见 [iOS 开发者证书指南](https://devoria.fr/zh-hans/blog/ios-certificate-provisioning-profile-expo)。

### 二进制在签名后被修改

签名通过哈希值把代码、资源和元数据封存起来，[Apple 技术说明 TN3126](https://developer.apple.com/documentation/technotes/tn3126-inside-code-signing-hashes) 有详细解释。解压 IPA 改一个文件再重新压缩，就会破坏这个封印。**在你的配置里做修改，然后重新构建。** 永远不要手动改 EAS 生成的 IPA。

代码放错位置也是同样的道理，比如放在 `.zip` 压缩包里：App Store 无法对它重新签名。Apple 在关于 [bundle 内容](https://developer.apple.com/documentation/bundleresources/placing-content-in-a-bundle)的页面里说明了允许的位置。

### 本地凭据

如果你的 EAS 配置用了 `"credentialsSource": "local"`，你的 `credentials.json` 文件会指向一个 `.p12` 证书和一个 `.mobileprovision` 描述文件。用第 3 步的命令检查描述文件：它必须是 App Store 类型，并且包含你当前的分发证书。另外，这些文件不要放进代码仓库，和 [Expo app 的 API 密钥](https://devoria.fr/zh-hans/blog/expo-api-secret-key-security)一样。

### 一切都有效的时候

还剩一种让人头疼的情况。在 Apple 论坛上，有开发者什么都没改，重新上传同一个 build，错误就消失了。2026 年 8 月和 9 月，有两个帖子描述了相反的情况：证书和描述文件都是新的，签名也验证过，还是一直失败。其中一个帖子里，一位 Apple 工程师建议提交 bug 报告，附上 IPA、签名分析和 Transporter 日志，然后联系 App Store Connect。

所以，先用新的 build 号重新上传一次。如果你的四条命令结果都没问题，错误还是出现，就带着这些材料向 Apple 反馈。**不要条件反射地去吊销证书**：这解决不了任何问题，还会让你的描述文件失效。

## 上传 build 不再踩坑

签名在上传前两分钟就能检查完。其他自动检查也需要同样严谨，比如 Xcode 版本相关的 [ITMS-90725](https://devoria.fr/zh-hans/blog/itms-90725-sdk-version-issue-expo)，或者权限说明文字相关的 [ITMS-90683](https://devoria.fr/zh-hans/blog/itms-90683-missing-purpose-string-expo)。从构建到上传、不用 Mac 的完整流程，见 [不用 Mac 发布 iOS app](https://devoria.fr/zh-hans/blog/publish-ios-app-without-mac-expo-eas)。

审核员的拒绝需要更冷静地处理：应对方法在 [app 被 Apple 拒绝](https://devoria.fr/zh-hans/expertise/app-rejected-by-apple)这一页，最常见的拒绝原因在 [Apple 为什么拒绝你的 app](https://devoria.fr/zh-hans/blog/apple-app-rejection-reasons-real-cases)。

想在上传前检查你的材料，[Review Kit](https://devoria.fr/zh-hans/kits/app-review) 里有我的检查清单，还有会帮你审查项目的 Claude Code skills。如果你的上传卡住了，想找个人帮你看看，[和我预约一小时](https://devoria.fr/zh-hans/coaching)：我们视频通话，在你的屏幕上一起过你的项目。如果你正在准备第一次发布，[做一下免费诊断](https://devoria.fr/zh-hans/diagnostic)：它会帮你理顺步骤顺序，并把我的防 Apple 拒审清单发给你。

## 常见问题

### ITMS-90034 是 App Review 的拒绝吗？

不是。这是上传 build 时的自动校验，发生在 TestFlight 之前，也在任何审核之前。没有人打开过你的 app：Apple 只是发现它的签名不是来自有效的分发证书。

### 修复 ITMS-90034 需要吊销我的分发证书吗？

只有在证书泄露或已经失效时才需要。吊销一个正常工作的证书会让你的描述文件失效，却不能解决根本原因。先用 `codesign` 查看 IPA 的签名，然后按决策树指出的问题去修。

### 能用远程更新修复 ITMS-90034 吗？

不能。签名是二进制的一部分，被拒的 build 永远无法使用。你必须生成一个正确签名的新二进制并重新上传。

### 为什么报错提到的是我的小组件，而不是我的 app？

因为小组件是独立的 bundle，用自己的描述文件签名。如果它没有向 EAS 声明，或者用别的方式签了名，整个上传都会失败。在配置里声明这个扩展，然后重新构建。

### 如果 codesign 显示一切有效怎么办？

再检查一下内嵌的描述文件和每个扩展。如果都没问题，用新的 build 号重新上传一次。如果错误还在，就向 Apple 提交报告，附上 IPA、`codesign` 的输出和上传日志。


## 你的项目

[Review Kit](https://devoria.fr/zh-hans/kits/app-review)：我的 App Store 审核清单、我被 Apple 拒审后的修正方案、Google Play 审核清单，以及三个 Claude Code skill。¥369。

[iOS & Android Kit](https://devoria.fr/zh-hans/kits/ios)：用 Claude Code 打造你的 iPhone 和 Android 应用：我自己应用的起步代码、上架商店的完整流程，以及全部工具包。¥739。

[诊断：你离自己的 iPhone 应用还差什么](https://devoria.fr/zh-hans/diagnostic)：7 个问题，60 秒：看清真正阻碍你发布 iPhone 应用的原因，拿到你的 4 步路线和适合你的套件。
