Signing a macOS app签署macOS应用程序

Code signing is a security technology that you use to certify that an app was created by you.代码签名是一种安全技术,用于证明应用程序是由您创建的。

On macOS, there are two layers of security technology for application distribution: code signing and notarization.在macOS上,应用程序分发有两层安全技术:代码签名公证

From macOS 10.15 (Catalina) onwards, your application needs to be both code signed and notarized to run on a user's machine without disabling additional operating system security checks.从macOS 10.15(Catalina)起,您的应用程序需要经过代码签名和公证才能在用户的机器上运行,而无需禁用额外的操作系统安全检查。

The exception is for Mac App Store (MAS) apps, where notarization is not required because the MAS submission process involves a similar automated check.Mac应用商店(MAS)应用程序除外,因为MAS提交过程涉及类似的自动检查,因此不需要公证。

Prerequisites先决条件

Installing 安装Xcode

Xcode is Apple's integrated development environment (IDE) for development on macOS, iOS, and other platforms.是苹果的集成开发环境(IDE),用于在macOS、iOS和其他平台上进行开发。

Although Electron does not integrate tightly with the IDE itself, Xcode is a helpful tool for installing code signing certificates (see next section) and is required for notarization.尽管Electron与IDE本身没有紧密集成,但Xcode是安装代码签名证书的一个有用工具(见下一节),并且是公证所必需的。

Obtaining signing certificates获取签名证书

Code signing certificates for macOS apps can only be obtained through Apple by purchasing a membership to the Apple Developer Program.macOS应用程序的代码签名证书只能通过购买苹果开发者计划的会员资格通过苹果获得。

To sign Electron apps, you may require two separate certificates:要签署Electron应用程序,您可能需要两个单独的证书:

Once you have an Apple Developer Program membership, you first need to install them onto your machine. 一旦你拥有了苹果开发者计划的会员资格,你首先需要将它们安装到你的机器上。We recommend loading them through Xcode.我们建议通过Xcode加载它们

Verifying your certificate is installed验证您的证书是否已安装

Once you have installed your certificate, you can check available code signing certificates in your terminal using the following shell command:安装证书后,可以使用以下shell命令在终端中检查可用的代码签名证书:

security find-identity -p codesigning -v

Configuring 配置Forge

In Electron Forge, macOS apps are signed and notarized at the Package step by the electron-packager library. 在Electron Forge中,macOS应用程序在打包步骤由electron-packager库进行签名和公证。There is a separate option within your Forge packagerConfig for each one of these settings.在您的ForgepackagerConfig中,每个设置都有一个单独的选项。

osxSign optionsosxSign选项

Under the hood, Electron Forge uses the @electron/osx-sign tool to sign your macOS application.在引擎盖下,Electron Forge使用@electron/osx-sign工具为您的macOS应用程序签名。

To enable code signing on macOS, ensure that packagerConfig.osxSign exists in your Forge configuration.要在macOS上启用代码签名,请确保您的Forge配置中存在packagerConfig.osxSign

module.exports = {
  packagerConfig: {
    osxSign: {} // object must exist even if empty
  }
};

The osxSign config comes with defaults that work out of the box in most cases, so we recommend you start with an empty configuration object.osxSign配置附带的默认值在大多数情况下都是开箱即用的,因此我们建议您从一个空的配置对象开始。

For a full list of configuration options, see the OsxSignOptions type in the Forge API docs. 有关配置选项的完整列表,请参阅Forge API文档中的OsxSignOptions类型。For more detailed information on how to configure these options, see the @electron/osx-sign documentation.有关如何配置这些选项的更多详细信息,请参阅@electron/osx-sign文档

Customizing entitlements自定义权利

A common use case for modifying the default osxSign configuration is to customize its entitlements. 修改默认osxSign配置的一个常见用例是自定义其权限。In macOS, entitlements are privileges that grant apps certain capabilities (e.g. access to the camera, microphone, or USB devices). 在macOS中,授权是授予应用程序某些功能的特权(例如访问相机、麦克风或USB设备)。These are stored within the code signature in an app's executable file.这些存储在应用程序的可执行文件中的代码签名中。

By default, the @electron/osx-sign tool comes with a set of entitlements that should work on both MAS or direct distribution targets. 默认情况下,@electron/osx-sign签名工具附带一组权限,这些权限应适用于MAS或直接分发目标。See the complete set of default entitlement files on GitHub.请参阅GitHub上的一整套默认权利文件。

module.exports = {
  // ...
  packagerConfig: {
    // ...
    osxSign: {
      optionsForFile: (filePath) => {
        // Here, we keep it simple and return a single entitlements.plist file.在这里,我们保持简单,并返回一个authoritysplist文件。
        // You can use this callback to map different sets of entitlements to specific files in your packaged app.您可以使用此回调将不同的权限集映射到打包应用程序中的特定文件。
        return {
          entitlements: 'path/to/entitlements.plist'
        };
      }
    }
  }
  // ...
};

For further reading on entitlements, see the following pages in Apple developer documentation:有关权利的进一步阅读,请参阅Apple开发人员文档中的以下页面:

osxNotarize options选项

Under the hood, Electron Forge uses the @electron/notarize tool to notarize your macOS application.在引擎盖下,Electron Forge使用@electron/notarize工具来公证您的macOS应用程序。

The osxNotarize configuration object can be set up to either use the legacy or notarytool strategies. osxNotarize配置对象可以设置为使用遗留legacynotarytool策略。If you are using Xcode 13 or higher, we strongly recommend using notarytool. 如果您使用的是Xcode 13或更高版本,我们强烈建议您使用notarytoolThe legacy tooling will be removed when Apple sunsets altool (projected for Fall 2023).当苹果日落altool(预计2023年秋季)时,legacy工具将被移除。

