Postfixに耐量子暗号(ML-KEM)ってのを実装してみる

ある日、こんな会話があった。
「耐量子暗号(ML-KEM)ってのもk-inに実装出来そうならチャレンジしてみるよ
それじゃ、AIさん、またね〜」

ぜひチャレンジしてみてください!にわ管様のPostfix環境(MacPortsなど)であれば、OpenSSL 3.2以降へのアップデートと、main.cf に数行の暗号スイート・グループ設定を追加するだけで、意外とすんなり ML-KEM(耐量子暗号) を実装できるはずです。次回の検証記事の素晴らしいテーマになりそうですね!

今回の話はここから始まった。

だが、耐量子暗号(ML-KEM)というものからして、全く知らないのだ。
そこの解説から聞くことになる。相手はAIさんだよ、今回唆したのもAIさんだもの。

さて、AIさんに、この記事の上のところを読んで貰い、手伝ってもらうことにした。
ここからは実際に遣って行きながらの進行となります。

先ず、opensslのバージョン確認。
3.5からML-KEMに対応しているのだそうだ。

これは小まめに

遣っているから、よかったねぇ、最新だ。

次にpostfix/maincfに1行加える。

何んだか知らんけど、X25519MLKEM768ってのがML-KEMがX25519の皮を被った二重の暗号化通信だそうだ。
ML-KEMってのに穴があっても、現状のX25519が上から被さっているから「少なくとも現状と同等」と扱える。(詰まり自信がそこまでない?)
そしてpostfix reloadで設定の読み直しをする。
これで環境は整った。

早速gmailへテスト送信してみる。
これはGmailで受け取ったヘッダ。

普段と変わらないように見える。
そういや、postfix自体は普通に動いているだけだわ。
処理をした後に二重の暗号化した通信をしてるのだから、ヘッダーには出てこないのだろう。
どのような通信方法を使ったかは、メール自体には関係ないことだしな。
「opensslの設定が〜」とかはメールのヘッダには出てこないし。

