コジマです。
私はCDについているシリアルコードでライブのチケットに応募することがしばしばある。いくつかコードを打ち込むうち、魔が差してこんなことを考えてしまう。「適当に打ち込んだら通ったりしないかな……」と。
本当に通ったら一大事なので、このような仕組みを設計する段階でどうにかして防いでいる訳だが、どのようにやっているのだろう。防止策のひとつ「チェックディジット」について紹介する。
まず、完全にランダムな文字列にすると困る
あなたがライブを主催することになり、0〜9の数字からなる16桁のシリアルコードで抽選を行うとしよう。あなたならどのようにコードを作るだろうか?
単純に考えれば16個の枠それぞれに0〜9の数字を1つずつランダムに選べばいい(0〜9の乱数を16個並べればいい)のだが、完全にランダムだと不都合が多い。例えば、ランダムだと限りなく似ているコードが生成される可能性がある。つまり、
- 1234 5678 9012 3456
- 1234 5678 0012 3456
のような、1箇所しか変わらない2つのシリアルコードが生まれ得る。1つ目のシリアルコードを持っている人が、うっかり数字をひとつ打ち間違えたり、あるいは狙って数字を変えたりして、2つ目が受理されてしまう、という事態が考えられる。
異なる箇所が少ないほどこういう事故は起こりやすい、というのは直感的に分かるだろう。これを防ぐためには、シリアルコード同士が、どんなに運の悪い乱数を引いても最低n箇所以上は異なる、という状態が望ましい。
では、それを作る方法なんてあるの?という話になるが、そこでチェックディジットが登場する。
誤りを見つける仕組み「チェックディジット」
チェックディジットとは、符号の誤りを検査(チェック)するための桁(ディジット)のこと。
今回の例でいえば、最初から16桁をランダムに生成する代わりに、15桁だけランダムに生成することにして、残りの1桁をチェックディジットに割り当てることにする。チェックディジットの計算方法はいろいろあるが、ここでは「15桁の数字を足し合わせて10で割った余り」をチェックディジットとしよう。
まず、15桁のコードとしてランダムに
- 1234 5678 9012 345
が生成されたとする。1+2+3+...+3+4+5=60なので、10で割ると余りは0。これをチェックディジットとすれば
- 1234 5678 9012 3450
というシリアルコードができる。
このようにすると何がいいかというと、シリアルコード同士が必ず2桁以上異なることが担保されるのだ。
例えば、この中から1桁だけ変えた
- 1234 5678 0012 3450
は絶対に当たりのコードではない。なぜなら、末尾以外の15桁を足し合わせると51なので、チェックディジットは1であるはず。
- 1234 5678 0012 3451
はあり得ても、上の末尾が0のコードは生まれないのだ。
このように、チェックディジットを1桁設けることで、シリアルコードが互いに2箇所以上異なるようにできる。また、適当に打ち込まれたコードならば、チェックディジットを確認することで用意したシリアルコードを検索するまでもなく間違いだと判定できる。
チェックディジットが1桁だと「何かが間違っている」ことしか分からないが、桁を増やし、計算方法を工夫することで、具体的に「◯桁目が間違っている」まで判別することもできる。そのようなチェックディジットは、通信やQRコードのように、必ず正確に読み取れるとは限らないが確実に中身を伝えたい暗号化でよく用いられている。
チェックディジットは、コードが正しく作られたものであることを証明し、間違ったコードを正しいとみなしてしまう事故を防ぐ役割をもつ。
原理を知れば、勘で打ち込むのはやめておこう、と思うはず。あるいは勘当てのヒントにしようと企む人もいるかもしれないが、おすすめはしないぞ。