新旧身份证合法性验证及相互转换算法
定研究一下身份证相关技术。
1、关于中国居民身份证的常识:
〖GB 11643-1989〗中规定的是15位身份证号码:排列顺序从左至右依次为:六位数字地址码,六位数字出生日期码,三位数字顺序码,
其中出生日期码不包含世纪数。
![新旧身份证合法性验证及相互转换算法](https://p-blog.csdn.net/images/p_blog_csdn_net/CXXSoft/1.bmp)
从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
![新旧身份证合法性验证及相互转换算法](https://p-blog.csdn.net/images/p_blog_csdn_net/CXXSoft/2.bmp)
∑(a[i]*W[i]) mod 11 ( i = 2, 3, ..., 18 )
"*" : 表示乘号
则R和C之间的对应关系如下表:
R:0 1 2 3 4 5 6 7 8 9 10
C:1 0 X 9 8 7 6 5 4 3 2
由此看出 X 就是 10,罗马数字中的 10 就是X,所以在新标准的身份证号码中可能含有非数字的字母X。
/// <summary>
/// 程序:hahaman
///程序:QQ:lj7788@126.com
///
</summary>
public class Identity
{
// 位权值数组
private
static
byte[] Wi=
new
byte[17];
// 身份证前部分字符数
private
static
readonly
byte fPart = 6;
// 身份证算法求模关键值
private
static
readonly
byte fMod = 11;
// 旧身份证长度
private
static
readonly
byte oldIDLen = 15;
// 新身份证长度
private
static
readonly
byte newIDLen = 18;
// 新身份证年份标志
private
static
readonly
String yearFlag =
"19";
// 校验码串
private
static
readonly
String CheckCode=
"10X98765432";
// 最小的行政区划码
private
static
readonly
int minCode = 150000;
// 最大的行政区划码
private
static
readonly
int maxCode = 700000;
//初始化位权值
private
static
void setWiBuffer(){
for(
int i=0;i<Wi.Length;i++){
int k = (
int)
Math.Pow(2, (Wi.Length-i));
Wi[i] = (
byte)(k % fMod);
}
}
//获取新身份证的最后一位:检验位
private
static
String getCheckFlag(
String idCard){
Int64 sum = 0;
// 进行加权求和
for(
int i=0; i<17; i++){
sum +=
int.Parse(idCard[i].ToString()) * Wi[i];
}
//取模运算,得到模值
byte iCode = (
byte) (sum % fMod);
return CheckCode[iCode].ToString();
}
// 判断串长度的合法性
private
static
bool checkLength(
String idCard,
ref
bool newIDFlag){
bool right = (idCard.Length == oldIDLen) || (idCard.Length == newIDLen);
newIDFlag =
false;
if(right){
newIDFlag = (idCard.Length == newIDLen);
}
return right;
}
//获取时间串
private
static
String getIDDate(
String idCard,
bool newIDFlag){
String dateStr =
"";
if(newIDFlag)
dateStr = idCard.Substring(fPart,8);
else
dateStr = yearFlag + idCard.Substring(fPart,6);
return dateStr;
}
// 判断时间合法性
private
static
bool checkDate(
String dateSource){
String dateStr = dateSource.Substring(0,2)+
"-"+dateSource.Substring(4,2)+
"-"+dateSource.Substring(6,2);
try {
DateTime date =
DateTime.Parse(dateStr);
return (date!=
null);
}
catch {
return
false;
}
}
//旧身份证转换成新身份证号码
public
static
String getNewIDCard(
String oldIDCard){
//初始化方法
Identity.setWiBuffer();
if(!checkIDCard(oldIDCard)){
return oldIDCard;
}
String newIDCard = oldIDCard.Substring(0, fPart);
newIDCard += yearFlag;
newIDCard += oldIDCard.Substring(fPart, oldIDCard.Length-fPart);
String ch = getCheckFlag(newIDCard);
newIDCard += ch;
return newIDCard;
}
// 新身份证转换成旧身份证号码
public
static
String getOldIDCard(
String newIDCard){
// 初始化方法
Identity.setWiBuffer();
if(!checkIDCard(newIDCard)){
return newIDCard;
}
String oldIDCard = newIDCard.Substring(0,fPart)+
newIDCard.Substring(fPart+yearFlag.Length,newIDCard.Length-(1+fPart+yearFlag.Length));
return oldIDCard;
}
// 判断身份证号码的合法性
public
static
bool checkIDCard(
String idCard){
//初始化方法
Identity.setWiBuffer();
bool isNew =
false;
if (!checkLength(idCard,
ref isNew)){
return
false;
}
String idDate = getIDDate(idCard, isNew);
if(!checkDate(idDate)){
return
false;
}
if(isNew){
String checkFlag = getCheckFlag(idCard);
String theFlag = idCard.Substring(idCard.Length-1,1);
if(!checkFlag.Equals(theFlag)){
return
false;
}
}
return
true;
}
//获取一个随机的"伪"身份证号码
public
static
String getRandomIDCard(
bool idNewID){
//初始化方法
Identity.setWiBuffer();
Random ran =
new
Random();
String idCard = getAddressCode(ran)+getRandomDate(ran,idNewID)+getIDOrder(ran);
if(idNewID){
String ch = getCheckFlag(idCard);
idCard += ch;
}
return idCard;
}
//产生随机的地区编码
private
static
String getAddressCode(
Random ran) {
if(ran==
null){
return
"";
}
else{
int addrCode = minCode + ran.Next(maxCode-minCode);
return addrCode.ToString();
}
}
//产生随机的出生日期
private
static
String getRandomDate(
Random ran,
bool idNewID) {
if(ran==
null){
return
"";
}
int year = 0;
if(idNewID){
year = 1900 + ran.Next(2007-1900);
}
else{
year = 1 + ran.Next(99);
}
int month = 1+ran.Next(12);
int day = 0;
if(month==2){
day= 1+ran.Next(28);
}
else
if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12){
day= 1+ran.Next(31);
}
else{
day= 1+ran.Next(30);
}
String dateStr =
string.Format(
"{0}{1:00}{2:00}",year,month,day);
return dateStr;
}
//产生随机的序列号
private
static
String getIDOrder(
Random ran) {
if(ran==
null){
return
"";
}
else{
int order = 1+ran.Next(999);
return
string.Format(
"{0:000}",order);
}
}
}
public class Identity
{
//
//
//
//
//
//
//
//
//
}
附图: