certbotを使いLet's EncryptでECDSAな証明書を作る 2022年

鍵
©いらすとや.

5年前に Let's EncryptでECDSAな証明書 を書いたときはまだECDSAな証明書を作るのは少し面倒だった。現在は簡単にECDSA鍵なTLS証明書を発行できるようになっている。
今回「がとらぼ」を https://gato.intaa.net から https://intaa.net にドメイン内移転させるにあたり、メールサービスに使っていた https://intaa.net を別ホストから「がとらぼ」の動いているホストに移すことになった。そこで、別ホストのintaa.net証明書を破棄 (certbot delete)し、「がとらぼ」のホストで再発行することにした。そのついでにECDSAな鍵の証明書を再発行した。

certbotでECDSAな証明書を発行(新規)

# certbot certonly --key-type ecdsa -d example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Spin up a temporary webserver (standalone)
2: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Requesting a certificate for example.com
Input the webroot for example.com: (Enter 'c' to cancel): /var/www/example.com

Successfully received certificate.
Certificate is saved at: /usr/local/etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at:         /usr/local/etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2023-01-16.
These files will be updated when the certificate renews.

NEXT STEPS:
- The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

このように --key-type ecdsa をコマンドに追加するだけでECDSAな証明書が発行される。なお、鍵のタイプだけを指定した場合は P-256 (prime256v1=secp256r1) になるみたい。高めの暗号強度を得たくて P-384 (secp384r1) にしたいのであれば追加で --elliptic-curve secp384r1 を指定する。まぁ普通はsecp256r1で良さそう。
強度的にはECDH256が鍵長3076bitのRSAに少し及ばない程度。ECDH384だと鍵長7680bitのRSAに少し及ばない程度でこれはブログなどの普通のウェブサイトで使うにはオーバーキルだと思う。

設定と更新への影響

以降全ての証明書の発行でECDSAにするとかP-384にしたいということであれば設定ファイル /usr/local/etc/letsencrypt/cli.ini (FreeBSDのPKG/Portsでインストールした場合のPath)に書く。cli.iniはPKG/Portsでインストールした場合は存在しないので過去に設定ファイルを作っていないなら新規作成となる。

key-type = ecdsa
elliptic-curve = secp384r1

設定を書いてしまうとそれがデフォルトになるので以降に例えばRSAな鍵を作りたいなら コマンドで --key-type rsa を指定することになる。RSAの鍵長さを初期値の2048bitではなく4096bitにしたいとなれば --rsa-key-size 4096 を追加指定する。
設定を書くと既存の証明書(発行時にオプション指定なしの証明書)の次回以降の更新に影響が及ぶため十分に注意。証明書発行時に付けたオプションは設定ファイルより優先して更新時にも適用されます。つまり --key-type ecdsa--key-type rsa を付けて発行(更新)した証明書は次回以降の更新でも設定ファイルの指定を無視して発行時と同じ --key-type ecdsa や --key-type rsa を付けたのと同様に更新されます。

ECDSAな証明書に変更して更新

既存のRSAな証明書をただちにECDSAな証明書に「更新」したいということがある筈。

# certbot renew --cert-name example.com --key-type ecdsa --force-renewal
こんな感じでいける。

ハイブリッド証明書

5,6年前はECDSAな証明書を普通のウェブサイトで使用するなら閲覧者のブラウザとの互換性のためにRSAな証明書とのハイブリッドを勧めたが、2022年の今はもうハイブリッドにする必要はないように思う。よほど古いスマホ Android 2.xとか古いゲーム機のブラウザが非対応なくらい。
ECDSAなSSL証明書を作ってみる

RSAな証明書を作成済みとして、ECDSAな証明書を追加発行する。

# certbot certonly --key-type ecdsa --cert-name example.com-ecdsa

5年前と比べると、需要を満たすコマンドが多く追加されたようでとても簡単になってて良い感じ。

関連記事:

WordPressで特定カテゴリだけの検索機能をテーマに追加

検索
©いらすとや.

WordPressはテーマでサイト内全体から検索する機能があることが多い。テーマに検索機能がなくても例えば検索ウィジェットを使うというのもある。 ただ、サイトが肥大したときに例えば特定のカテゴリだけ検索したい/させたいということがある。検索フォームを拡張して閲覧者にカテゴリを選ばせるという方法もあるが、それって意外と閲覧者にとっては不親切。例えば、あるカテゴリ表示専用テンプレートがあって、そこにある検索フォームで検索するとそのカテゴリの記事だけが検索対象になるというのがわかり易いかと。