The notarytool command has three authentication options, which are detailed below. notarytool命令有三个身份验证选项,详细信息如下。Note that you will want to use a forge.config.js configuration so that you can load environment variables into your Forge config.请注意,您需要使用forge.config.js配置,以便将环境变量加载到Forge配置中。

Keep your authentication details private将您的身份验证详细信息保密

You should never store authentication info in plaintext in your configuration. 您不应该在配置中以明文形式存储身份验证信息。In the examples below, credentials are stored as environment variables and accessed via the Node.js process.env object.在下面的示例中,凭据存储为环境变量,并通过process.env对象进行访问。

Option 1: Using an app-specific password选项1:使用特定于应用程序的密码

You can generate an app-specific password from Apple to provide your credentials to notarytool. 你可以从苹果公司生成一个特定于应用程序的密码,向notarytool提供你的凭据。This password will need to be regenerated if you change your Apple ID password.如果您更改Apple ID密码,则需要重新生成此密码。

There are two mandatory fields for osxNotarize if you are using this strategy:如果使用此策略,osxNotarize有两个必填字段:

Field字段Type类型Description描述
appleIdstringApple ID associated with your Apple Developer account与您的Apple Developer帐户关联的Apple ID
appleIdPasswordstringApp-specific password应用程序特定密码
teamIdstringThe Apple Team ID you want to notarize under. 您要在下面进行公证的Apple Team ID。You can find Team IDs for team you belong to by going to https://developer.apple.com/account/#/membership您可以通过访问https://developer.apple.com/account/#/membership找到所属团队的团队ID。
module.exports = {
  // ...
  packagerConfig: {
    // ...
    osxNotarize: {
      tool: 'notarytool',
      appleId: process.env.APPLE_ID,
      appleIdPassword: process.env.APPLE_PASSWORD,
      teamId: process.env.APPLE_TEAM_ID
    }
  }
  // ...
};

Despite the name, appleIdPassword is not the password for your Apple ID account.尽管有这个名字,appleIdPassword不是您的Apple ID帐户的密码。

Option 2: Using an App Store Connect API key选项2:使用App Store Connect API密钥

You can generate an App Store Connect API key to authenticate notarytool by going to the App Store Connect access page and using the "Keys" tab. 您可以通过转到App Store Connect访问页面并使用“密钥”选项卡生成App Store Connect API密钥以验证notarytoolThis API key will look something like AuthKey_ABCD123456.p8 and can only be downloaded once.此API密钥将类似于AuthKey_ABCD123456.p8,并且只能下载一次。

There are three mandatory fields for osxNotarize if you are using this strategy:如果使用此策略,osxNotarize有三个必填字段:

Field字段Type类型Description描述
appleApiKeystringFilesystem path string to your API key file.API密钥文件的文件系统路径字符串。
appleApiKeyIdstring10-character alphanumeric ID string. 10个字符的字母数字ID字符串。In the previous AuthKey_ABCD123456.p8 example, this would be ABCD123456.在上一个AuthKey_ABCD123456.p8示例中,这将是ABCD123456
appleApiIssuerstringUUID that identifies the API key issuer. 标识API密钥颁发者的UUID。You will find this ID in the "Keys" tab where you generated your API key.您将在生成API密钥的“密钥”选项卡中找到此ID。
module.exports = {
  // ...
  packagerConfig: {
    // ...
    osxNotarize: {
      tool: 'notarytool',
      appleApiKey: process.env.APPLE_API_KEY,
      appleApiKeyId: process.env.APPLE_API_KEY_ID,
      appleApiIssuer: process.env.APPLE_API_ISSUER
    }
  }
  // ...
};

Option 3: Using a keychain选项3:使用钥匙扣

Instead of providing environment variables to the Forge config passed to notarytool, you can choose to use a macOS keychain containing either set of credentials (either Option 1 or Option 2 above).您可以选择使用包含任意一组凭据的macOS密钥链(上面的选项1或选项2),而不是向传递给notarytool的Forge配置提供环境变量。

You can do this directly in your terminal via the notarytool store-credentials command. For usage information, you can refer to the man page for notarytool:您可以通过notarytool store-credentials命令直接在终端中执行此操作。有关用法信息,您可以参考notarytool的手册页:

man notarytool

There are two mandatory fields for osxNotarize if you are using this strategy:如果使用此策略,osxNotarize有两个必填字段:

Field字段Type类型Description描述
keychainstringName of (or path to) the keychain containing the profile with your credentials.包含具有凭据的配置文件的密钥链的名称(或路径)。
keychainProfilestringName of the keychain profile containing your notarization credentials.包含您的公证证书的钥匙链配置文件的名称。
module.exports = {
  // ...
  packagerConfig: {
    // ...
    osxNotarize: {
      tool: 'notarytool',
      keychain: 'my-keychain',
      keychainProfile: 'my-keychain-profile'
    }
  }
  // ...
};

Example configuration配置示例

Below is a minimal Forge configuration for osxSign and osxNotarize.以下是osxSignosxNotarize的最低Forge配置。

module.exports = {
  packagerConfig: {
    osxSign: {},
    osxNotarize: {
      tool: 'notarytool',
      appleId: process.env.APPLE_ID,
      appleIdPassword: process.env.APPLE_PASSWORD,
      teamId: process.env.APPLE_TEAM_ID
    }
  }
};