중국신분증 번호의 구조와 진위여부 확인하기

대한민국에 주민등록번호가 있듯, 중국에는 신분증(정식 명칭으론 중화인민공화국 거민신분증) 번호가 있다.
주민등록번호의 알고리즘은 워낙 많이 퍼진 관계로, 이 포스팅에서는 외국의 신분증 번호 알고리즘을 한번 파해쳐 보고자 한다.

먼저, 중국신분증 번호는 15자리식과 18자리 식이 있는데, 15자리는 체크섬(Checksum) 값이 없는 형태이고
18자리 식이 이번에 다루고자 하는 주요 내용이다.

18자리 식의 형태는 다음과 같다

123456789ABCDEFGHI

1,2 : 중국의 성(城)급 행정구역을 나타낸다. (예 : 길림성, 하남성 등등) 이 코드는 아래를 참조한다.

11:”北京”,12:”天津”,13:”河北”,14:”山西”,15:”内蒙古”,21:”辽宁”,22:”吉林”,23:”黑龙江”,31:”上海”,32:”江苏”,33:”浙江”,34:”安徽”,35:”福建”,36:”江西”,37:”山东”,41:”河南”,42:”湖北”,43:”湖南”,44:”广东”,45:”广西”,46:”海南”,50:”重庆”,51:”四川”,52:”贵州”,53:”云南”,54:”西藏”,61:”陕西”,62:”甘肃”,63:”青海”,64:”宁夏”,65:”新疆”,71:”台湾”,81:”香港”,82:”澳门”,91:”国外”

재밌는 점은 72번(台湾) 인데 이것을 한국식으로 발음하면 “대만”이다.
중국에서는 대만을 하나의 나라로 인정하지 않으며 “성급”으로 취급하는데, 여기에서도 그런 모습이 드러난다.

3,4 : 성급 행정구역보다 한단계 아래인 지구별행정구역(區, qi라고 발음)을 나타낸다.
5,6 : 지구별행정구역의 하위 개념인 현(縣)급 행정구역을 나타낸다.
3,4,5,6은 워낙 많기때문에 여기서 다루지 않고 넘어간다. -_-;
7,8,9,A : 출생년도를 표기한다. (예 : 1985, 2009) 신분증 번호 중 15자리 식은 예문을 85 또는 09로만 표현한다.
B,C : 출생월을 표기한다. (예 : 09, 12)
D,E : 출생일을 표기한다. (예 : 22, 31)
F,G,H : 이것은 위에서 나타낸 정보 (XX성 XX구 XX현 yyyy년 mm월 dd일)에서 몇번째로 태어난 사람인지 기록하는 카운터(counter)의 개념이다. 여기서 유의점은 남자는 홀수, 여자는 짝수로 표기된다. (예 : 남자의 경우 001, 003, 005 순서로 기록)

I : 이 값이 골치를 썩게 하는 체크섬 값이다. 이 부분은 아래에서 구하는법을 다루겠다.

대략 위와 같은 형태로 신분증 번호가 구성이 되는데, 주민등록번호처럼 맨 마지막 값이 체크섬 값이다. 이 값에 따라
형식이 올바른 번호인지 아닌지가 구별이 되므로 이제 이 체크섬 값을 구하는 것을 기술해보겠다.

먼저, 예문이 될 중국신분증 번호를 하나 만들어보자.
112524198509226478 로 만들었다.
북경시에서 태어났고 (xx구,xx현은 대충 만듬) 1985년 09월 22일생이며 324번째로 태어난 남자다.

우리가 구해야 하는 값은 i,Ai,Wi,S 라는 값이다.
이것은 간단하게 표로 정리해 보겠다.

18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 i
1 1 2 5 2 4 1 9 8 5 0 9 2 2 6 4 7 Ai
7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 Wi
7 9 20 25 16 16 2 9 48 15 0 81 20 10 48 16 14 S

오른쪽에 각각 i, Ai, Wi, S 라는 글짜가 보인다.

i는 2~18까지의 숫자를 오른쪽에서 왼쪽으로 1씩 더해가며 쓴 숫자이다.
Ai는 우리가 만든 신분증 번호를 순서대로 왼쪽에서 오른쪽으로 쓴것이다.
Wi는 모든 사람이 같은 값을 가지게 되는데 이것은 아래의 식을 따른다.



저 식을 적용하고 나면 7,9,10,5,8,4,2,1,6,3 이라는 숫자가 계속 반복해서 나옴을 알 수 있다.

S는 Ai와 Wi를 곱한 값으로써 i_2부터 i_18까지 행해준다. (식은 아래를 참조)



