為簽署的 Electron 和 Node.js 應用程式提供安全儲存,由現代 macOS Data Protection Keychain 提供支援。

accounts 宣告不可變的 Keychain 項目;mutableAccounts 宣告可變的項目。儲存區可以存取它們的聯合,而只有可變帳戶可以被變更或移除。一個名稱必須屬於且僅屬於一個列表,並且任一列表都可以省略。

執行的 Electron 或 Node 主機必須具有有效的 Apple 代碼簽章。預設情況下,套件使用主機的 Bundle ID 作為其 Keychain 服務,並讓 macOS 使用主機的私人 Keychain 存取群組。不需要進行任何套件身分識別設定。

此套件將 generic-password 項目儲存在 macOS 的 Data Protection Keychain 中。其原生實作使用 SecItem API 和 kSecUseDataProtectionKeychain: true,而不是舊版 Keychain 和 SecKeychain API 使用的基於檔案的舊版 Keychain。Apple 建議對新專案使用 Data Protection Keychain,因為它支援現代的存取群組、iCloud Keychain 和生物辨識存取控制。請參閱 Apple 的 keychain 實作指南。

透過舊版基於檔案的 Keychain API 建立的項目在這裡無法自動取得;如有需要,請明確遷移它們。安全性 CLI 同樣不是此儲存區項目的檢查路徑。請改用 Keychain Access:項目會顯示在 Local Items 下(如果 iCloudSync 為 false),或 iCloud Keychain 下(如果 iCloudSync 為 true)。

未修改的 Electron 執行環境會將自身識別為 Electron,因此它不是您應用程式開發秘密的良好命名空間。相反,請使用已簽署為獨立開發應用程式的快取 Electron 執行環境來執行 Electron Vite,例如 com.example.product.dev。當沒有 keychainService 時,相同的 openKeychainStore() 呼叫會自動使用該 Bundle ID,將本地值與生產環境分開。

在 Apple Developer 入口網站中,註冊 com.example.product.dev 並為其建立 macOS 開發佈建設定檔。啟用 Keychain Sharing。該設定檔必須允許此完整的存取群組:

com.apple.security.application-groups: ["group.com.example.product.dev"]

將 ABCDE12345 替換為您的 Apple Developer Team ID。Xcode 可以為您建立設定檔:建立一個具有該 Bundle ID 的臨時 macOS 應用程式目標,選擇您的 Team,新增 Keychain Sharing 功能,然後建置一次。

將此副本保留在 node_modules 外部的使用者快取中;每當 Electron 版本、開發憑證或佈建設定檔變更時,請重新建立它。建立一個包含您完整識別碼和 Electron 常規執行環境權限的主權限檔案:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

<key>com.apple.security.app-sandbox</key>

<true/>

<key>com.apple.security.application-groups</key>

<array>

<string>group.com.example.product.dev</string>

</array>

</dict>

</plist>

首先簽署 Electron 的輔助應用程式。它們不需要您的 Keychain 存取群組;此最小輔助權限檔案足以用於標準 Electron 開發執行環境:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

<key>com.apple.security.app-sandbox</key>

<true/>

</dict>

</plist>

將這兩個檔案儲存為 electron-development.entitlements.plist 和 electron-helper.entitlements.plist,然後執行:

$ codesign --deep --force --sign "Developer ID Application: Your Name" --entitlements electron-development.entitlements.plist "./dist/electron/main" "./dist/electron/preload.js" "./dist/electron/renderer.js"

$ codesign --deep --force --sign "Developer ID Application: Your Name" --entitlements electron-helper.entitlements.plist "./dist/electron/electron-updater.exe"

在您的 Electron Vite 啟動之前設定這些(通常在啟動 electron-vite dev 的腳本中):

import { openKeychainStore } from "keychain-store";

const keychainStore = await openKeychainStore({

name: "my-app-secrets",

// keychainService: "com.example.product.dev", // Omitted for local development

});

