pacman/软件包签名

出自 Arch Linux 中文维基

為了保證軟體包來自開發者, Pacman 使用信任網絡中的 GnuPG 密鑰進行軟體包驗證。這個網址記錄了 Archlinux 的主密鑰。其中至少三個主密匙被用來簽署官方開發者和授信用戶自己的密鑰,而他們將用這些密鑰簽署自己的包。用戶在配置 pacman-key 時也會生成一個唯一的密鑰。所以信任網絡也會把用戶的密鑰連接到五大主密鑰上面。

信任網絡示例:

  • 自定義軟體包: 用戶自己構建軟體包並用本地密鑰簽名。
  • 非官方軟體包: 開發者構建軟並簽名軟體包。用戶需要用自己的密鑰簽名開發者的密鑰,將其變為可信。
  • 官方軟體包: 開發者構建軟體包,而開發者的密鑰已經被 Arch 主密鑰簽名。最終用戶用自己的密鑰簽名主密鑰,這樣就能信任所有官方開發者。
提示:HKP協議使用11371/tcp埠用來通信。為了從伺服器得到簽署的密鑰(使用pacman-key),這個埠必須打開。

配置[編輯 | 編輯原始碼]

配置 pacman[編輯 | 編輯原始碼]

/etc/pacman.conf 中的 SigLevel 配置用 pacman -S 安裝軟體時使用的檢查級別。文件的注釋中列出了幾個可選設置,pacman.conf(5) § PACKAGE AND DATABASE SIGNATURE CHECKING 有詳細介紹。簽名檢查可以全局配置或針對某個倉庫配置。如果 SigLevel 在 [options] 節中進行了全局設置,那麼所有的包都必須簽名。如果使用 pacman.conf 中默認的 LocalFileSigLevel ,所有編譯和用 pacman -U 安裝的軟體包都不需要使用 makepkg 進行簽名。

注意: 儘管所有的官方軟體包現在都進行了簽名,但是在2018年11月的時候簽名資料庫還在開發。如果設置了 Required ,那麼 DatabaseOptional 也應該被設置。

默認的設置下,系統只安裝被授信的密鑰簽署的軟體包。

/etc/pacman.conf
SigLevel = Required DatabaseOptional

TrustedOnly 是 pacman 的默認設置。

默認配置的效果與下行等同:

SigLevel = Required DatabaseOptional TrustedOnly

上面這些也可以在倉庫內部進行設置,比如:

[core]
SigLevel = PackageRequired # 』Optional』 here would turn off a global 』Required』 for this repository
Include = /etc/pacman.d/mirrorlist

軟體倉庫中的軟體啟用了簽名驗證,但是並不要求倉庫資料庫也被簽名了。

警告: SigLevel TrustAll 設置僅僅為了測試而存在,使用它會信任未被驗證的密鑰。對於所有的官方軟體源你應該使用 TrustedOnly

初始化密鑰環[編輯 | 編輯原始碼]

要初始化 pacman 密鑰:

# pacman-key --init

初始化密鑰,需要收集到足夠的。請隨意移動滑鼠,隨機按鍵盤或者運行一些磁碟讀寫操作(比如在其他終端運行ls -R /或者find / -name foo 或者 dd if=/dev/sda8 of=/dev/tty7之類的)應該會收集足夠的熵。如果你的系統沒有足夠的熵,這項工作需要好幾個小時,但是如果你有,那麼就會快多了。

這會在 /etc/pacman.d/gnupg 初始化密鑰並生成系統主密鑰。

注意: 如果pacman-key --init運行時系統沒有足夠的熵,可能會需要很長時間。請在目標機器上安裝 havegedrng-tools。然後在用 root 權限執行pacman-key --init啟動 haveged.service

管理密鑰[編輯 | 編輯原始碼]

驗證主密鑰[編輯 | 編輯原始碼]

通過以下命令進行配置:

# pacman-key --populate

該命令對 Master Signing Keys 進行驗證,when prompted as these are used to co-sign (and therefore trust) all other packager's keys.

PGP 通常很長(2048 位或更長),不太容易使用,所以通常創建一個40位十六進位指紋,最後八位被稱為密鑰 ID,是密鑰的名字。長簽名可以用來檢測兩個密鑰是否相同。

官方開發者密鑰[編輯 | 編輯原始碼]

官方開發者和 TU 的密鑰已經被主密鑰簽名認證,所以不需要用 pacman-key 認證它們。pacman 遇到不認識的簽名時,它將會詢問是否從密鑰伺服器(設置在/etc/pacman.d/gnupg/gpg.conf文件中,或在命令行中使用--keyserver選項)下載。

提示:維基百科提供了一份公鑰伺服器列表

下載開發者密鑰後,以後都不需要下載。以後會用它驗證所有這個開發者構建的軟體包。

注意:

如果開發者和 TU 的密鑰是較早之前導入,它們的簽名可能還不存在於本地資料庫,用下面命令更新:

# pacman-key --refresh-keys
當使用--refresh-keys 時,本地簽名也會被遠程查找,並收到未找到的消息,這是正常的。

導入非官方密鑰[編輯 | 編輯原始碼]

可以通過此方法在pacman密鑰環中添加你自己的密鑰,或者啟用已簽名的非官方軟體倉庫

