要約
- BarryのREADMEはトラストアンカーの既定IPv6資源として
::/0を掲げるが、issue 7は証明書とROAの資源フィールドで同じ表記が拒否されると報告する。 - 固定したコミットのlexerは、開始済みの非引用文字列にはコロンとスラッシュを許す。しかし先頭に使えるのは英数字、
$、だけである。0::/0はtokenになり、::/0はIPプレフィックス解析より前で失敗する。 - RFC 4291上、
::/0は正当なIPv6プレフィックスであり、RFC 5952では正規表記でもある。0::/0は同じ意味を持つが、最大限に圧縮された出力ではない。 - 不正なRPKIオブジェクトの生成、relying partyによる受領、LACNICの本番環境や経路への影響を示す資料はない。必要なのは、失敗段階を明示するlexerからDERまでの適合表だ。
ゼロは空間ではなく入口を変えた
違いは一文字でしかない。
::/0
0::/0
どちらも128ビットすべてがゼロのIPv6アドレスに長さゼロのプレフィックスを付けたもので、対象範囲は全IPv6空間である。LACNIC/barryのissue 7が報告する差はネットワーク上の意味ではない。正規表記はunexpected characterで止まり、先頭を数字にした表記が回避策になるという、プログラム内の経路差である。
BarryはRPKI素材を生成し、検証ソフトを試すために意図的に不正な素材も作れるツールだ。だからこそ、負の試験より先に正の入力契約が必要になる。正当な文字列が明確なIP値へ変わり、さらに特定可能なバイト列へ変わったと証明できて初めて、後段のrelying partyが何を拒否したかを論じられる。文字列がtokenにさえならなければ、証明書やROAの試験は始まっていない。
組織にとって最も好意的な読み方も欠かせない。リポジトリのメタデータはBarryを小さな生成ツールとして説明する。調査対象コミットに固定したREADMEは、プロジェクトとRepository Descriptor仕様をwork in progressと明記し、1.0以前には互換性のない変更があり得ると告げる。取得時点のrelease一覧とtag一覧は空だった。小さな再現例を伴う公開issueは、実験段階の透明性を示すもので、本番障害の証拠ではない。
表示された入力と貼られたtraceは同一ではない
issueは2026年8月28日に開かれた。9月6日の証拠締切時点でもopenで、ラベル、コメント、更新はない。GitHub上の報告者のauthor associationはNONEであり、maintainerによる再現、診断、修正方針の表明もまだない。
報告は::/0を二つの場所に置く。CA証明書のIP resource extensionと、ROAのipAddrBlocksである。回避策として0::/0を示す。ただし、画面に載った再現記述子と貼り付けられたtraceはバイト単位で同じではない。再現例は両方に::/0を書く一方、traceが最初に表示する値はすでに0::/0へ変更されている。その後、別フィールド先頭のコロンでUnexpected character: : (0x3a)となる。
この食い違いはissueを無効にはしないが、主張を限定する。traceが直接示すのは、ある経路で先頭コロンが失敗することだ。報告本文は二つのフィールドで正規形が失敗すると述べる。しかし公開資料だけでは、同一実行における二つの完全同一入力の失敗を独立に証明できない。適合試験が入力の正確なバイト列とhashを保存すべき理由はここにある。回避策を一か所へコピーしただけで、試験対象が静かに変わり得るからだ。
また、このtraceには不正な証明書やROA、公開済みリポジトリ、検証結果がない。経路変化もLACNICの本番RPKI利用も示していない。観測された段階より後ろの出来事を補ってはならない。
開始文字の規則だけで非対称性を説明できる
コードは2026年9月1日のコミット994a598321336baf1767f0fbfb460ed96c29fe4fに固定した。件名はAKIのauthorityCertIssuer実装であり、issue 7の修正を主張していない。直近40件の履歴も観測点を定めるだけで、この挙動の導入時期を証明しない。
同コミットのsrc/rpki_tree.cでは、next_tokenが非引用文字列を開始できるのは、最初の文字が英数字、$、のどれかである場合に限られる。コロンは該当しないため、処理はtry_emojiへ落ち、通常の:はunexpected characterとして拒否される。
一方、tokenが始まった後の規則は広い。空白や記述子の構造区切りを除き、コロンやスラッシュを文字列内に残せる。0::/0の先頭ゼロは、別のIPv6ライブラリに異なる値を受け入れさせるのではない。開始条件を満たし、その後の::/0を同じtokenに収めるだけだ。
README自身が境界を可視化する。2001:db8::/64のような圧縮表記も登場するが、これは16進数字から始まるので入口を通る。そしてトラストアンカーの既定IPv6資源には::/0を使う。したがって「圧縮IPv6を扱える」というラベルでは足りない。数字の後で始まる圧縮と、一文字目から始まる圧縮ではlexerの経路が違う。
IPとして意味を読む処理はさらに下流にある。src/field.cのparse_ip_nodeは/で分割し、コロンの有無でIPv6を識別し、inet_ptonを呼び、プレフィックス長を読む。拒否された正規表記はここへ届かない。inet_ptonや長さ解析、field bindingの失敗と呼ぶのは、決定していない部品へ責任を移すことになる。
正規表記こそ通常経路であるべきだ
RFC 4291は、連続するゼロgroupを::で圧縮できるとし、全ゼロアドレスそのものを::で示す。IPv6プレフィックスは正当なアドレス表記と/後の長さからなるため、::/0は正当な入力である。
RFC 5952は受理と出力を分ける。実装はRFC 4291の正当な表記を受け入れ、文字列を生成するときは正規化と最大圧縮を行うべきだ。0::/0はアドレス族、数値、長さが同じだが、正規出力なら消えるゼロgroupを一つ残している。
RubyのIPAddrを使った限定的な補助確認では、::/0、0::/0、0000::/0、全展開したゼロアドレスが同じ値と範囲へ正規化された。これはBarryの実行ではなく、RFCより強い証拠でもない。意味の差ではなく、字句入口を調べるべきだという確認にすぎない。
オブジェクト層では表現がさらに変わる。RFC 3779はIP資源をDERのBIT STRINGとして格納する。全アドレスを示す長さゼロのブロックは03 01 00となり、記述子での綴りは証明書やROAの性質として残らない。lexerで止まった場合、後段が受理・拒否できるDER値は存在しない。
小さな適合表で十分である
必要なのは「IPv6対応」という大きな約束ではない。version管理された表の各行に、記述子の正確なバイト列とhash、対象フィールド、token化結果、正規化したaddress family・数値・prefix length、正規出力、parser/generatorのcommit、構築に達した場合のobject hashを持たせればよい。
終了段階はdescriptor-tokenize、prefix-parse、field-bind、object-build、DER-encode、RP-validateから選ぶ。これで、生成器の入口拒否をvalidator失敗として数えることを防げる。中心となる不変条件はparse(format(parse(input)))が同じ三つ組を保つことだ。意味が等しい正当な入力は、生成に成功すれば同じDERプレフィックス値へ収束すべきである。
この表はBarryを認証せず、IPv6全体を説明もしない。どのバイトを受理し、何と理解し、どのオブジェクトを作り、どの段階が最後に決めたかを局所的に検証可能にする。負の試験を行う道具には、その狭さこそが必要だ。
情報源
会員向け解説
プロフィールの詳細
適切な会員レベルでログインすると、解説全文と出典メモをご覧いただけます。
Strategic Circle 限定
Strategic Circle
すべての読者に公開されています。参加してログインすると プロフィール解説 を閲覧できます。
Strategic Circle に参加Leadership Alliance 会員限定
Leadership Alliance
対象となる IP 資産の所有者・管理者向けです。ログインすると Leadership Alliance の解説を閲覧できます。
Leadership Alliance に参加
