GNOME/Keyring
GNOME Keyring 是「GNOME 中一組用於存儲機密、密碼、密鑰、證書,並將其提供給應用程式使用的組件」。
它提供了 org.freedesktop.secrets,這是一個 API,允許客戶端應用藉助運行在用戶登錄會話中的服務來安全地存儲機密。
安全性
防禦惡意應用
過去曾報告過一個關於 GNOME/Keyring API 行為的安全問題(即 CVE-2018-19358)。只要鑰匙環處於解鎖狀態,任何應用都能輕易讀取任何機密。而如果用戶已登錄,那麼登錄/默認鑰匙環就是解鎖的。現有的 D-Bus 防護機制(涉及 busconfig 和 policy XML 元素)默認並未啟用,而且就算啟用也很容易被繞過。
GNOME 項目不認同這份漏洞報告,因為按照他們聲明的安全模型,不應允許不可信的應用與 secret service 通信。
通過行為規範的沙箱(例如未添加額外權限的 Flatpak)運行的應用,對會話總線只有經過過濾的訪問權限。
會話鎖定時鑰匙環並未鎖定
會話鎖定時,鑰匙環並不會自動鎖定。[1] 這意味著密碼仍留在內存中,從而使系統暴露於 DMA 攻擊之下。
安裝
gnome-keyring包 是 gnome包組 組的成員,因此在運行 GNOME 的系統上通常已經存在。在其他情況下,也可以單獨安裝該軟體包。還應安裝 libsecret包,以便讓其他應用訪問你的鑰匙環。雖然 libgnome-keyringAUR 已被棄用(並由 libsecret 取代),但某些應用可能仍然需要它。
gnome-keyring-daemon 會在登錄時通過 systemd 用戶服務自動啟動。它也可以按需通過套接字啟動。
與 GNOME Keyring 相關的其他實用工具包括:
- secret-tool — 從命令行訪問 GNOME Keyring(以及任何其他實現了 DBus Secret Service API 的服務)。
- lssecret — 使用 libsecret 列出所有機密條目(例如 GNOME Keyring)。
用圖形界面管理
你可以使用 Seahorse 管理 GNOME Keyring 的內容;請安裝 seahorse包 軟體包。
鑰匙環的密碼(例如默認鑰匙環 「Login」)可以修改,甚至可以移除。更多信息見 GNOME 幫助中的 創建新鑰匙環 和 更新鑰匙環密碼。
使用鑰匙環
PAM 模塊 pam_gnome_keyring.so 會部分初始化 GNOME Keyring,並在該過程中解鎖 login 鑰匙環。gnome-keyring-daemon 會通過 systemd 用戶服務自動啟動。
PAM 步驟
- 要在自動登錄的情況下實現自動解鎖,可以把鑰匙環的密碼設為空。請注意,這種情況下鑰匙環的內容將以未加密形式存儲。
- 另一種做法是,如果使用 GDM 和 LUKS,當鑰匙環密碼與 LUKS 密碼一致時,GDM 可以解鎖你的鑰匙環。為此,你需要在 mkinitcpio.conf 中使用 systemd 初始化,並設置相應的內核參數,同時應確保系統的實時時鐘設為 UTC 而非本地時間(見 [2])。更多細節見 [3]。
- 如果你希望跳過 PAM 這一步,那就必須手動或以其他方式解鎖鑰匙環。參見#在桌面環境(KDE、GNOME、XFCE……)之外使用 gnome-keyring-daemon和 GnomeKeyring wiki。
使用顯示管理器時,多數情況下鑰匙環開箱即用。GDM、LightDM、LXDM 和 SDDM 已經帶有必要的 PAM 配置。對於不會自動解鎖鑰匙環的顯示管理器,請編輯對應的文件,而不是下文提到的 /etc/pam.d/login。
使用基於控制台的登錄方式時(即不使用顯示管理器),請編輯 /etc/pam.d/login:
在 auth 部分的末尾添加 auth optional pam_gnome_keyring.so,並在 session 部分的末尾添加 session optional pam_gnome_keyring.so auto_start。
/etc/pam.d/login
#%PAM-1.0 auth required pam_securetty.so auth requisite pam_nologin.so auth include system-local-login auth optional pam_gnome_keyring.so account include system-local-login session include system-local-login session optional pam_gnome_keyring.so auto_start
使用指紋登錄時解鎖
使用 fprintd 進行指紋認證時不會設置 PAM_AUTHTOK:讀取器返回的是判定結果,而不是密碼。因此 pam_gnome_keyring.so 沒有可用於解鎖 login 鑰匙環的東西,第一個請求機密的程序便會提示輸入密碼 [4]。任何不產生帳戶密碼的認證方式都是如此。
可以考慮的做法:
- 在會話的首次提示中輸入帳戶密碼。此後該會話餘下的時間裡鑰匙環都保持解鎖。
- 按#PAM 步驟中所述,把 login 鑰匙環的密碼設為空。此時鑰匙環內容將以未加密形式存儲。
- 用一個在
pam_gnome_keyring.so之前運行的 PAM 模塊把PAM_AUTHTOK設為鑰匙環密碼。該密碼存放在哪裡、由什麼保護,正是這類實現之間的區別所在。
SSH 密鑰
GNOME Keyring 可以充當 ssh-agent 的包裝層。在這種模式下,每次需要解鎖 SSH 密鑰時,它都會顯示一個圖形化密碼輸入對話框。該對話框帶有一個記住所輸入密碼的複選框,若勾選,那麼只要你的登錄鑰匙環處於解鎖狀態,今後就能完全無密碼地使用該密鑰。
自 1:46 版起,gnome-keyring-daemon 的構建中默認禁用 SSH 功能。該功能已被遷移到 /usr/lib/gcr-ssh-agent,它是 gcr-4包 軟體包的一部分。
配置 gcr
啟用並啟動 gcr-ssh-agent.socket 這個 systemd 用戶單元。
該單元啟動後,會創建套接字文件 $XDG_RUNTIME_DIR/gcr/ssh。
如果 gcr-ssh-agent.socket 單元處於活動狀態,則無需手動配置 SSH_AUTH_SOCK 環境變量。當用戶註銷並重新登錄時,SSH_AUTH_SOCK 環境變量的值會被設為 $XDG_RUNTIME_DIR/gcr/ssh。
使用
你可以運行
$ ssh-add -L
來列出正在運行的 agent 中已加載的 SSH 密鑰。這有助於確認你啟動了正確的服務,並正確設置了 SSH_AUTH_SOCK。
要把口令永久保存到鑰匙環中,請使用 seahorse包 軟體包提供的 ssh-askpass:
$ /usr/lib/seahorse/ssh-askpass my_key
要從其他目錄手動添加 SSH 密鑰:
$ ssh-add ~/.private/id_ed25519 Enter passphrase for ~/.private/id_ed25519:
~/.ssh/id_ed25519.pub)。另外,請確保公鑰文件名為私鑰文件名加上 .pub(例如 my_key.pub)。要禁用所有手動添加的密鑰:
$ ssh-add -D
禁用
如果你希望改用其他 SSH agent(例如直接使用 ssh-agent,或使用 gpg-agent),最好禁用 GNOME Keyring 的 ssh-agent 包裝層。這樣做並非嚴格必需,因為每個 agent 監聽的套接字不同,可以用 SSH_AUTH_SOCK 在它們之間選擇,但這能讓排查問題更容易。請注意,GNOME 的實現不支持許多腳本特性,例如 BatchMode [5]。
要禁用 gcr-ssh-agent,請確保 gcr-ssh-agent.socket 和 gcr-ssh-agent.service 在 systemd 中都已禁用並停止。
提示與技巧
與應用程式集成
鎖定鑰匙環
$ dbus-send --session --dest=org.freedesktop.secrets \ --type=method_call \ /org/freedesktop/secrets \ org.freedesktop.Secret.Service.Lock \ array:objpath:/org/freedesktop/secrets/collection/login
該命令執行一次 D-Bus 方法調用,以鎖定 login 鑰匙環。或者,如果你想使用圖形界面,也可以用 Seahorse 鎖定鑰匙環。
清空口令
$ gnome-keyring-daemon -r -d
該命令會啟動 gnome-keyring-daemon,並關閉此前已經在運行的實例。
Git 集成
當你通過 HTTPS 推送時,GNOME keyring 與 Git 配合使用會很有用。libsecret包 軟體包需要安裝,該功能才可用。
配置 Git 使用 libsecret 助手:
$ git config --global credential.helper /usr/lib/git-core/git-credential-libsecret
下次運行 git push 時,如果你的鑰匙環尚未解鎖,系統會要求你解鎖它。
GnuPG 集成
有幾個使用 GnuPG 的應用需要設置 pinentry-program。設置以下內容即可使用 GNOME 3 pinentry,讓 GNOME Keyring 來管理口令提示。
~/.gnupg/gpg-agent.conf
pinentry-program /usr/bin/pinentry-gnome3
另一種做法是強制 GPG 使用 loopback,這樣應該就能在應用內輸入口令。
重命名鑰匙環
鑰匙環的顯示名稱(即 Seahorse 和 file 命令中顯示的名稱)可以通過[更改未加密鑰匙環文件中 display-name 的值來修改]。鑰匙環通常存放在 ~/.local/share/keyrings/ 中,擴展名為 .keyring。
用戶密碼變化時自動更改鑰匙環密碼
向 /etc/pam.d/passwd 中追加 password optional pam_gnome_keyring.so:
/etc/pam.d/passwd
... password optional pam_gnome_keyring.so
在桌面環境(KDE、GNOME、XFCE……)之外使用 gnome-keyring-daemon
啟動
如果你使用 sway、i3,或任何不會執行
/etc/xdg/autostart/gnome-keyring-*.desktop/etc/X11/xinit/xinitrc.d/50-systemd-user.sh
的窗口管理器,那麼你的窗口管理器需要在啟動時執行以下命令。這些命令不必按特定順序執行。
dbus-update-activation-environment DISPLAY XAUTHORITY WAYLAND_DISPLAY
或者
dbus-update-activation-environment --all
該命令會把環境變量從窗口管理器傳遞給會話 dbus。若不執行,就無法通過 DBus 觸發圖形化的提示框。例如,Seahorse 的密碼提示就依賴於此。
之所以需要這樣做,是因為會話 dbus 在圖形環境啟動之前就已經啟動,因此會話 dbus 並不知道你處在哪個圖形環境中。必須有某個東西把描述圖形環境的環境變量傳給會話 dbus,讓它了解當前的圖形環境。
gnome-keyring-daemon --start --components=secrets
登錄期間,PAM 會啟動 gnome-keyring-daemon --login,它負責用登錄密碼讓 gnome-keyring 保持解鎖狀態。如果 gnome-keyring-daemon --login 在幾分鐘內沒有連接到會話 dbus,gnome-keyring-daemon --login 就會退出。如果在窗口管理器中針對會話 dbus 啟動了 gnome-keyring-daemon --start ...,那麼 gnome-keyring-daemon --login 就會連接到會話 dbus。如果你的登錄會話沒有在 gnome-keyring-daemon --login 退出前啟動 gnome-keyring-daemon --start ...,你也可以在 gnome-keyring-daemon --login 退出之前,先運行任何使用 gnome-keyring 或 secret service API 的程序。
GNOME Keyring XDG 門戶
GNOME Keyring 提供一個 XDG 門戶後端(例如可供通過 Flatpak 沙箱化的應用使用)。要使其在 GNOME 之外工作,必須配置為使用它。有幾種做法。
配置用戶級的 Secrets 門戶
避免修改系統文件的方法是,在 $XDG_CONFIG_HOME/xdg-desktop-portal/$XDG_CURRENT_DESKTOP-portals.conf 中把 gnome-keyring 配置為首選的 Secrets 門戶。例如,要把 sway 配置為使用 gnome-keyring 作為 org.freedesktop.impl.portal.Secret 的首選門戶:
~/.config/xdg-desktop-portal/sway-portals.conf
[preferred] default=wlr;gtk org.freedesktop.impl.portal.Secret=gnome-keyring
修改 gnome-keyring.portal
另一種方法是修改 UseIn 鍵,把你的桌面環境加入 /usr/share/xdg-desktop-portal/portals/gnome-keyring.portal 配置文件。例如,要加入 sway:
/usr/share/xdg-desktop-portal/portals/gnome-keyring.portal
[portal] DBusName=org.freedesktop.secrets Interfaces=org.freedesktop.impl.portal.Secret UseIn=gnome;sway
關於 XDG 桌面門戶後端的更多信息,見 XDG 桌面門戶#後端。
故障排除
密碼沒有被記住
如果你在登錄後被要求輸入密碼,並且發現密碼沒有被保存,那麼你可能需要創建/設置一個默認鑰匙環。要使用 Seahorse(也稱「密碼和密鑰」)完成此操作,見 GNOME 幫助中的 創建新鑰匙環 和 更改默認鑰匙環。
重置鑰匙環
如果你收到以下錯誤信息:「The password you use to login to your computer no longer matches that of your login keyring」,你需要更改登錄鑰匙環密碼。
或者,你可以從 ~/.local/share/keyrings/ 中刪除 login.keyring 和 user.keystore 文件。請注意,這會永久刪除所有已保存的密鑰。刪除這些文件後,只需註銷再重新登錄即可。
Unable to locate daemon control file
登錄後,日誌中可能會出現以下錯誤:
gkr-pam: unable to locate daemon control file
如果沒有其他相關問題,這條消息「可以安全地忽略」 [6]。
No such secret collection at path: /
如果你嘗試用 Seahorse 添加新鑰匙環,可能會因以下原因收到此錯誤:
-
~/.local/share/keyrings/目錄不存在。若缺失請創建它。 - 使用了自定義的
~/.xinitrc。添加以下一行可能可以解決 [7]
~/.xinitrc
source /etc/X11/xinit/xinitrc.d/50-systemd-user.sh
終端提示 「discover_other_daemon: 1」
這是因為 gnome-keyring-daemon 被第二次啟動了。既然該守護進程已經隨附了 systemd 服務,就無需再以其他方式啟動它。所以請確保從 .zshenv、.bash_profile、.xinitrc、config.fish 或類似文件中刪除啟動命令。或者,你也可以禁用 gnome-keyring-daemon.service 和 gnome-keyring-daemon.socket 這些用戶單元。
鑰匙環初始化不正確
這有幾種症狀:
- SSH 或 Git 之類的程序在等待鑰匙環提供密碼時掛起,最終超時並報出 「agent refused operation」 之類的錯誤。
- Seahorse 不顯示任何鑰匙環,而且手動創建一個名為 「login」 的鑰匙環似乎不起作用。
- Seahorse 的輸出中出現以下錯誤信息:
couldn't load all secret collections: No such secret collection at path: /org/freedesktop/secrets/collection/login
要解決此問題,請執行以下操作:
-
重啟
gnome-keyring-daemon.service這個 systemd 用戶單元。這應當能正確初始化 login 鑰匙環。 - 如果使用的話,重啟
gcr-ssh-agent.service這個 systemd 用戶單元。其他 agent 可能也需要重啟。
如果這樣仍無法解決問題,可以考慮重置鑰匙環。
SSH agent 不可用
症狀:
$ ssh-add -L
Error connecting to agent: Connection refused
請確保 gcr-ssh-agent.socket 用戶單元已被啟用並啟動,並且 gnome-keyring-daemon 的套接字和服務用戶單元也已啟用並啟動:
{service,socket} 使用 shell 的花括號展開。No Process Capabilities, Insecure Memory Might Get Used
如果看到以下錯誤 gnome-keyring-daemon: no process capabilities, insecure memory might get used,這意味著鑰匙環可能會被保存到交換文件/分區中。這是一個安全問題,因為他人可能在沒有適當授權的情況下讀取並提取這些機密。解決方法是讓內核不要這樣做,但 gnome-keyring-daemon 需要具備相應的權限才行。
運行以下命令,賦予 gnome-keyring-daemon 適當的內存鎖定權限:
# setcap cap_ipc_lock=+ep /usr/bin/gnome-keyring-daemon