首先從密鑰持有者手中拿到密鑰 ID(keyid),然後把密鑰加入密鑰環:

  • 如果密鑰位於密鑰伺服器,通過下面命令導入:
    # pacman-key -r keyid
  • 如果提供了地址,先下載,然後用下面密鑰導入:
    # pacman-key --add /path/to/downloaded/keyfile

對於所有要簽名的密鑰,都通過指紋進行驗證:

$ pacman-key -f keyid

最後,本地簽名導入的密鑰:

# pacman-key --lsign-key keyid

現在可以用這個密鑰簽名軟體包了。

用GPG調試[編輯 | 編輯原始碼]

如果需要,可以直接使用GPG調試pacman鑰匙環,例如:

# gpg --homedir /etc/pacman.d/gnupg --list-keys

提示和技巧[編輯 | 編輯原始碼]

Upgrade system regularly[編輯 | 編輯原始碼]

Upgrading the system regularly via pacman#Upgrading packages prevents most signing errors. If delay is unavoidable and system upgrade gets delayed for an extended period, manually sync the package database and upgrade the archlinux-keyring package before system upgrade:

# pacman -Sy archlinux-keyring && pacman -Su

This command is not considered a partial upgrade since it syncs the package database and upgrades the keyring package first. Both must be processed just before starting system upgrade to ensure signatures of all upgraded packages can be properly verified.

Update system time regularly[編輯 | 編輯原始碼]

When the 系統時間 is faulty, signing keys could be considered expired (or invalid) and signature checks on packages will fail. Synchronize the system clock regularly by using the Network Time Protocol daemon.

問題解決[編輯 | 編輯原始碼]

error: signature from xxx is invalid[編輯 | 編輯原始碼]

Pacman-key 依賴於系統時間。如果系統時間是錯誤的,將會獲得一個報錯:

error: PackageName: signature from "User <email@archlinux.org>" is invalid
error: failed to commit transaction (invalid or corrupted package (PGP signature))
Errors occured, no packages were upgraded.

如果是使用 ntpd, (root權限) 執行 ntpd -qg,然後執行 hwclock -w.

如果使用的是其他 NTP 客戶端,請參考系統時間#時鐘同步

如果問題依然存在,請嘗試下面方法:

刪除報錯的包[編輯 | 編輯原始碼]

如果相同的包持續失敗,並且您確定 pacman-key 的相關操作是正確的,可以嘗試移除軟體包 rm /var/cache/pacman/pkg/packagename 或者清空所有緩存,然後可以重新下載軟體包。

重置所有密鑰[編輯 | 編輯原始碼]

如果要刪除或重置系統,刪除 /etc/pacman.d/gnupg 目錄並重新運行 pacman-key --init。通過 pacman-key --populate 重新添加默認密鑰。

禁用簽名檢查[編輯 | 編輯原始碼]

警告: 小心使用,禁用簽名檢查,pacman 會自動安裝不信任的軟體包。

如果不在意軟體包簽名,可以完全禁用 PGP 簽名檢查,編輯 /etc/pacman.conf 並取消注釋 [options] 下的如下行:

SigLevel = Never
 #LocalFileSigLevel = Optional
#RemoteFileSigLevel = Required

需要同時注釋掉單獨軟體源的 SigLevel 設置,因為他們會覆蓋全局設置。

這樣就不會進行任何簽名檢查,和 pacman 4 之前一樣。如果這樣,就不需要用 pacman-key 建立密鑰環。

密鑰導入失敗[編輯 | 編輯原始碼]

有三種可能的情況導致這個問題:

  • 過期的archlinux-keyring 包。
  • 不正確的系統時間。
  • 你的ISP屏蔽了用於導入 PGP keys 的埠。
  • pacman 緩存中包含之前的未簽名軟體包
  • 未正確設置 dirmngr

過期的 archlinux-keyring 包可能會導致這個問題,根據情況採用下面的解決方法

切換公鑰伺服器[編輯 | 編輯原始碼]

如果這樣沒有起作用,並且系統時間是正確的,你可以嘗試切換到 Ubuntu 提供的公鑰伺服器(keyserver)。編輯 /etc/pacman.d/gnupg/gpg.confkeyserver 行替換為

keyserver hkp://keyserver.ubuntu.com

清理軟體包緩存[編輯 | 編輯原始碼]

如果上面方法都不起作用,pacman 緩存 /var/cache/pacman/pkg/ 可以包含之前下載的未簽名軟體包,手動清空緩存:

# pacman -Sc

=== Signature is unknown trust ===

在執行 pacman -Syu 時可能出現下面錯誤:

error: package-name: signature from "packager" is unknown trust

這是因為 package-name 軟體包使用的 packager 的密鑰不被本地的 pacman-key gpg 資料庫信任。可能是密鑰在加入密鑰鏈之後失效了,可以通過下面方法解決:

  • pacman-key --refresh-keys 刷新密鑰
  • 本地手動簽署密鑰
  • 刷新所有密鑰
  • SigLevel 設置成 TrustAll (不推薦)

後面兩個選項將會破壞信任連,所以請謹慎使用。

通過代理更新密鑰[編輯 | 編輯原始碼]

要使用代理更新密鑰,必須同時在 /etc/gnupg/dirmngr.conf/etc/pacman.d/gnupg/dirmngr.conf 中設置 honor-http-proxy 選項。更多信息請閱讀 GnuPG#Use a keyserver.

注意: 如果 pacman-key 沒有用 honor-http-proxy 選項,執行失敗,重啟可能能夠解決問題。

參閱[編輯 | 編輯原始碼]