macOS Keychain 存取 API Key

macOS 15 起 Passwords 应用收录网站登录与 Passkey,通用密码项无图形新建入口,API Key 以 security 命令按 generic password 存取。

macOS 上存 API Key,我们以 security 命令行读写 Keychain。本文是《API Key 不应该放在 shell 配置文件里》中 Keychain 方案的展开,聚焦命令行增删改查。

图形界面变化

macOS 15 Sequoia 起,网站登录,Wi-Fi 密码和 Passkey 纳入 Passwords (密码) 应用,Keychain Access (钥匙串访问) 移入 Other 文件夹,Spotlight 搜索 Keychain Access 跳转至 Passwords。

Passwords 仅收录上述三类,不显示通用的 application password (应用密码)。Sequoia 下 Secure Note (安全备忘) 新建入口失效,新建仅弹出 New Password 对话框,“文件,新建密码项”流程无响应。

API Key 这类自定义项在图形界面无对应入口,命令行为可用入口。

密码项类型

API Key 存放于 generic password (通用密码) 项,以 service (服务),account (账户),password (密码) 三个字段定位。以下是字段与 API Key 的对应关系:

  • service 为项目或应用名,如 MyApp
  • account 为 Key 名,如 OPENAI_API_KEY
  • password 为 Key 值

internet password (互联网密码) 另有 server (服务器),protocol (协议),port (端口) 等字段,用于网站登录,不用于 API Key。

命令行增删改查

我们以 login keychain (登录钥匙串) 为默认对象,未指定 keychain 文件的命令均读写该钥匙串。

新增

-w 不跟值时转交互式输入,密码值不进入 shell history:

security add-generic-password -s "MyApp" -a "OPENAI_API_KEY" -w

附加备注可用 label 和 comment:

security add-generic-password -s "MyApp" -a "OPENAI_API_KEY" -l "MyApp OpenAI" -j "prod key 2026-09" -w

查询

-w 仅输出密码值,-g 输出完整条目及密码值:

security find-generic-password -s "MyApp" -a "OPENAI_API_KEY" -w
security find-generic-password -s "MyApp" -a "OPENAI_API_KEY" -g

更新

-U 支持已存在时覆盖写入,不加 -U 且条目已存在时命令报错:

security add-generic-password -U -s "MyApp" -a "OPENAI_API_KEY" -w

不使用 -U 时,先删除再新增可达到相同效果:

security delete-generic-password -s "MyApp" -a "OPENAI_API_KEY"
security add-generic-password -s "MyApp" -a "OPENAI_API_KEY" -w

删除与列举

以下是删除指定条目与列举全部条目的命令:

security delete-generic-password -s "MyApp" -a "OPENAI_API_KEY"
security dump-keychain | grep -A4 "svce"

dump-keychain 输出包含全部条目与元数据。

脚本与代码调用

Shell 在启动时读取一次并注入环境变量,密码值不写入文件:

export OPENAI_API_KEY=$(security find-generic-password -s "MyApp" -a "OPENAI_API_KEY" -w)

Python 经 keyring (密钥存取库) 调用 Keychain,serviceaccount 与命令行三元组对应:

import keyring
keyring.set_password("MyApp", "OPENAI_API_KEY", "sk-...")
api_key = keyring.get_password("MyApp", "OPENAI_API_KEY")

原生开发调用 Security framework (系统安全框架),以 kSecClassGenericPasswordkSecAttrServicekSecAttrAccount 查询,Node 以 keytar 调用,Go 以 go-keychain 调用,三者字段语义一致。

实操注意点

实操注意点集中在以下三处:history 泄露,授权弹窗,同步范围。

第一,history 泄露security add-generic-password -w sk-... 将密码值写入 shell history 与进程表,我们以交互式输入或 security -i 交互模式避开明文进入 history 与进程表。

第二,授权弹窗。默认写入 login keychain,登录后保持解锁,创建者进程默认直接读取,其他应用首次读取触发系统授权弹窗,点按 Allow Always 后不再弹出。CI 或 SSH 无图形会话的主机无法点按弹窗,以 -T /Applications/xxx.app 预先限定可访问应用,或改用专用 keychain 文件。-A 允许任意应用读取,未限定访问主体。

第三,同步范围。经 iCloud 同步的条目随账号同步到多台设备,高权限 API Key 存放于本地 login keychain,换机时随 keychain 文件迁移。

参考来源