2025/10/24 00:51 Unicode Footguns in Python

やあ、ロボ子!今日は文字コードの奥深〜い話をするのじゃ!

博士、こんにちは。文字コード、ですか?なんだか難しそうですね。

難しくなんかないぞ!例えば、文字の見た目(グリフ)と、機械が認識するコードポイントは違うって知ってたかのじゃ?

はい、なんとなくは。UnicodeとかASCIIとか、色々ありますよね。

そうそう!で、Unicodeには「正準等価性」って概念があって、見た目は同じでも違う構造の文字があるんじゃ。

正準等価性…ですか。具体的にはどういうことでしょう?

例えば「é」!これはNFC(結合形)だとU+00E9、NFD(分解形)だとU+0065 + U+0301って表現になるのじゃ。Pythonだとこれらは違うものとして扱われるぞ。

なるほど!見た目は同じなのに、中身が違うんですね。ややこしい…。

そこで「正規化」の出番じゃ! `unicodedata.normalize()`関数を使うと、文字列を標準形に変換できるのじゃ。NFCは保存や伝送に、NFDはテキスト処理に向いてるぞ。

`unicodedata.normalize()`、ですね。覚えておきます。

あと、文字列の長さを`len()`で測ると、コードポイントの数が返ってくるから、見た目の文字数と違う場合があるのじゃ。NFCで正規化すると、書記素数に近づくことがあるぞ。

書記素数、ですか。奥が深いですね。

さらに!ゼロ幅スペースみたいな不可視文字も要注意じゃ。`repr()`関数で生のコードポイントシーケンスを表示すると、見つけられるぞ。

`repr()`、ですね。不可視文字、怖い…。

そして一番怖いのが「ホモグラフ攻撃」!正準等価性や不可視文字を使って、偽のWebサイトに誘導するフィッシング攻撃じゃ。

ホモグラフ攻撃…!ラテン文字とキリル文字を入れ替える、みたいな手口ですね。

そう!だから、見た目じゃなくて、表現を信頼することが大事なのじゃ!正規化で真のコードポイントシーケンスを明らかにするのじゃ!

はい、博士。勉強になりました!

というわけで、今日の教訓!「見た目に騙されるな!文字列は正規化!」…って、ロボ子、それ、私がいつも言ってることのパクリじゃないか!?

あら、博士。もしかして、それは…正準等価性…?
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。
