15位或18位身份證驗證

c#實現的18位身份證格式驗證算法

18位身份證標準在國家質量技術監督局於1999年7月1日實施的GB11643-1999《公民身份號碼》中做了明確的規定。 GB11643-1999《公民身份號碼》爲GB11643-1989《社會保障號碼》的修訂版,其中指出將原標準名稱"社會保障號碼"更名爲"公民身份號碼",另外GB11643-1999《公民身份號碼》從實施之日起代替GB11643-1989。GB11643-1999《公民身份號碼》主要內容如下:
一、範圍
該標準規定了公民身份號碼的編碼對象、號碼的結構和表現形式,使每個編碼對象獲得一個唯一的、不變的法定號碼。
二、編碼對象
公民身份號碼的編碼對象是具有中華人民共和國國籍的公民。
三、號碼的結構和表示形式
1、號碼的結構
公民身份號碼是特徵組合碼,由十七位數字本體碼和一位校驗碼組成。排列順序從左至右依次爲:六位數字地址碼,八位數字出生日期碼,三位數字順序碼和一位數字校驗碼。
2、地址碼
表示編碼對象常住戶口所在縣(市、旗、區)的行政區劃代碼,按GB/T2260的規定執行。
3、出生日期碼
表示編碼對象出生的年、月、日,按GB/T7408的規定執行,年、月、日代碼之間不用分隔符。
4、順序碼
表示在同一地址碼所標識的區域範圍內,對同年、同月、同日出生的人編定的順序號,順序碼的奇數分配給男性,偶數分配給女性。
5、校驗碼
(1)十七位數字本體碼加權求和公式
S = Sum(Ai * Wi), i = 0, ... , 16 ,先對前17位數字的權求和
Ai:表示第i位置上的身份證號碼數字值
Wi:表示第i位置上的加權因子
Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
(2)計算模
Y = mod(S, 11)

(3)通過模得到對應的校驗碼
Y: 0 1 2 3 4 5 6 7 8 9 10
校驗碼: 1 0 X 9 8 7 6 5 4 3 2
四、舉例如下:
北京市朝陽區: 11010519491231002X
廣東省汕頭市: 440524188001010014

 


根據〖中華人民共和國國家標準 GB 11643-1999〗中有關公民身份號碼的規定,公民身份號碼是特徵組合碼,由十七位數字本體碼和一位數字校驗碼組成。排列順序從左至右依次爲:六位數字地址碼,八位數字出生日期碼,三位數字順序碼和一位數字校驗碼。

地址碼錶示編碼對象常住戶口所在縣(市、旗、區)的行政區劃代碼。生日期碼錶示編碼對象出生的年、月、日,其中年份用四位數字表示,年、月、日之間不用分隔符。順序碼錶示同一地址碼所標識的區域範圍內,對同年、月、日出生的人員編定的順序號。順序碼的奇數分給男性,偶數分給女性。校驗碼是根據前面十七位數字碼,按照ISO 7064:1983.MOD 11-2校驗碼計算出來的檢驗碼。下面舉例說明該計算方法。

15位的身份證編碼首先把出生年擴展爲4位,簡單的就是增加一個19,但是這對於1900年出生的人不使用(這樣的壽星不多了)

某男性公民身份號碼本體碼爲34052419800101001,首先按照公式⑴計算:

∑(ai×Wi)(mod 11)……………………………………(1)

公式(1)中:
i----表示號碼字符從由至左包括校驗碼在內的位置序號;
ai----表示第i位置上的號碼字符值;
Wi----示第i位置上的加權因子,其數值依據公式Wi=2(n-1)(mod 11)計算得出。

i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1

ai 3 4 0 5 2 4 1 9 8 0 0 1 0 1 0 0 1 a1

Wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1

ai×Wi 21 36 0 25 16 16 2 9 48 0 0 9 0 5 0 0 2 a1

根據公式(1)進行計算:

∑(ai×Wi) =(21+36+0+25+16+16+2+9+48++0+0+9+0+5+0+0+2) = 189

189 ÷ 11 = 17 + 2/11

∑(ai×Wi)(mod 11) = 2

