Emacsのパッケージをインストールする時には署名の検査が行われますが、署名の検査を行わないように設定に設定できます。今回はその際に設定する変数と使われ方について調べました。
TL;DR
- パッケージの署名の検査はpackage-check-signatureとpackage-unsigned-archivesの設定で検査するかどうかが決定する
- package-check-signatureに設定できる値は
nil
'allow-signed
t
'all
のいずれかを設定する - package-unsigned-archivesは署名の検査をしないパッケージアーカイブの名前のリストを設定する
package-check-signatureに設定できる値と意味
値 | 意味 |
nil | 署名のチェックをしない |
'allow-signed | 署名があり鍵がある時だけ署名の確認を行う |
t | 少なくとも1つの検証済み署名が必要 |
'all | 全ての検証済み署名が必要 |
署名ファイルがないのにpackage-refresh-contentsできる?
自分用にパッケージアーカイブを作成しました。しかし署名ファイルはまだ準備していません。それにもかかわらずなぜかpackage-refresh-contentsできてしまいました。Emacsのパッケージがインストールされるのを眺めるで確認した時にはM-x package-refresh-contentsを実行してインデックス情報であるarchive-contentsをダウンロードした時にも、パッケージをインストールする時にも署名ファイル(.sig)のダウンロードとその検査を行なっていました。今回はこの挙動の違いの理由を調べます。
package-check-signature - 署名を確認するかどうかを制御する
package-check-signatureはインストール時に署名を確認するかどうかを制御するための変数です。
(defcustom package-check-signature (if (and (require 'epg-config) (epg-find-configuration 'OpenPGP)) 'allow-unsigned) "Non-nil means to check package signatures when installing. More specifically the value can be: - nil: package signatures are ignored. - `allow-unsigned': install a package even if it is unsigned, but if it is signed and we have the key for it, verify the signature. - t: accept a package only if it comes with at least one verified signature. - `all': same as t, except when the package has several signatures, in which case we verify all the signatures. This also applies to the \"archive-contents\" file that lists the contents of the archive." :type '(choice (const nil :tag "Never") (const allow-unsigned :tag "Allow unsigned") (const t :tag "Check always") (const all :tag "Check all signatures")) :risky t :version "27.1")
現在の値を確認します。
package-check-signature
allow-unsigned
現在の値はallow-unsignedになっていました。これは署名があれば検証するが、なければそのままインストールしてしまう設定です。このため署名を作ってない自分用のパッケージアーカイブからもインストールができる状態になっていました。
package-check-signatureに設定できる値
package-check-signatureには nil
'allow-signed
t
'all
が設定できます。
値 | 意味 |
nil | 署名のチェックをしない |
'allow-signed | 署名があり鍵がある時だけ署名の確認を行う |
t | 少なくとも1つの検証済み署名が必要 |
'all | 全ての検証済み署名が必要 |
使われている所
package-refresh-contents
package-refresh-contentsはpackage-archivesに設定されているパッケージアーカイブからパッケージの情報をダウンロードし読み込みます。
抜粋::
(when (and package-check-signature (file-exists-p default-keyring)) (condition-case-unless-debug error (package-import-keyring default-keyring) (error (message "Cannot import default keyring: %S" (cdr error))))))
package-check-signatureが設定されていればGnuPGの鍵を読み込みます。この鍵は署名の検証に使われます。なおdefault-keyringはデフォルトは以下で設定されている。
"/Applications/Emacs.app/Contents/Resources/etc/package-keyring.gpg"
package–download-one-archive
package–download-one-archiveはアーカイブからファイルをダウンロードしてキャッシュします。 アーカイブは(NAME . LOCATION)という形式のコンスセルです。 ダウンロードしたファイルはpackage-user-dir配下のpackages/NAME/FILEに保存されます。
抜粋::
(if (or (not package-check-signature) (member name package-unsigned-archives)) ;; If we don't care about the signature, save the file and ;; we're done. (progn (let ((coding-system-for-write 'utf-8)) (write-region content nil local-file nil 'silent)) (package--update-downloads-in-progress archive)) ;; If we care, check it (perhaps async) and *then* write the file. (package--check-signature location file content async ;; This function will be called after signature checking. (lambda (&optional good-sigs) (let ((coding-system-for-write 'utf-8)) (write-region content nil local-file nil 'silent)) ;; Write out good signatures into archive-contents.signed file. (when good-sigs (write-region (mapconcat #'epg-signature-to-string good-sigs "\n") nil (concat local-file ".signed") nil 'silent))) (lambda () (package--update-downloads-in-progress archive))))))))
package-check-signatureとpackage-unsigned-archivesの状態をみてpackage–check-signatureされるかどうかが分岐しています。package–check-signatureは署名ファイルをダウンロードし検証します。
package-unsigned-archives - 署名を確認しないパッケージアーカイブのリスト
package-unsigned-archivesに名前が設定されたパッケージアーカイブは署名のチェックを行いません。
(defcustom package-unsigned-archives nil "List of archives where we do not check for package signatures." :type '(repeat (string :tag "Archive name")) :risky t :version "24.4")
現在の値を確認します。
package-unsigned-archives
nil
こちらは設定していませんでした。
使われているところ
(member name package-unsigned-archives)
のようにこのpackage-unsigned-archivesにパッケージ名が含まれているかどうかをチェックしています。
package–download-one-archive
抜粋::
(if (or (not package-check-signature) (member name package-unsigned-archives)) ;; If we don't care about the signature, save the file and ;; we're done. (progn (let ((coding-system-for-write 'utf-8)) (write-region content nil local-file nil 'silent)) (package--update-downloads-in-progress archive)) ;; If we care, check it (perhaps async) and *then* write the file. (package--check-signature
package-install-from-archive
抜粋::
(package--with-response-buffer location :file file (if (or (not package-check-signature) (member (package-desc-archive pkg-desc) package-unsigned-archives)) ;; If we don't care about the signature, unpack and we're ;; done. (let ((save-silently t)) (package-unpack pkg-desc))
まとめ
署名の検査をする(もしくはしない)ための設定はpackage-check-signatureとpackage-unsigned-archivesの設定によって制御されていました。package-check-signatureは署名の検査を(どの程度)するか、package-unsigned-archivesはそのパッケージアーカイブが署名の検証が不要かを設定する変数でした。