「正しい番号が入力されていること」という難しさ

（この記事は [地平線に行く](https://yujisoftware.hatenablog.com/entry/2021/05/21/010318) とのマルチポストです）

「正しい番号が入力されていること」の難しさについて、少し考えてみましょう。
（結論だけ読みたい人は、[こちら](#ちなみに)）

例えば、通販サイトの基本設計書で「入力フォームの電話番号の項目に、**正しい電話番号が入力されていない場合はエラーとすること**」と書かれていたとします。
では、正しい電話番号が入力されているかどうかの判定とは、どのように実装すればいいのでしょうか。

# 「正しい電話番号」とは？

電話番号とはどのようなものでしょうか。
総務省のホームページに分かりやすくまとめられていました。[^number]
[総務省｜電気通信番号制度｜電話番号に関するQ&A](https://www.soumu.go.jp/main_sosiki/joho_tsusin/top/tel_number/q_and_a.html)

[^number]: 仕様としては ITU-T の [E.164 勧告](https://ja.wikipedia.org/wiki/E.164)ですが、これは国別割り当て電話番号「国番号＋国内電話番号を合わせた最大15桁」とだけ定められており、国内電話番号の部分（090-XXXX-XXXX、03-XXXX-XXXX など）は**各国の方針**となっています。

この中から一般的[^emergency]に使われている**市外局番から始まる電話番号[^telecom]、または携帯電話[^satellite]の番号**で検討を進めます。
上記のページから関連する部分をピックアップすると、このようになっています。

> ◆電話番号とは、通話の相手を識別するために使われる、<font color="red">0から9までの数字を組み合わせた番号です。</font>

> **「0A0から始まる番号（Aは0以外）」**
> ◆携帯電話とPHSは<font color="red">「070」、「080」又は「090」から始まる11桁の番号です。</font>

> **「0ABCから始まる番号（A、B、Cは0以外）」**
> ◆普通の固定電話の電話番号は、次のようになっています。
> *固定電話の桁数*
> <font color="red">国内プレフィックス「0」市外局番「1～4桁」市内局番「1～4桁」加入者番号「4桁」
> ※市外局番と市内局番は合計5桁</font> [^old]

[^emergency]: 119 や 110 といった 1XY 特番、フリーダイヤルといった電話サービスの番号は除く
[^satellite]: 衛星携帯電話は、国際電話扱いのようなのでここでは検討しない。[衛星電話（インマルサット）あての電話のかけ方を教えてください。【インマルサット】](https://bizcs.kddi.com/s/article/3357)
[^telecom]: 中継する電話会社を明示する番号を指定しない番号
[^old]: 市外局番と市内局番の合計が4桁の地域もありましたが、現在はなくなりました。　[9桁の電話番号 ‐ 通信用語の基礎知識](https://www.wdic.org/w/WDIC/9%E6%A1%81%E3%81%AE%E9%9B%BB%E8%A9%B1%E7%95%AA%E5%8F%B7)

これを基にすると、（ハイフンを取り除いて）以下の正規表現にマッチすれば「正しい電話番号」と言えそうです。

```
((0[987]0)[0-9]{11}|0[0-9]{9})
```
しかし、この判定には問題があります。

# 有効な電話番号の判定

例えば、"0998-76-5432" は正しい番号番号と判定します。
しかし、今日時点で 998 という市外局番は存在しません。そのため、この電話番号は存在しない無効なものだと分かります。
つまり、厳密に正しい番号かどうかを判定するには、市外局番が存在するものかどうかも判定しなければいけません。

また、"060-4321-1234" は正しくない電話番号と判定します。
ですが、060 は携帯電話への割り当てが検討されており[^060]、これはいずれ有効になる番号です。これを、正しくないものとしてエラーにしてしまうと、今後改修が必要になってしまいます。

[^060]: FMC（Fixed-Mobile Convergence）にすでに使われていますが、利用が伸びないので携帯電話にも使用しようという見当が行われています。 [携帯電話の「060」がまもなく開放 そもそも「090」「080」「070」の違い、知ってる？｜TIME＆SPACE by KDDI](https://time-space.kddi.com/ict-keywords/kaisetsu/20170725/2052)

しかも、ここまで考えても、まだ**使われていない無効な電話番号**という可能性が残されています。
「正しい番号 ＝ 存在する有効な番号」なのかは微妙なところですが**世間一般としてはそういう認識のようです。**

# 存在する有効な番号の判定

では、「正しい番号 ＝ 存在する有効な番号」を判定するにはどうすればいいのでしょうか。
解決策は、実際にその電話番号にかけてみるということです。

これならば、存在する有効な番号であることが確認できます。
銀行などは、実際にこの方式をとっています。

ただし、単純に実装すると脆弱性となります。
[本の虫: ダイヤルQ2風の電話番号でInstagramやGoogleやMicrosoftから金をむしりとれる脆弱性](https://cpplover.blogspot.com/2016/07/q2instagramgooglemicrosoft.html)

国内ではダイヤルQ2が終了しているので、このままの方法は取れません[^hat]が、ひたすら電話をかけさせて相手に莫大な電話料金を支払わせる、他人の番号を入力して DDoS させるといったことが考えられます。
このような可能性を考慮して、慎重に実装を行う必要があります。

[^hat]: 情報料代理徴収サービスの一種である災害募金サービスは残っているので、意図しない募金を行うということは可能です。

# 簡単な判定

しかし、ここまで厳密な判定は必要なのでしょうか。
「存在しうる番号かどうかの判定」や「有効な電話番号の判定」を行うのはとても大変です。実装にも時間もかかります。

一番手っ取り早く、確実な方法は「正しい電話番号が入力されていること」という判定をしないことです。
シンプルに「数字のみが入力されていること」だけ判定すれば、考えなくてはいけないことがぐっと減ります。

その代わり、**架空の番号で登録できてしまうことを許容する必要があります。**

どこまでを求めるかは、要件次第です。

# ちなみに

「正しい電話番号の判定」は**これでも簡単な方です。**
なぜなら、電話局という（仮想的な）一つのデータベースに問い合わせすれば、存在する正しい番号かどうかわかるからです。

もし複数のデータベースに分散していて、それぞれに問い合わせる必要がある場合は、とても大変です。
分散しているすべてのデータベースに接続する必要があるためです。もしくは、番号を一つのデータベースに集約するという方法もありますが、これだと更新をどのように行うかを考えなくてはいけません。

例えば、ワクチンの接種番号は全国の市町村（今日時点で 1,718[^kouiki]）が管理しています。東京都区部に限っても23の区がそれぞれ管理しています。
これが正しいかどうかを確認するには、すべての市町村のデータベースと接続するか、番号を集約し常に更新し続ける必要があります。
参考：[新型コロナウイルスワクチンに係る接種券等の印刷及び発送について - 総務省](https://www.mhlw.go.jp/content/000714248.pdf)

それをやろうと思うと、時間も費用もかかると思います。

[^kouiki]: [総務省｜地方自治制度｜広域行政・市町村合併](https://www.soumu.go.jp/kouiki/kouiki.html)