除非您有意在應用程式之間共用項目,否則請省略 keychainService。共用服務還需要其匹配的 Keychain 存取群組權限在開發執行環境中。

macOS 會將存取權授予所有使用匹配 Keychain 存取群組權限簽署的應用程式。請妥善保管您的簽章憑證、私鑰和權限設定。

Authentication 控制 macOS 是否要求使用者驗證存取權。它不決定哪些應用程式可以存取項目:簽章的主機身分識別和 Keychain 存取群組始終決定這一點。

選擇一個驗證邊界。套件不會合併它們,因此一個操作不會產生兩個提示。

authentication: { accessControl: ... } 將要求與項目一起儲存。每當有權限的應用程式讀取該項目時,即使該應用程式不使用此套件,也會套用此要求。

user-presence 允許 macOS 裝置擁有者驗證,例如 Touch ID 或使用者的密碼。biometrics-only 在沒有註冊 Touch ID 的 Mac 上會失敗;它不會使用 Apple Watch 或附近的 iPhone。

authentication: { operationAuth: ... } 會在每個套件操作之前要求目前應用程式進行驗證。它不會變更已儲存的項目,因此另一個有權限的應用程式不需要進行相同的提示。

當不需要額外的使用者驗證提示時,請使用 authentication: "none"。它不會使項目公開;只有滿足已設定簽章和權限政策的應用程式才能存取它們。

項目的 accessControl 政策是持久的。要變更它,請使用新政策建立一個新帳戶,並將您的應用程式資料遷移到其中。對於加密金鑰,這通常意味著使用新金鑰重新加密應用程式資料。operationAuth 不會與項目一起儲存,並且可以獨立變更。

設定 iCloudSync: true 以要求 macOS 透過 iCloud Keychain 同步儲存區的項目。變更設定永遠不會刪除現有項目。

get() 仍然是唯讀的。如果一個項目僅存在於相反的同步設定下,它將被拒絕並顯示 synchronization_migration_required。getOrCreate() 會在設定的範圍內新增一個副本;它不會覆寫或移除現有副本。

該套件不會檢查使用者是否已登入 Apple 帳戶或是否已啟用 iCloud Keychain。即使 macOS 目前無法同步項目,建立也可能在本地成功;成功僅表示 Keychain 已接受它,而不是其他裝置已收到它。如果 Security framework 無法建立或存取項目,該操作將被拒絕並顯示其 Keychain 錯誤。

請使用字串表示 UTF-8 文字,並使用 Uint8Array 表示二進位資料。呼叫 get() 時明確選擇表示法。請求 "string" 會因 item_not_utf8 而被拒絕,如果項目不包含有效的 UTF-8 文字。

在每個共用此儲存區的應用程式中設定相同的 keychainService。該套件會將存取群組衍生為執行中應用程式的 Team ID 後面加上此值。

每個應用程式都必須在其簽章權限中包含產生的完整存取群組。使用 Electron Builder 時,將其新增到 macOS 的 entitlements plist。使用 Electron Forge 時,將該 plist 透過 packagerConfig.osxSign 傳遞。

此儲存庫還為簽署的原生 macOS 目標提供了 KeychainStore Swift Package Manager 函式庫。它透過 Swift Package Manager 發佈,而不是 npm 套件。從此儲存庫新增 KeychainStore 函式庫產品:

import KeychainStore from "@biw/keychain-store/dist/swift";

一旦儲存庫有標記的發行版,請改用版本要求。Swift 函式庫使用與 Node 套件相同的項目格式和宣告帳戶政策。

ensure() 會建立一個項目而不返回其位元組,這對於原生程式碼擁有加密工作流程的情況很有用。

KeychainStoreSwiftSync 提供相同的宣告帳戶方法,但僅使用 authentication: .none。其操作可能會封鎖呼叫執行緒,因此請使用非同步儲存區,除非需要同步邊界。

為簽署的 Electron 和 Node.js 應用程式提供安全儲存,由現代 macOS Data Protection Keychain 提供支援。