ウェブサイトに security.txt を設置する機会がありましたので、作業した手順を残しておきます。
RFC9116(security.txt)とは
security.txt は、セキュリティに関する連絡先を記したテキストファイルで、インターネット関連技術の標準化団体である IETF(Internet Engineering Task Force)が発行する RFC(Request for Comments)9116 で規定されています。
ウェブサイトやサービスの脆弱性を発見した者に対し、セキュリティ担当者の連絡先を知らせるために設置します。

配置するパス
配置するパスが定められており、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)
今回設置したウェブサイトにはセキュリティ報告フォームなどは無かったため、メールアドレスを設定しました。
OpenPGP の設定
security.txt は改竄されていない事が確認できるよう、OpenPGP の平文署名(Cleartext Signature)でデジタル署名することが推奨されています。
今回設定したサーバー(Amazon Linux 2023)には GPG(GNU Privacy Guard)は入っていましたが、設定が済んでいなかったので Pinentry を使って進めていきます。
GnuPG のインストール
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # dnf install gpg pinentry Package gnupg2-2.3.3-4.el9.aarch64 is already installed. Dependencies resolved. ================================================================================ Package Architecture Version Repository Size ================================================================================ Installing: pinentry aarch64 1.1.1-8.el9 appstream 64 k Installing dependencies: libsecret aarch64 0.20.4-4.el9 appstream 155 k Transaction Summary ================================================================================ Install 2 Packages Total download size: 220 k Installed size: 653 k Is this ok [y/N]: y |
主鍵の作成
GPG で使用する鍵は主鍵と副鍵の 2 つがあります。主鍵は副鍵を生成・管理するために使用し、普段使いはしません。
また、GPG で作成できる鍵の用途には以下の 4 種類があります。
- Certify(証明)
- 公開鍵へ署名をするために使います。(主鍵)
- Sign(署名)
- ファイルなどのデータに対して電子署名を行うために使います。(副鍵)
- Authenticate(認証)
- SSH などのユーザー認証に使います。(今回は使用しない)
- Encrypt(暗号化)
- データの暗号化のために使います。(副鍵)
主鍵の用途に Certify(証明)だけを割り当てるように作成します。アルゴリズムには ECC を指定しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | $ 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 を指定しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | $ 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 など)にバックアップを取って、サーバーからは削除しておきます。
1 | $ gpg --export-secret-key -a <<FINGERPRINT>> > secret-masterkey.asc |
secret-masterkey.asc をバックアップを取り、削除します。
1 | $ shred -uz secret-masterkey.asc |
delete-secret-key コマンドで主鍵だけを削除します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | $ 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 |
正しく削除されたか確認します。
1 2 3 4 5 6 7 | $ gpg -K /home/USER/.gnupg/pubring.kbx ------------------------------- sec# ed25519 2025-06-17 [C] <<FINGERPRINT>> uid [ultimate] John Doe <admin@example.com> ssb ed25519 2025-06-17 [S] |
※ sec の右に # が付いていれば、主鍵の秘密鍵が削除されている状態です。
主鍵の失効証明書を削除
失効証明書も主鍵(secret-masterkey.asc)と同様、安全な場所にバックアップしてサーバーから削除します。
1 2 3 4 | $ ls .gnupg/openpgp-revocs.d/ <<FINGERPRINT>>.rev $ shred -uz .gnupg/openpgp-revocs.d/<<FINGERPRINT>>.rev |
副鍵の秘密鍵をエクスポート
副鍵の秘密鍵をエクスポートして、お使いの MUA(メールソフト)に設定します。
1 | $ gpg --export-secret-subkeys -a -o secret-subkey.asc admin@example.com |
副鍵の公開鍵をエクスポート
副鍵の公開鍵をエクスポートして、公開用ディレクトリにコピーします。
パーミッションの問題については .well-known ディレクトリの所有者を USER に変更することで対処しました。
1 2 3 4 5 | $ sudo mkdir /var/www/example.com/.well-known $ sudo chown USER: /var/www/example.com/.well-known $ 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)に作成します。
1 2 3 4 5 | 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 |
デジタル署名
security.txt にはデジタル署名する事が推奨されていますので、クリア署名(clearsign)を施します。
1 2 3 4 5 6 7 8 9 10 11 12 13 | $ 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 の公開用ディレクトリに配置します。
1 | $ mv security.txt.asc /var/www/example.com/.well-known/security.txt |
以上で、security.txt を公開することができました。
更新の自動化
security.txt には期限が設けられており、1 年以上を指定することは推奨されていません。
手動で更新するのも面倒なので、定期的に期限を更新してデジタル署名しなおすスクリプトを作成しました。
1 2 3 4 5 6 | #!/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 を使って、月に一度スクリプトを動かします。
1 | $ crontab -e |
1 | 0 0 1 * * ~/security.sh |
以上で security.txt の設定が完了しました!
設定の確認
internet.nl で security.txt のチェックができるので、設定したドメインを確認しておきましょう。
まとめ
後半はずっと OpenPGP に関する内容になってしまいましたが、自分がちゃんと理解できていなかった部分を記事にすることで整理できて良かったです。
参考にしたページ


コメント