とあるカテゴリ表示専用のテーマ内テンプレートに検索フォームを書く。
1
2
3
4
5
6
<div class="ui search">
    <form class="search icon input" method="get" action="/search-hogehoge" role="search">
        <input type="search" class="search-field" placeholder="<?php echo esc_attr_x( '検索 …', 'placeholder' ) ?>" value="<?php echo get_search_query() ?>" name="s" title="<?php echo esc_attr_x( 'Search for:', 'label' ) ?>" />
        <button type="submit" role="button" class="btn btn-default right"/><i class="search icon" aria-hidden="true"></i></button>
    </form>
</div>

action="/search-hogehoge" と指定したので検索ワードを入力して検索ボタンを押すとhttps://example.com/search-hogehoge が表示される。通常は「 / 」つまりWordPressの大元である/index.phpが指定され、テーマ/search.phpがあればそれ、無ければ戻って/index.phpが使用されて検索結果が表示されることになる。
検索ワードは ?s=検索ワード という形でURLクエリに乗って送られる。(WordPress標準の形式)

テーマディレクトリにsearch-hogehoge.php(任意)のファイルを新規作成する。
テーマによってはサイト内全ての検索結果表示用のsearch.phpがあるかもなのでそれをコピペして作成するのが簡単かも。

 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
<?php
/*
Template Name: Certain-Category-SearchResults
*/
get_header("hogehoge"); //header-hogehoge.php が表示される   ?>
    <main class="bny-main" role="main">
<?php

//検索キーワード取得 普通に$_GET['s']では取得できないのでこの方法で
$enc_int = 'UTF-8';
$enc_ord = 'UTF-8, eucJP-win, SJIS-win';

$s = ''; //検索キーワード
if (isset($GLOBALS["_SERVER"]["REQUEST_URI"])) {
    $s = esc_textarea($GLOBALS["_SERVER"]["REQUEST_URI"]); //URLクエリ(パラメータ)を取得
    if(strpos($s, '?s=') !== false) {
        $s =explode('?s=', $s)[1]; //URLクエリを ?s= で分断してその後半を検索ワードとして抜き出す
        $s = rawurldecode($s);
        $s = mb_convert_encoding($s, $enc_int, $enc_ord);
        $s = trim(mb_convert_kana($s, 's'));
        $s = htmlspecialchars($s, ENT_QUOTES, $enc_int); //検索ワードをエスケープ処理
    } else {
        get_template_part('template-parts/page', 'top');  //テーマディレクトリ内のtemplate-parts/page-top.phpが表示される
        get_footer("hogehoge");  //footer-hogehoge.phpが表示される
        exit;
    }
} else {
    //検索キーワードが無かった場合はトップページとフッタを表示して終了 または見つからなかった旨の表示でも
    get_template_part('template-parts/page', 'top');  //テーマディレクトリ内のtemplate-parts/page-top.phpが表示される
    get_footer("hogehoge"); //footer-hogehoge.phpが表示される
    exit;
}

//クエリーに検索ワードをセット
$args = array(
  's' =>  $s, // 検索キーワード
  'cat' => 18, // 検索対象をカテゴリID 18に限定する
);
//クエリーをセットしたので後は普通に記事表示させる処理でOK

$query = new WP_Query($args);

if (have_posts()) : ?>
    <header class="page-header">
        <h2 class="page-title">
            <?php printf(__('Search Results for: %s', 'mytheme'), '<span>' . $s . '</span>'); ?>
       </h2>
    </header><!-- .page-header -->
<?php endif; ?>

<?php //あとは検索でヒットした記事を表示するループを書く。数行前のif (have_posts()) :から(最後まで) search.phpと同様の処理を書けばOKです ?>

上のコードではカテゴリIDが18のカテゴリに含まれる記事だけが抽出される。
2〜4行目は普通にphpのコメントだが、WordPressでは3行目のTemplate Name: Certain-Category-SearchResultsが意味を持ち、これでCertain-Category-SearchResultsというテンプレートが認識され、そのテンプレートを選択するとこのファイルが使われるようになる。

スラッグが /search-hogehoge の固定記事を作成する。記事のタイトルと本文は無しでも可だがタイトルが空だと判りにくいので何かメモでも入力しておく。その固定記事の「ページ属性」でテンプレートを変更する。その選択するテンプレート上で作成した「Certain-Category-SearchResults」。

WordPressのおせっかい機能のせいで、テーマ/search.php か /index.php以外では検索ワードの「?s=検索ワード」が無効化扱いになるので テーマ/search.php や /index.php以外で検索ワードが受け取りにくい。そのため、普通には検索結果を表示するためのテンプレートファイルを増やすというのができない。
そこで、ちょっとインチキな方法で検索結果テンプレートを作ってみたという内容でした。もっとスマートな方法をご存知の方は教えていただけると嬉しいです。

Up