마지막으로 각 S의 값을 모두 더한 값이 최종적인 S의 값이 된다.
이렇게 구한 S를 11로 나눈 뒤 나머지만 취한다. (result = S % 11)

예문에서 모두 합산된 S의 값은 356이다. 이 값을 11로 나눠 나머지만 취하면 4라는 값을 구할 수 있다.
이 값을 가지고 아래 표에 대입하여 마지막 체크섬 값을 찾아낸다.

0 1 2 3 4 5 6 7 8 9 10 대입할 값
1 0 X 9 8 7 6 5 4 3 2 치환될 값

우리가 가지고 있는 값은 4 이므로 “대입할 값”에서 4를 찾으면 “치환될 값”란에는 8이라고 써있으므로

마지막 18번째 체크섬 값은 8이 된다.

우리가 맨처음 생성한 112524198509226478 라는 값에서 맨 마지막값이 8이므로 체크섬값이 일치함을 알 수 있고

따라서 이 신분증번호는 형식에 올바른 신분증 번호라는것이 판명된다. (진위여부 확인 OK)

보통 이것을 홈페이지 같은곳에서 진위여부 확인을 위해 체킹하는 함수를 만드는데,
아래에 “발로 대충 만든” 알고리즘이 있으니 참고하여 쓰면 된다.

* 비베가 익숙칠 않아서 IF문이 본의 아니게 많이 사용됬다.
* text1.text에 112524198509226478 와 같이 입력한다.

————————————————————————————————-

Dim ai(17) As String
Dim wi(17) As String

ai(0) = Mid(Text1.Text, 1, 1)
ai(1) = Mid(Text1.Text, 2, 1)
ai(2) = Mid(Text1.Text, 3, 1)
ai(3) = Mid(Text1.Text, 4, 1)
ai(4) = Mid(Text1.Text, 5, 1)
ai(5) = Mid(Text1.Text, 6, 1)
ai(6) = Mid(Text1.Text, 7, 1)
ai(7) = Mid(Text1.Text, 8, 1)
ai(8) = Mid(Text1.Text, 9, 1)
ai(9) = Mid(Text1.Text, 10, 1)
ai(10) = Mid(Text1.Text, 11, 1)
ai(11) = Mid(Text1.Text, 12, 1)
ai(12) = Mid(Text1.Text, 13, 1)
ai(13) = Mid(Text1.Text, 14, 1)
ai(14) = Mid(Text1.Text, 15, 1)
ai(15) = Mid(Text1.Text, 16, 1)
ai(16) = Mid(Text1.Text, 17, 1)
checkkey = Mid(Text1.Text, 18, 1)

‘연산을 위한 지정값
wi(0) = 7
wi(1) = 9
wi(2) = 10
wi(3) = 5
wi(4) = 8
wi(5) = 4
wi(6) = 2
wi(7) = 1
wi(8) = 6
wi(9) = 3
wi(10) = 7
wi(11) = 9
wi(12) = 10
wi(13) = 5
wi(14) = 8
wi(15) = 4
wi(16) = 2

‘ai(i)와 wi(i)를 곱한 값을 모두 합친다.
For i = 0 To 16
tmp = ai(i) * wi(i)
result = tmp + result
Next i

‘마지막 연산을 위해 11로 나눈 나머지 값을 취한다.
result = result Mod 11

‘매직키 테이블로 마지막 18번째 자리값을 대조해서 찾는다.
Dim checksum As String

If result = 0 Then
checksum = 1
End If
If result = 1 Then
checksum = 0
End If
If result = 2 Then
checksum = “X”
End If
If result = 3 Then
checksum = 9
End If
If result = 4 Then
checksum = 8
End If
If result = 5 Then
checksum = 7
End If
If result = 6 Then
checksum = 6
End If
If result = 7 Then
checksum = 5
End If
If result = 8 Then
checksum = 4
End If
If result = 9 Then
checksum = 3
End If
If result = 10 Then
checksum = 2
End If

If checksum = checkkey Then
Text5.Text = ” [O] ” & Text1.Text & vbCrLf & ” (올바른 신분증번호)”
End If
If checksum <> checkkey Then
Text5.Text = ” [X] ” & Text1.Text & vbCrLf & ” (틀린 신분증번호)” & vbCrLf & vbCrLf & ” 올바른 신분증번호는” & vbCrLf & ” ” & Mid(Text1.Text, 1, 17) & checksum & ” 입니다.”
End If

————————————————————————————————-

올바른 목적으로 사용하자. (악용하면 생성기가 만들어진다.)

댓글 남기기