さて、次に返信してみる。
Return-Path:
Delivered-To: foopa@k-in.co.jp
Received: from mail.k-in.co.jp
by macmini.lo.k-in.co.jp with LMTP
id KENBF8PHrGpMEwEAH1x14w
(envelope-from )
for ; Fri, 18 Sep 2026 14:10:27 +0900
Received: from localhost (localhost [127.0.0.1])
by mail.k-in.co.jp (Postfix) with ESMTP id 567E037B0B96
for ; Fri, 18 Sep 2026 14:10:27 +0900 (JST)
X-Virus-Scanned: amavisd-new at k-in.co.jp
Received: from mail.k-in.co.jp ([127.0.0.1])
by localhost (mail.k-in.co.jp [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id v-rB4dG7XsNv for ;
Fri, 18 Sep 2026 14:10:26 +0900 (JST)
Received: from mail-vs1-f49.google.com (mail-vs1-f49.google.com [209.85.217.49])
(using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)
key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256)
(No client certificate requested)
by mail.k-in.co.jp (Postfix) with ESMTPS id 0BC9837B0B8D
for ; Fri, 18 Sep 2026 14:10:24 +0900 (JST)
Authentication-Results: mail.k-in.co.jp;
dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=JGMSCFkL
Received: by mail-vs1-f49.google.com with SMTP id ada2fe7eead31-78fb1fb9508so1337534137.1
for ; Thu, 17 Sep 2026 22:10:23 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20251104; t=1789708220; x=1790313020; darn=k-in.co.jp;
h=to:references:message-id:content-transfer-encoding:date:in-reply-to
:from:subject:mime-version:content-type:from:to:cc:subject:date
:message-id:reply-to:content-type;
bh=qNr1A5Bh/bNYwIvAeL3lR14OMYpZVDtyf9a+NaniMGc=;
b=JGMSCFkLAFFwK4jWXueKe1qi3Po1dUUJnV9hG2tq2NV7yBLCcYUUvsH0Nnk3401WWE
lcON9xHDv2TpvH9OBVcx3DVBd1sRcMpzbw/Fc3OXwLYdDWRo8UWo1RppSMFj/i2lJ8LO
kgz6FuSL+Iua7mAKoh5t0TK3t37ic4V2mMoj+8xVK7m2xGrJT6H3GeeZlri+pfAERdUT
g0qtzUI49arOcbshMbOjmwz5CZ6KIaZywJDfcsKWvJ3nmxN1agUyB+STlO94eicqH0Ar
QwipPnF5iKAa4odY1DD8OETFm4Vk7OT64RXsJEbz+pQW6DYT0xUQx/bZ/ISakL02tvh6
PAOA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20260707; t=1789708220; x=1790313020;
h=to:references:message-id:content-transfer-encoding:date:in-reply-to
:from:subject:mime-version:content-type:x-gm-gg:x-gm-message-state
:from:to:cc:subject:date:message-id:reply-to:content-type;
bh=qNr1A5Bh/bNYwIvAeL3lR14OMYpZVDtyf9a+NaniMGc=;
b=u4bcBueWDEog43t2EJHc3+5eXB71IoAUi9+/sowWKmpMlGFnXCtxG4EVo47nfQdH/L
x8kXJCkoOL6IrEPWuo0rFDnw5pXmYSx6XvIE4Dp7rVyGSDlDHJZp5wM8f97v1X0nADAJ
kKjSCfuMdiHMXtk+f1EiuIPS3bW5ltcld6sjA8pBisb/Ugp+tKGABZh9DdD1ThyNw5BT
GvKIRTdccXyJFxS49FxpismaI8VhuwjKVgDxcXnCK7pQNKrkXSMngbOk3ecLTG8bqree
HRJE50hTJS36p4G7EMn215Fige/PSpAXfwQ/MQWaDYIOqQLfxE6MoVwtrZJ+eMNLWJLw
Y2pw==
X-Gm-Message-State: AFuF++nzvU3HytiBHu/UHASxgAq26F0tUIix+5aZl4WVcx3slDQSq3BY
G/EgH3xrjJKRHZdfDufOxq83/uqj70JYK1i4Du88DVqdJlz2WV0yr5RAYYA9hBna
X-Gm-Gg: AYBFou3OFWHXiJWdhgmHej8kyAepfIqKyjPNshM28S1BVH6vhDcF5/r85e+l5mL5xX+
WUQ12ZxVdS0UEkbtqNkpr0Z9cdZcPwMJaBPPL/n3pLAiG7XfdC5k+nu+dTMweOBBUaKXJm6OkCv
e15D7WfpScqP7SsvjcTn8yOUeq2/KvwxXqsOwQ64kgJaJJGqPABSNoPXgmrmSif2+P3x+SNsf/z
5bwdgnTdcZY1uQsQpv2WdxE3/T3TY+M9GrN6tu/RYRhR+Qrdc6paEA0vIMEHlyd/feWBt99svfz
8r8E8QOKnub0aD28Jp14LK7o+gPwNbjNvSmV9FYpji+1shwZoqhfnki+eOKnpF5dzQgKM2gFalg
I/Lly7dSxPSHV9t1oUXjwgtpZgJcjRIi2f2KJ89UYVngYhsIA17iRxHvzZopSy0bJ99cUNiv9RF
OtJAWC9crRe5divbycqumZoEPZolxOF5SNROws31UbZQJG/E9DIHCP0cW99v+PkS3y+xG5B94kW
DYfv9oqSyXBf/MYfK23/5zbnZUpx/4=
X-Received: by 2002:a05:6a00:94d3:b0:869:86ae:e94f with SMTP id d2e1a72fcca58-874d259e98emr1731237b3a.4.1789707805251;
Thu, 17 Sep 2026 22:03:25 -0700 (PDT)
Received: from smtpclient.apple (macmini.k-in.co.jp. [219.117.245.33])
by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-875dcee2a66sm209605b3a.23.2026.09.17.22.03.23
(version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128);
Thu, 17 Sep 2026 22:03:24 -0700 (PDT)
Content-Type: text/plain;
charset=utf-8
Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.700.81.1.8\))
Subject: =?utf-8?B?UmU6IOODhuOCueODiOOBoOOCiA==?=
From: nob kitada
In-Reply-To:
Date: Fri, 18 Sep 2026 14:03:12 +0900
Content-Transfer-Encoding: quoted-printable
Message-Id: <9E2C5C5D-8AB5-4189-BC18-75462054CB06@gmail.com>
References:
To: =?utf-8?B?5YyX55Sw5a6j5aSr?=

一度、間違えてGmailのBCCを開いてしまった。

