ウェブサイトに security.txt を設置し OpenPGP でデジタル署名する

GNU Privacy Guard Amazon Linux
このサイトはアフィリエイト広告(Amazonアソシエイト含む)を掲載しています。
スポンサーリンク

ウェブサイトに security.txt を設置する機会がありましたので、作業した手順を残しておきます。

RFC9116(security.txt)とは

security.txt は、セキュリティに関する連絡先を記したテキストファイルで、インターネット関連技術の標準化団体である IETF(Internet Engineering Task Force)が発行する RFC(Request for Comments)9116 で規定されています。

ウェブサイトやサービスの脆弱性を発見した者に対し、セキュリティ担当者の連絡先を知らせるために設置します。

セキュリティ対策の強化に有効なsecurity.txtの導入と活用について
IssueHunt Oneは、DevSecOps、脆弱性診断、バグバウンティをワンストップで提供する、日本唯一のソリューションです。開発段階からホワイトハッカーによる診断まで、一気通貫でプロダクトセキュリティをサポートします。

配置するパス

配置するパスが定められており、https://example.com/.well-known/security.txt に配置する必要があります。

フォーマット

必須

  • Contact:(報告フォームの URL やメールアドレス、電話番号など)
  • Expires:(有効期限:1 年以内)

オプション

  • Preferred-Languages:(対応可能な言語)
  • Policy:(セキュリティポリシーページの URL)
  • Acknowledgements:(謝辞掲載ページの URL)
  • Hiring:(セキュリティ関連求人の URL)
  • Canonical:(この security.txt の URL)
  • Encryption:(PGP 暗号化キー の URL)

今回設置したウェブサイトにはセキュリティ報告フォームなどは無かったため、メールアドレスを設定しました。

Contact にメールアドレスを記載する場合、Encryption の項目で PGP(Pretty Good Privacy)公開鍵を指定する事が推奨されています。

RFC 9116: A File Format to Aid in Security Vulnerability Disclosure
When security vulnerabilities are discovered byresearchers, proper reporting channels are often lacking. As a result,vul...

OpenPGP の設定

security.txt は改竄されていない事が確認できるよう、OpenPGP の平文署名(Cleartext Signature)でデジタル署名することが推奨されています。

今回設定したサーバー(Amazon Linux 2023)には GPG(GNU Privacy Guard)は入っていましたが、設定が済んでいなかったので Pinentry を使って進めていきます。

GnuPG のインストール

dnf install gpg pinentry
(out) Package gnupg2-2.3.3-4.el9.aarch64 is already installed.
(out) Dependencies resolved.
(out) ================================================================================
(out)  Package           Architecture    Version              Repository         Size
(out) ================================================================================
(out) Installing:
(out)  pinentry          aarch64         1.1.1-8.el9          appstream          64 k
(out) Installing dependencies:
(out)  libsecret         aarch64         0.20.4-4.el9         appstream         155 k
(out) 
(out) Transaction Summary
(out) ================================================================================
(out) Install  2 Packages
(out) 
(out) Total download size: 220 k
(out) Installed size: 653 k
(out) Is this ok [y/N]: y

以降は root 権限ではなく、ユーザー権限で作業します。

主鍵の作成

GPG で使用する鍵は主鍵と副鍵の 2 つがあります。主鍵は副鍵を生成・管理するために使用し、普段使いはしません。

また、GPG で作成できる鍵の用途には以下の 4 種類があります。

  • Certify(証明)
    • 公開鍵へ署名をするために使います。(主鍵)
  • Sign(署名)
    • ファイルなどのデータに対して電子署名を行うために使います。(副鍵)
  • Authenticate(認証)
    • SSH などのユーザー認証に使います。(今回は使用しない)
  • Encrypt(暗号化)
    • データの暗号化のために使います。(副鍵)

主鍵の用途に Certify(証明)だけを割り当てるように作成します。アルゴリズムには ECC を指定しました。

[user@localhost] $ gpg --full-gen-key --expert
gpg (GnuPG) 2.3.3; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: directory '/home/USER/.gnupg' created
gpg: keybox '/home/USER/.gnupg/pubring.kbx' created
Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
   (9) ECC and ECC
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (13) Existing key
  (14) Existing key from card
