カテゴリー
Computer Development PHP Security Programming Security

マイナンバーのチェックデジット確認

マイナンバーのチェックディジットを確認する必要があったのでPHP関数を作りました。

(Last Updated On: 2018/08/13)

マイナンバーのチェックデジットを確認する必要があったのでPHP関数を作りました。

個人番号

マイナンバー(個人番号)のチェックデジットの計算式は法律に記載されています。

(検査用数字を算出する算式)
第五条  令第八条の総務省令で定める算式は、次に掲げる算式とする。
算式
11―(n=1(シグマ)11(P×Q))を11で除した余り)
ただし、(n=1(シグマ)11(P×Q))を11で除した余り≦1の場合は、0とする。
算式の符号
 個人番号を構成する検査用数字以外の十一桁の番号の最下位の桁を1桁目としたときのn桁目の数字
 1≦n≦6のとき n+1 7≦n≦11のとき n―5
 これを使って入力されたマイナンバーが妥当であるか確認できます。形式として正しいことだけチェックするのでマイナンバーが本人の物であるか、実際に利用されている物なのか、などは当然確認できません。
<?php
// 個人用マイナンバーのチェックデジットを計算し確認。(注:法人用は異る)
// アルゴリズムは
// http://law.e-gov.go.jp/announce/H26F11001000085.html
// を参照。
function verifyPersonalMyNumber($mynum) {
	// 必ず数字12文字
	if (strlen($mynum) !== 12 || strspn($mynum, '1234567890') !== 12 ) {
		return FALSE;
	}
	$sum = 0;
	// 最後の一文字がチェックディジット。小さい桁から計算。
	for ($i=1; $i <= 11; $i++) {
		$m = substr($mynum, 11-$i, 1);
		$n = ($i <= 6) ? $i+1 : $i-5;
		$sum += $m * $n;
	}
	$mod = $sum % 11;
	// 必ず数字一桁
	if ($mod <= 1) {
		return (substr($mynum, 11, 1) == '0');
	} else {
		return ((int)substr($mynum, 11, 1) === 11 - $mod);
	}
}

// テスト (注:0で始まる場合も考慮すると文字列でなければならない)
$mynum = '123456789010';
for ($i = 0; $i < 10; $i++) {
	var_dump($mynum+$i, verifyPersonalMyNumber($mynum+$i));
}

出力

[yohgaki@dev ~]$ php mynumber.php 
int(123456789010)
bool(false)
int(123456789011)
bool(false)
int(123456789012)
bool(false)
int(123456789013)
bool(false)
int(123456789014)
bool(false)
int(123456789015)
bool(false)
int(123456789016)
bool(false)
int(123456789017)
bool(false)
int(123456789018)
bool(true)
int(123456789019)
bool(false)

問題ないと思いますが、さっと作ったので問題があれば教えてください。

 

法人番号

コード中に法人用の法人番号のチェックデジットのアルゴリズムは異る、と記載しています。法人番号のチェックデジットはこの法律で定められています。

(検査用数字を算出する算式)
第二条  令第三十五条第一項に規定する財務省令で定める算式は、次に掲げる算式とする。
算式
9―((n=1(シグマ)12(Pn×Qn))を9で除した余り)
算式の符号
Pn 令第三十五条第一項に規定する基礎番号の最下位の桁を1桁目としたときのn桁目の数字
Qn nが奇数のとき 1、nが偶数のとき 2

法人番号は既に12桁の数字が割り振られています。これの最後に1桁のチェックデジットを足した13桁の数字が新しい法人番号になります。

<?php
function verifyCooporateNumber($cnum) {
    //文字列として処理するので文字列型に変換して最適化
    $cnum = (string)$cnum;
    // 必ず13桁
    if (strlen($cnum) !== 13 || strspn($cnum, '1234567890') !== 13 ) {
        return FALSE;
    }
    $sum = 0;
    // 最初の一文字がチェックディジット。小さい桁から計算。
    for ($i=1; $i <= 12; $i++) {
        $m = substr($cnum, 13-$i, 1);
        $n = ($i % 2) ? 1 : 2;
        $sum += $m * $n;
    }
    $mod = 9 - $sum % 9;
    return (substr($cnum, 0, 1) == $mod);
}

// Test
$cnum = '1234567890120';
for ($i = 0; $i < 10; $i++) {
    var_dump(($cnum+$i) . ' = '. verifyCooporateNumber($cnum+$i));
}

今すぐ必要ではなかったので確認していません。問題がある場合は教えてください。

追記:チェックデジットは最後という思い込みがあったので、最後がチェックデジットとして処理していましたが最初として処理するよう修正しました。