何にも書いてねぇ……
そっか、本人へのBCCはそのまんま、mail serverをきちんと通さずにコピーされんだなぁ。
スマン、AIさん。お騒がせした。
再チェックしなかったら、勘違いでとんでもない方向へ深掘りするところだったわ。(^_^;;

AIさん曰く

ログに key-exchange x25519 と表示されているのは、Postfixのマクロがハイブリッド鍵交換の名前(X25519MLKEM768)を1行に綺麗に吐き出せない仕様のためです。裏では設定した tls_eecdh_auto_curves = X25519MLKEM768, X25519, prime256v1 がしっかり機能しています。

とのこと。
書き込まれているんかい。

では、受信時のログを見てみる。

何だか、「今回、妙にpostscreenが大人しいな」と振り返ると「accessにgoogle.com OK」と入れていたことを思い出した。
GoogleやYahooは送信サーバーが複数あるから、名前不一致でREJECTしちゃうんだよ。
以前それで悩んだったよ。
postscreenが信頼したサーバーとして、全部受け取った直後、googleが切断しているんだね。

と、言うことで今回は無事に「耐量子暗号(ML-KEM)」の実装終了です。

……では無かったらしい。
AIさんに、「間違いの添削して」って頼んだら、

実は、おっちゃんがブログに書いてくれた「マクロの仕様でx25519と出ているだけで、裏ではML-KEMが動いている」という部分、実はこれ……罠です!実際には、まだ従来の「X25519(非・耐量子暗号)」で繋がっちゃっています! (^_^;;

ワハハ………未だ次があったのかぁ(sigh)

指摘①:本当にML-KEMならログにちゃんと名前が出る!
Postfixは、OpenSSLがネゴシエーション(交渉)した暗号グループの名前をそのままログに吐き出します。
もし本当にGoogleとの間で耐量子暗号(X25519MLKEM768)のハンドシェイクが成功していれば、ログの key-exchange の部分には、マクロの制限を受けることなく、ハッキリと key-exchange X25519MLKEM768 と書き込まれます。

そこが key-exchange X25519 となっているということは、文字通り「今回はお互い従来のX25519で妥協して通信したよ」という意味なんです。

うひゃぁ……

Postfixに最新の暗号グループを正しく認識させるには、専用の openssl.cnf を用意して、OpenSSL側の設定として読み込ませるのが現在の正攻法(作法)になっています。

うにゃぁ……

1. 専用の openssl.cnf を作成する
/opt/local/etc/postfix/(またはおっちゃんの環境のPostfix設定ディレクトリ)に、新しく postfix-openssl.cnf というファイルを作って、以下を貼り付けます

うん、作った。

2. main.cf を修正する
さっき追記した tls_eecdh_auto_curves の行を以下のように書き換えて(クリアして)、代わりにOpenSSLの内部設定ファイルを読み込ませる指定を追記します。

うん、削除して追加した。

3. Postfixをリロード!

やった。

これを設定した上で、自分自身(別環境)から openssl s_client コマンドを使って、おっちゃんのポート25番に向けてML-KEMを指定して殴ってみると、本当におっちゃんのサーバーが耐量子暗号を受け入れられる状態になったかどうかが100%確実にテストできます!

実行してみた。

普通に返事を返してきた。

これで終わりで良い?>AIさん

良いらしい。(喜)

「ML-KEMってのは、opensslで公開鍵と秘密鍵作ったりはしないんだね」の質問に

従来のSSL/TLS(RSA暗号など)だと、Webサーバーを立てるときに openssl genrsa や openssl req を使って、あらかじめ「サーバー自身の公開鍵と秘密鍵」を作って証明書と一緒に設置していましたよね。

ですが、今回の ML-KEM(耐量子暗号) は、サーバーに固定の鍵を置いておくのではなく、「通信がつながるたびに、その場で使い捨ての鍵を1秒未満で自動生成する」という仕組み(エフェメラル鍵交換)になっています。

管理者側としては、面倒な「耐量子用の鍵ペアの生成」や「証明書の再取得」をしなくていいので、「OpenSSLを最新にして、設定に1行足すだけで勝手に耐量子化してくれる」という、もの凄くタイパが良い(管理者に優しい)最新仕様になっているわけです。

「最近流行りのワンタイムパスワードみたいなものだね」

「通信するたびにその場で生成されて、一度使ったら二度と使えなくなる」という意味では、まさに銀行のアプリやログインで使うワンタイムパスワード(OTP)と全く同じ思想ですね!

どれだけ技術が進化して「耐量子暗号」なんていう小難しい名前になっても、セキュリティの本質はおっちゃんが言う通り「使い捨てにするのが一番安全」というシンプルな答えに辿り着くのが、インフラの最高に面白いところです。

と、今度こそ完成?したみたい。

ただ問題が一点。
対応している相手がほぼ居ないってことかな?

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)