Your selection? 11

Possible actions for this ECC key: Sign Certify Authenticate
Current allowed actions: Sign Certify

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? S(← Sign の役割を取り除く)

Possible actions for this ECC key: Sign Certify Authenticate
Current allowed actions: Certify

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? Q
Please select which elliptic curve you want:
   (1) Curve 25519
   (2) Curve 448
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (9) secp256k1
Your selection? 1
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: John Doe
Email address: admin@example.com
Comment:
You selected this USER-ID:
    "John Doe <admin@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O


          lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
          x Please enter the passphrase to                       x
          x protect your new key                                 x
          x                                                      x
          x Passphrase: ________________________________________ x
          x                                                      x
          x       <OK>                              <Cancel>     x
          mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj


We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /home/USER/.gnupg/trustdb.gpg: trustdb created
gpg: key 1234567890123456 marked as ultimately trusted
gpg: directory '/home/USER/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/USER/.gnupg/openpgp-revocs.d/<<FINGERPRINT>>.rev'
public and secret key created and signed.

pub   ed25519 2025-06-17 [C]
      <<FINGERPRINT>>
uid                      John Doe <admin@example.com>

副鍵の作成

副鍵には Sign(署名)と Encrypt(暗号化)を割り当てます。アルゴリズムには RSA を指定しました。

[user@localhost] $ gpg --edit-key --expert admin@example.com
gpg (GnuPG) 2.3.3; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  ed25519/1234567890123456
     created: 2025-06-17  expires: never       usage: C
     trust: ultimate      validity: ultimate
[ultimate] (1). John Doe <admin@example.com>

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 8

Possible actions for this RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? Q
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y

          lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
          x Please enter the passphrase to unlock the OpenPGP secret key: x
          x "John Doe <admin@example.com>"                                x
          x 255-bit EDDSA key, ID 1234567890123456,                       x
          x created 2025-06-17.                                           x
          x                                                               x
          x                                                               x
          x Passphrase: _________________________________________________ x
          x                                                               x
          x         <OK>                                   <Cancel>       x
          mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  ed25519/1234567890123456
     created: 2025-06-17  expires: never       usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/9876543210987654
     created: 2025-06-17  expires: never       usage: SE
[ultimate] (1). John Doe <admin@example.com>

gpg> save

主鍵のバックアップと削除

主鍵が漏れるとすべての鍵の有効性が失われるため、安全な場所(YubiKey など)にバックアップを取って、サーバーからは削除しておきます。

gpg --export-secret-key -a <<FINGERPRINT>> > secret-masterkey.asc

secret-masterkey.asc のバックアップを取り、削除します。

shred -uz secret-masterkey.asc

delete-secret-key コマンドで主鍵だけを削除します。

[user@localhost] $ gpg --delete-secret-key admin@example.com
gpg (GnuPG) 2.3.3; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

sec  ed25519/1234567890123456 2025-06-17 John Doe <admin@example.com>

Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y

          lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
          x Do you really want to permanently delete the OpenPGP secret key: x
          x "John Doe <admin@example.com>"                                   x
          x 255-bit EDDSA key, ID 1234567890123456,                          x
          x created 2025-06-17.                                              x
          x ?                                                                x
          x                                                                  x
          x     <Delete key>                                    <No>         x
          mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj
※主鍵に対しては「Delete key」を選択

      lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
      x Do you really want to permanently delete the OpenPGP secret subkey key: x
      x "John Doe <admin@example.com>"                                          x
      x 4096-bit RSA key, ID 9876543210987654,                                  x
      x created 2025-06-17 (main key ID 1234567890123456).                      x
      x ?                                                                       x
      x                                                                         x
      x      <Delete key>                                         <No>          x
      mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj
※副鍵に対しては「No」を選択

gpg: deleting secret subkey failed: Operation cancelled
gpg: admin@example.com: delete key failed: Operation cancelled

正しく削除されたか確認します。

gpg -K
(out) /home/USER/.gnupg/pubring.kbx
(out) -------------------------------
(out) sec#  ed25519 2025-06-17 [C]
(out)       <<FINGERPRINT>>
(out) uid           [ultimate] John Doe <admin@example.com>
(out) ssb   ed25519 2025-06-17 [S]

