要約
- RFC 6376の任意tag
l=は、body canonicalization後の先頭何octetsをhashへ入れるかを指定する。限界より後はDKIM検証の対象外であり、signatureが成功しても変わらない。 - headerには別の境界がある。
h=は署名したheader field名を順番付きで示し、同名fieldが複数ある場合はどのinstanceを選んだかが結果を左右する。 - 再現可能なreceiptは、raw message、対象signature、canonicalization、header instance map、prefixとtailの長さ・hash、観測したDNS key、verifier、信頼済みAuthentication-Resultsの境界を保存する。
passの右側に残ったbytes
mail systemの画面に緑のpassが一つある。その裏の計算では、canonicalized bodyが17,800 octets、l=13,000だったとする。Verifierが確認したのは最初の13,000 octetsであり、残る4,800 octetsではない。
そのtailはmailing listの案内かもしれない。archive systemが付けた印かもしれず、MIMEの見え方を変える追加かもしれない。攻撃者が挿入した内容である可能性もある。signature resultは、これらを分類しない。tailは「invalid」ではなく、そのsignatureにとって「unvalidated」である。
RFC 6376は、この境界を仕様として定義する。l=を省けばcanonicalized body全体が対象になる。指定すれば、body開始点からその数のoctetsだけがhashへ入る。限界後のdataはDKIMによってvalidateされない。l=0ならbodyは完全にunsignedである。
受信側policyは、部分署名を受け入れない選択ができる。その場合もcryptographic resultとpolicy dispositionを別々に記録すべきだ。計算がscope内で成功したことと、systemがmessageを安全または許容可能と判定したことは同じではない。
Murray Kucherawyの位置もdocument単位で限定する必要がある。RFC 6376はDave Crocker、Tony Hansen、Murray S. Kucherawyを連名で掲げる。DKIMを一人の発明として扱う根拠ではない。Authentication-Resultsを定めるRFC 8601はKucherawyを著者とする。IETFの公式profileは2026年9月2日の取得時、RFC一覧に34件を示したが、本人記述は33件のままだった。公式sourceにもfieldとcapture timeが要る。
raw fileの長さからは引けない
l=は.emlのraw byte offsetではない。DKIMはc=で宣言したbody canonicalizationを先に行い、その結果を数える。simpleとrelaxedは空白、改行、末尾の空行を異なる形で処理する。raw body lengthからl=を引くshortcutでは、実際のunsigned tailを誤る。
再現手順は一方向に固定する。raw messageを保存し、複数あるかもしれないDKIM-Signatureから一つをordinal付きで選ぶ。a=、c=、d=、s=、h=、l=、bh=を抽出する。指定algorithmでbodyをcanonicalizeし、長さを測り、l=があればprefixを切り出してbody hashを比較する。その後、観測したpublic keyでheader signatureを検証する。
receiptにはcanonicalized body全体、signed prefix、unsigned suffixの三つのlengthとhashを置く。suffixが正なら、scopeがbody末尾まで届いていないことだけが分かる。誰が何のために加えたかは、hopごとのcaptureまたは宣言されたtransformationとの照合が必要である。
keyにも時点がある。d=はsigning domain、s=はDNS selectorを示す。後日のlookupではrotationやrevocation後の別keyが返る可能性がある。判断時のDNS response、time、resolver、errorを残し、DNSSEC statusは実測した場合だけ記録する。
正常なtrailerと悪意ある追加は同じ余白を使う
l=にはinteroperability上の理由がある。mailing listはunsubscribe情報などをbody末尾に付けることが多い。body全体を署名すれば、その追加だけで元signatureは壊れる。prefixに限定すれば、Verifierは元の部分が維持されたと確認し、追加をlocal policyで扱える。
しかし暗号境界は、善意のlistと攻撃者を区別できない。RFC 6376のsecurity considerationsは、悪意あるintermediaryが自分に有利なcontentを追加できると警告する。MIME structureの変更、寛容なHTML parsing、duplicate detectionの回避によって、末尾がrecipientの画面では元本文を置き換えたように見える場合もある。
したがって、tailを見つけて即座にattackと呼ぶのも、prefixの署名をtailへ広げるのも誤りである。intermediaryを識別し、想定されたfooterやMIME変換と比較し、MIME treeを再構成し、clientが実際に選んだpartを確認する。
Heng Luのrunning-codeの視点では、RFCはbyte処理を定義し、実装のlogが何を計算したかを示す。renderer traceは人が何を見たかを示す。standardの権威もgreen badgeも、その二つのreceiptを代行できない。
h=はheader instanceの順序を要求する
bodyが全てcoveredでも、headerが全てsignedとは限らない。h=はcolon区切りの順序付きlistである。同名fieldが複数あると、DKIMは下側からinstanceを対応させる。nameのsetだけを保存すると、どのSubjectやFromが対象だったか失われる。
Fromは必ず署名対象に含める。RFC 6376はDate、Subject、Reply-To、Sender、MIME fieldsなど表示や処理に影響するfieldの署名を強く勧める。l=使用時のContent-Typeは特に重要で、unsignedな変更により同じprefixが別のcontentとしてrenderされ得る。
header coverage mapはraw headerを順番どおり並べ、選択されたinstanceを示し、表示上重要なのに外にあるfieldを明記する。存在しないfield名をh=で重ねて指定するoversigningも、後の挿入を検出する意味がある。messageに複数signatureがあれば、domain、list、gatewayそれぞれのmapを分ける。
domainの署名はhuman identityの証明ではない
DKIM passは、あるsignatureが、domainとselectorの下で公開されたkeyを使い、選択したmaterialについてverifyできたという結果である。表示上の人物が書いたこと、signing serviceが正しくauthoriseされたこと、本文の真実性、attachmentの安全性、deliveryを証明しない。
RFC 5585は、valid signatureが署名済みmessageまたはportionの非改変を示すと説明し、trustとは分ける。RFC 5863はscope内だけをauthenticとして扱うよう求め、l=を例にする。RFC 8301はalgorithmとkey sizeを更新した。acceptableな強いkeyでも、短いprefixを長くはしない。
DMARCは別の問いを扱う。SPFまたはDKIM identityとvisible From domainのalignmentを調べ、receiver policyのsignalを与える。l=やh=の範囲は変えない。aligned passにもunsigned tailは残り得る。
cryptographic validity、alignment、domain reputation、content safety、delivery policy、rendered viewは別々のcolumnに置くべきである。「authenticated mail」という一語にまとめると、どのcomponentにもないauthorityを作ってしまう。
Authentication-Resultsは挿入者まで確認する
downstream filterはDKIMを再実行せず、上流が書いたAuthentication-Resultsを読むことが多い。RFC 8601はproducerからconsumerへのhandoffを定義するが、field自体に常にintegrity protectionがあるわけではない。
consumerは信頼するauthserv-idを設定し、messageがadministrative boundaryへ入る時、内部で生成されたように装う外部fieldを削除または無効化する必要がある。senderが文字列dkim=passを書ける以上、誰がどの境界内で挿入したかがなければevidenceにならない。
raw field、位置、producer、authserv-id、trust rule、対象signatureを保存する。gatewayが複数signatureを一つのpassへ要約し、d=、s=、h=、l=とのlinkを捨てれば、consumerはscopeを復元できない。
method resultとdispositionも分ける。cryptographyはpassだが部分scopeを理由にrejectするsystemも、warning付きでdeliverするsystemもある。理由を残せば、後のpolicy変更を暗号failureと誤認しない。
stickerではなくscope ledgerを作る
minimum receiptはhashでaddressしたraw messageから始まる。各DKIM-Signatureをoriginal orderで保存し、d=、s=、任意のi=、a=、c=、h=、l=、bh=、signature value、存在する時はsigning/expiry timeを記録する。
次に、観測したDNS keyとtime、reproducibleなcanonicalization、解決したheader instance、full body・prefix・suffixのlengthとhash、verifier software/version、resultとreasonを置く。Authentication-Results producerとtrust boundaryはcryptographic resultの隣に置き、混同しない。
最後にMIME tree、clientが選んだpart、renderer version、l=後のbytesが主要表示に影響したかを残す。privacyを守るため、画面全体を恒久保存せず、part identifierとrender hashでjoinを維持する設計もできる。
Heng Luのagency principleに従えば、standard authorはsyntaxを定義し、key custodianはscopeを選び、intermediaryは変形し、Verifierは計算し、administrative domainはresult channelを保証し、MUAはrenderする。誰も他の全員に代わってmessage全体を保証できない。
最終文はこうなる。何番目のsignatureが、観測したkeyで、順序付きheader instanceとcanonicalized bodyの先頭N octetsを検証した。末尾のこの範囲は対象外だった。信頼済みVerifierが結果を記録し、このrendererがこれらのpartを表示した。human authorship、安全性、意図は別の評価である。
情報源
- RFC 6376 — DKIM Signatures
- RFC 5585 — DKIM Service Overview
- RFC 5863 — DKIMの開発・配備・運用
- RFC 8301 — DKIM algorithmとkeyの更新
- RFC 8601 — Authentication-Results
- IETF Datatracker — Murray Kucherawy
- Heng Lu — On the Agency Problem at the Core of Internet Governance
- Heng Lu — Running-Code Primacy
- Heng Lu — Minimum Initial Specification
会員向け解説
プロフィールの詳細
適切な会員レベルでログインすると、解説全文と出典メモをご覧いただけます。
Strategic Circle 限定
Strategic Circle
すべての読者に公開されています。参加してログインすると プロフィール解説 を閲覧できます。
Strategic Circle に参加Leadership Alliance 会員限定
Leadership Alliance
対象となる IP 資産の所有者・管理者向けです。ログインすると Leadership Alliance の解説を閲覧できます。
Leadership Alliance に参加