然後根據計算的結果,從下面的表中查出相應的校驗碼,其中X表示計算結果爲10:

∑(ai×WI)(mod 11) 0 1 2 3 4 5 6 7 8 9 10
校驗碼字符值ai 1 0 X 9 8 7 6 5 4 3 2
根據上表,查出計算結果爲2的校驗碼爲所以該人員的公民身份號碼應該爲 34052419800101001X。

以上是轉載的(sorry忘了哪裏找過來的),以下是根據原文寫的一個校驗類,並自動將15位轉換成18位.
CODE(C#)

using System;
using System.Text;
using System.Text.RegularExpressions;
namespace Leisang
{
/// <summary>
/// CID 的摘要說明。
/// </summary>
public class IdentityCard
{
  private string cid_;
  private string errmsg;
  private string[] aCity;
  public IdentityCard()
  {
   aCity = new string[]{null,null,null,null,null,null,null,null,null,null,null,
         "北京","天津 ","河北","山西","內蒙古",
         null,null,null,null,null,
         "遼寧","吉林","黑龍江",
         null,null, null,null,null,null,null,
         "上海","江蘇","浙江","安微","福建","江西","山東",
         null,null, null,
         "河南","湖北","湖南","廣東","廣西","海南",
         null,null,null,
         "重慶","四川","貴州","雲南","西藏",
         null,null,null,null,null,null,
         "陝西","甘肅","青海","寧夏","新疆",
         null,null, null,null,null,
         "臺灣",
         null,null,null,null,null,null,null,null,null,
         "香港","澳門",
         null,null,null,null,null,null,null,null,
         "國外"};
  }
 
  public bool Check(string CardID)
  {
   CID=CardID;
   return Check();
  }

  public bool Check()
  {
   //判斷位數
   if(CID.Length==15)
   {
    return Check15();
   }
   else if(CID.Length==18)
   {
    return Check18(CID);
   }
   else
   {
    ErrMsg="身份證位數不正確";
    return false;
   }
  }

  public bool Check18(string cid)
  {
   double iSum=0;
   //string info="";
   System.Text.RegularExpressions.Regex rg = new System.Text.RegularExpressions.Regex(@"^/d{17}(/d|x)$");
   System.Text.RegularExpressions.Match mc = rg.Match(cid);
   if(!mc.Success)
   {
    ErrMsg="身份證輸入錯誤";
    return false;
   }  
   cid = cid.ToLower();
   cid = cid.Replace("x","a");
   if(aCity[int.Parse(cid.Substring(0,2))]==null)
   {
    ErrMsg= "非法地區";
    return false;
   }
   try
   {
    DateTime.Parse(cid.Substring(6,4)+"-"+cid.Substring(10,2)+"-"+cid.Substring(12,2));
   }
   catch
   {
    ErrMsg= "非法生日";
    return false;
   }
   for(int i=17;i>=0;i--)
   {  
    iSum +=(System.Math.Pow(2,i)%11)*int.Parse(cid[17-i].ToString(),System.Globalization.NumberStyles.HexNumber);

   }
   if(iSum%11!=1)
   {
    ErrMsg="非法證號";
    return false;
   }
   //return "";
   string xx;
   int sex=int.Parse(cid.Substring(16,1))%2;
   if(sex==1)
   {
    xx="男";
   }
   else
   {
    xx="女";
   }
   ErrMsg=(aCity [int.Parse(cid.Substring(0,2))]+","+cid.Substring(6,4)+"-"+cid.Substring(10,2) +"-"+cid.Substring(12,2)+","+xx);
   return true;
  }

  public bool Check15()
  {
   string[] verifyID=new string[]{"0","1","2","3","4","5","6","7","8","9","x"};
   CID=CID.Substring(0,6)+"19"+CID.Substring(6,9);
   foreach(string vid in verifyID)
   {
    bool result=Check18(CID+vid);
    if(result)
    {
     ErrMsg+=" your Card ID:"+CID+vid;
     return true;
    }
   }
   return false;
  }
 
  public string CID
  {
   get{return cid_;}
   set{cid_=value;}
  }

  public string ErrMsg
  {
   get{return errmsg;}
   set{errmsg=value;}
  }
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章