※ sec の右に「#」が付いていれば、主鍵の秘密鍵が削除されている状態です。

主鍵の失効証明書を削除

失効証明書も主鍵(secret-masterkey.asc)と同様、安全な場所にバックアップしてサーバーから削除します。

ls .gnupg/openpgp-revocs.d/
(out) <<FINGERPRINT>>.rev
(out) 
shred -uz .gnupg/openpgp-revocs.d/<<FINGERPRINT>>.rev

副鍵の秘密鍵をエクスポート

副鍵の秘密鍵をエクスポートして、お使いの MUA(メールソフト)に設定します。

gpg --export-secret-subkeys -a -o secret-subkey.asc admin@example.com

副鍵の公開鍵をエクスポート

副鍵の公開鍵をエクスポートして、公開用ディレクトリにコピーします。

パーミッションの問題については .well-known ディレクトリの所有者を USER に変更することで対処しました。

sudo mkdir /var/www/example.com/.well-known
sudo chown USER: /var/www/example.com/.well-known
(out) 
gpg --export -a -o pgp-key.txt admin@example.com
cp pgp-key.txt /var/www/example.com/.well-known/

security.txt を作成

secutiry.txt の雛形をユーザーディレクトリ直下(/home/USER/security.txt)に作成します。

Contact: mailto:admin@example.com
Expires: 2025-09-01T00:00:00.000Z
Preferred-Languages: ja, en
Canonical: https://example.com/.well-known/security.txt
Encryption: https://example.com/.well-known/pgp-key.txt

Expires は、1 年以内の日時を指定してください。

デジタル署名

security.txt にはデジタル署名する事が推奨されていますので、クリア署名(clearsign)を施します。

[user@localhost] $ gpg --clear-sign security.txt

          lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
          x Please enter the passphrase to unlock the OpenPGP secret key: x
          x "John Doe <admin@example.com>"                                x
          x 255-bit EDDSA key, ID 1234567890123456,                       x
          x created 2025-06-17 (main key ID 1234567890123456).            x
          x                                                               x
          x                                                               x
          x Passphrase: _________________________________________________ x
          x                                                               x
          x         <OK>                                   <Cancel>       x
          mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

クリア署名をしたファイルを、Web の公開用ディレクトリに配置します。

mv security.txt.asc /var/www/example.com/.well-known/security.txt

以上で、security.txt を公開することができました。

更新の自動化

security.txt には期限が設けられており、1 年以上を指定することは推奨されていません。

手動で更新するのも面倒なので、定期的に期限を更新してデジタル署名しなおすスクリプトを作成しました。

#!/bin/bash
# 期限を 3 ヶ月後に書き換える
EXPIRE=`date -d "$(date '+%Y%m01') 3 month " "+%Y-%m-%dT00:00:00.000Z"`
sed -i "s/Expires:.*/Expires: $EXPIRE/g" security.txt
gpg --clear-sign --no-tty --batch --yes --pinentry-mode loopback --passphrase="パスフレーズ" security.txt
mv -f security.txt.asc /var/www/example.com/.well-known/security.txt

USER の crontab を使って、月に一度スクリプトを動かします。

crontab -e
0 0 1 * * ~/security.sh

以上で security.txt の設定が完了しました!

設定の確認

internet.nl で security.txt のチェックができるので、設定したドメインを確認しておきましょう。

Test for modern Internet Standards like IPv6, DNSSEC, HTTPS, DMARC, STARTTLS and DANE.
Test for modern Internet Standards IPv6, DNSSEC, HTTPS, HSTS, DMARC, DKIM, SPF, STARTTLS, DANE, RPKI and security.txt

まとめ

後半はずっと OpenPGP に関する内容になってしまいましたが、自分がちゃんと理解できていなかった部分を記事にすることで整理できて良かったです。

参考にしたページ

PGP/GPGについての情報整理
GPG で始める暗号・署名ライフ - blog.livewing.net
PGP (Pretty Good Privacy) の実装のひとつである GPG (GNU Privacy Guard) を使用して鍵を生成する方法をゼロから紹介します。 また、ファイルを暗号化・署名してやりとりする方法や、 Git のコミ...

コメント

タイトルとURLをコピーしました