[South African Specific]

SAIDValidator is an ASP.NET webservice to validate South African Person ID numbers. It provides validation of a person ID by calculating the check-digit (digit-13), and extracts the date-of-birth, gender, citizenship, sequence and other information. The following links are available:

- SAIDValidator Homepage
- SAIDValidator Test Page : Input an ID number and see if it is valid!
- SAIDValidator Webservice

If you would like to check your SA Passport or ID application status, or your current official marital status, please click on the link below:

An enigmatic quest indeed, with no definitive standards published by any SA government department known. The following blogs show the basics for validating SA Identity numbers:

- http://www.vanjaarsveld.com/default.aspx
- http://codingsanity.blogspot.com/2004/10/id-validation.html
- http://www.powertrip.co.za/blog/archives/000007.html
- http://www.powertrip.co.za/blog/archives/000135.html

Here's my interpretation and short code-excerpt for validating 'digit-13', the so-called 'check' digit:

Format:

{YYMMDD}{G}{SSS}{C}{A}{Z}

YYMMDD : Date of birth.

G : Gender. 0-4 Female; 5-9 Male.

SSS : Sequence No. for DOB/G combination.

C : Citizenship. 0 SA; 1 Other.

A : Usually 8, or 9 [can be other values]

Z : Control digit calculated in the following section:

Formula to calculate the check digit for a 13 digit identity number:

According to the provisions of the Identification Amendment Act, 2000 (Act No. 28 of 2000,

which was promulgated on 13 October 2000) all forms of identity documents other than the

green bar-coded identity document are invalid. [my observation: the following algorithm appears to work for the older 'blue'-book id numbers as well]. In accordance with the legislation,

the control figure which is the 13th digit of all identity numbers which have 08 and 09 is

calculated as follows using ID Number 800101 5009 087 as an example:

- Add all the digits in the odd positions (excluding last digit).

8 + 0 + 0 + 5 + 0 + 0 = 13...................[1] - Move the even positions into a field and multiply the number by 2.

011098 x 2 = 22196 - Add the digits of the result in b).

2 + 2 + 1 + 9 + 6 = 20.........................[2] - Add the answer in [2] to the answer in [1].

13 + 20 = 33 - Subtract the second digit (i.e. 3) from 10. The number must tally with the last number in the ID Number. If the result is 2 digits, the last digit is used to compare against the last number in the ID Number. If the answer differs, the ID number is invalid.

Here's the digit-13 check C# code

[Check below for a validator using a working version of this code]:

// This method assumes that the 13-digit id number has |

Your comment:
Title:
Name:
Comment: *Allowed tags: blockquote, a, strong, em, p, u, strike, super, sub, code*
Verification:
var RecaptchaOptions = {
theme : 'white',
tabindex : 0
};

Public Function parseIdNo(ByVal idNo As String) As Boolean

Try

Dim a As Integer = 0

For i As Integer = 0 To 5

a += CInt(idNo.Substring(i * 2, 1))

Next

Dim b As Integer = 0

For i As Integer = 0 To 5

b = b * 10 + CInt(idNo.Substring(2 * i + 1, 1))

Next

b *= 2

Dim c As Integer = 0

Do

c += b Mod 10

b = Int(b / 10)

Loop Until b <= 0

c += a

Dim d As Integer = 0

d = 10 - (c Mod 10)

If (d = 10) Then d = 0

If d = CInt(idNo.Substring(12, 1)) Then

Return True

Else

Return False

End If

Catch ex As Exception

Return False

End Try

End Function

What do ID numbers for birthdates in 2000 and later look like? How do you validate numbers like that?

Any ideas would be great!

A valid year 2000 ID is:

0005205113086 for a birthdate: 20 May 2000.

Anyone with clarity on this???

Hmmm, see DHA have a warning about using it for non-personal use.... would be interesting to see how they enforce that....

Thanks for the link!

Its not very ellegant and wont get us into the next century, but then again neither will VB.NET.

Public Function parseIdNo(ByVal idNo As String) As Boolean

Try

Dim a As Integer = 0

For i As Integer = 0 To 5

a += CInt(idNo.Substring(i * 2, 1))

Next

Dim b As Integer = 0

For i As Integer = 0 To 5

b = b * 10 + CInt(idNo.Substring(2 * i + 1, 1))

Next

b *= 2

Dim c As Integer = 0

Do

c += b Mod 10

b = Int(b / 10)

Loop Until b <= 0

c += a

Dim d As Integer = 0

d = 10 - (c Mod 10)

If (d = 10) Then d = 0

If (d = CInt(idNo.Substring(12, 1))) And (IsDate("19" & idNo.Substring(0, 2) & "/" & idNo.Substring(2, 2) & "/" & idNo.Substring(4, 2)) Or IsDate("20" & idNo.Substring(0, 2) & "/" & idNo.Substring(2, 2) & "/" & idNo.Substring(4, 2))) Then

Return True

Else

Return False

End If

Catch ex As Exception

Return False

End Try

End Function

public static function validateIdNumber($id) {

$match = preg_match ("!^(\d{2})(\d{2})(\d{2})\d{7}$!", $id, $matches);

if (!$match) {

return false;

}

list (, $year, $month, $day) = $matches;

/**

* Check that the date is valid

*/

if (!checkdate($month, $day, $year)) {

return false;

}

/**

* Now Check the control digit

*/

$d = -1;

$a = 0;

for($i = 0; $i < 6; $i++) {

$a += $id{2*$i};

}

$b = 0;

for($i = 0; $i < 6; $i++) {

$b = $b*10 + $id{2*$i+1};

}

$b *= 2;

$c = 0;

do {

$c += $b % 10;

$b = $b / 10;

} while($b > 0);

$c += $a;

$d = 10 - ($c % 10);

if($d == 10) $d = 0;

if ($id{strlen($id)-1} == $d) {

return true;

}

return false;

}

I need to find out how could a female and a male share the same identity number?

We all know that female ID numbers start with the number 0 after date of birth and the male ID numbers start with the number 5.

This is a worrying situation, especially with the recent corruption reports that we get regarding the Home Affairs Department.

Concerned

Norman Nosi

Can you please advise if this works for both old and new ID numbers??

Thanks

K

All the old and new ID numbers that I tested worked - but that included less than 100 old ID numbers...

Probably, only the Department of Home Affairs can answer your question.

If you are looking for a test to discern the old numbers from the new numbers, this isn't it!

Regards, Willem

eg: Black;White;Coloured;Idian etc.....

any one know??

i am busy writing a php script which will process the id number i am having problems though with birth dates after 1970 because php only supports up to 1970 any ideas

thank you

-- =============================================

-- Author: Craig Peacock

-- Create date: 08/10/2007

-- Description: This will validate a SA ID Number

-- =============================================

ALTER PROCEDURE [dbo].[VAL_S01_ValidateSAIDNumber]

@IDNumber VARCHAR (13)

AS

BEGIN

/*

This function was created from the function posted at:

http://geekswithblogs.net/willemf/archive/2005/10/30/58561.aspx

*/

DECLARE @A INT -- ~Holds Negative Index numbers

DECLARE @B INT -- ~Holds Positive Index numbers

DECLARE @C INT

DECLARE @D INT -- ~The check digit

DECLARE @I INT -- ~Counter Variable

SET @D = -1

SET @A = 0

SET @B = 0

BEGIN TRY

PRINT 'Getting Negative Numbers____________________'

SET @I = 0

WHILE (@I < 6)

BEGIN

PRINT SUBSTRING(@IDNumber, 2 * @I + 1, 1)

SET @A = @A + CAST(SUBSTRING(@IDNumber, 2 * @I + 1, 1) AS INT)

SET @I = @I + 1

END --WHILE

PRINT 'Getting Positive Numbers____________________'

SET @I = 1

WHILE (@I < 7)

BEGIN

PRINT SUBSTRING(@IDNumber, 2 * @I + 1, 1)

SET @B = @B * 10 + CAST(SUBSTRING(@IDNumber, 2 * @I, 1) AS INT)

SET @I = @I + 1

END --WHILE

SET @B = @B * 2

SET @C = 0

WHILE (@B > 0)

BEGIN

SET @C = @C + @B % 10

SET @B = @B / 10

END --WHILE

SET @C = @C + @A

SET @D = 10 - (@C % 10)

IF (@D = 10)

SET @D = 0

IF (CAST(SUBSTRING(@IDNumber, 13, 1) AS INT) = @D)

RETURN 1

ELSE

RETURN 0

END TRY

BEGIN CATCH

RETURN 0

END CATCH

RETURN 0

END

Will check it out soon and let you know..

function SAIDValidate()

{

//private method CalcSumOfString

this.CalcSumOfString = function(ValueToSum)

{

var lenghtOfString = ValueToSum.length;

var sumOfString=0;

for (var i = 0;i < lenghtOfString;i++)

{

sumOfString += parseInt(ValueToSum.substr(i,1));

}

return sumOfString;

}

//private method SAIDCheck

this.SAIDCheck = function (IdNumber)

{

var d1 = 0;

var d2 = 0;

var d3 = 0;

var d4 = 0;

var d5 = 0;

var d6 = 0;

var d7 = 0;

var d8 = 0;

var d9 = 0;

var d10 = 0;

var d11 = 0;

var d12 = 0;

var d13 = 0;

var evsum = 0;

var odsum = 0;

var evnum1 = 0;

var evnum2 = 0;

var evnum3 = 0;

var evnum4 = 0;

var evnum5 = 0;

var evnum6 = 0;

var checkDigit = 0;

if (IdNumber.length == 13 )

{

d1 = parseInt(IdNumber.substr(0,1),10);

d2 = parseInt(IdNumber.substr(1,1),10);

d3 = parseInt(IdNumber.substr(2,1),10);

d4 = parseInt(IdNumber.substr(3,1),10);

d5 = parseInt(IdNumber.substr(4,1),10);

d6 = parseInt(IdNumber.substr(5,1),10);

d7 = parseInt(IdNumber.substr(6,1),10);

d8 = parseInt(IdNumber.substr(7,1),10);

d9 = parseInt(IdNumber.substr(8,1),10);

d10 = parseInt(IdNumber.substr(9,1),10);

d11 = parseInt(IdNumber.substr(10,1),10);

d12 = parseInt(IdNumber.substr(11,1),10);

d13 = parseInt(IdNumber.substr(12,1),10);

evnum1 = (d2 * 2);

evnum2 = (d4 * 2);

evnum3 = (d6 * 2);

evnum4 = (d8 * 2);

evnum5 = (d10 * 2);

evnum6 = (d12 * 2);

evsum = (this.CalcSumOfString(evnum1.toString())) + (this.CalcSumOfString(evnum2.toString()))+ (this.CalcSumOfString(evnum3.toString()))+ (this.CalcSumOfString(evnum4.toString()))+ (this.CalcSumOfString(evnum5.toString()))+ (this.CalcSumOfString(evnum6.toString()));

odsum = d1 + d3 + d5 + d7 + d9 + d11;

if ( ((evsum + odsum) % 10) == 0 )

checkDigit = 0;

else

checkDigit = 10 - ((evsum + odsum) % 10);

if (checkDigit != d13)

return false;

else

return true;

}

else

{

return false;

}

}

}

function validateID(idVal){

var checkDigit = parseInt(idVal.charAt(idVal.length - 1));

var odd = 0;

var even = "";

var evenResult = 0;

var result;

for(var c = 1; c <= idVal.length; c++){

if(c % 2 == 0){

even += idVal.charAt(c - 1);

} else{

if(c == idVal.length){

continue;

} else{

odd = (parseInt(odd) + parseInt(idVal.charAt(c - 1)));

}

}

}

even = (Number(even) * 2);

even = even.toString();

for(var r = 1; r <= even.length; r++){

evenResult = (parseInt(evenResult) + parseInt(even.charAt(r - 1)));

}

result = (parseInt(odd) + parseInt(evenResult));

result = result.toString();

result = (10 - parseInt(result.charAt(result.length - 1)));

result = result.toString();

if(result.length > 1){

result = result.charAt(result.length - 1);

}

if(parseInt(result) != checkDigit){

return false;

} else{

return true;

}

}

I must say that this is a very helpful for us.

Can i Push the limits and ask if there is any way

that you can validate a Passport number also?

Thank you.

I had the following ID validation done by a student programmer for a specific form page, how can I add/change this ID validation to the validation.js file so that it works on ALL other forms needing the SA ID number?

Regards

Jan

['validate-id', 'You have entered an invalid identity number', function (v) {

if (document.Doves.gender[0].checked)

return !Validation.get('IsEmpty').test(v) && /^([0-9]{2})(((0[13578])|(1[02]))((0[1-9])|([12][0-9])|(3[01]))|((0[469])|(11))((0[1-9])|([12][0-9])|(30))|(02)((0[1-9])|([12][0-9])))([5-9])([0-9]{3})([01])([0-9]{2})$/.test(v) && ((document.Doves.date_of_birth.value.substring(2,4) == document.Doves.id_number.value.substring(0,2)) && (document.Doves.date_of_birth.value.substring(5,7) == document.Doves.id_number.value.substring(2,4)) && (document.Doves.date_of_birth.value.substring(8,10) == document.Doves.id_number.value.substring(4,6)))

else

return !Validation.get('IsEmpty').test(v) && /^([0-9]{2})((0[13578])((0[1-9])|([12][0-9])|(3[01]))|(0[469])((0[1-9])|([12][0-9])|(30))|(02)((0[1-9])|([12][0-9])))([0-4])([0-9]{3})([01])([0-9]{2})$/.test(v) && ((document.Doves.date_of_birth.value.substring(2,4) == document.Doves.id_number.value.substring(0,2)) && (document.Doves.date_of_birth.value.substring(5,7) == document.Doves.id_number.value.substring(2,4)) && (document.Doves.date_of_birth.value.substring(8,10) == document.Doves.id_number.value.substring(4,6)))

}]

The second last digit in my driver's licence is DIFFERENT to that in my green ID book. For example, the last three digits in my driver's licence is 050 --- but in my ID it is 084

This causes endless confusion.

One explanation might be that that the last THREE digits indicated race group in the old days and was done away with after the ANC came to power.

could anyone help me with a procedure to calculate the validity of ID numbers in an MS-ACCESS database, returning invalid IDs?

Thank you

http://www.dha.gov.za/enquiry/get_status.asp

Cheers.

PS: You can also verify your Status

Willem

Willem

Here's my code:

CREATE OR REPLACE FUNCTION CS_VALID_SA_ID_NUMBER

( p_id_number IN VARCHAR2

)

RETURN BOOLEAN

AS

lv_A NUMBER := 0; -- ~Holds Negative Index numbers

lv_B NUMBER := 0; -- ~Holds Positive Index numbers

lv_C NUMBER;

lv_D NUMBER := -1; -- ~The check digit

lv_I NUMBER; -- ~Counter Variable

lv_is_valid NUMBER;

lv_the_number NUMBER;

lv_rply BOOLEAN := FALSE;

BEGIN

--Getting Negative Numbers

lv_I := 0 ;

IF (lv_I < 6) THEN

lv_A := lv_A + CAST(SUBSTR(p_id_number, 2 * lv_I + 1, 1) AS NUMBER);

lv_I := lv_I + 1;

END IF;

--Getting Positive Numbers

lv_I := 1;

IF (lv_I < 7) THEN

lv_B := (lv_B * 10) + CAST(SUBSTR(p_id_number, 2 * lv_I, 1) AS NUMBER);

lv_I := lv_I + 1;

END IF;

lv_B := lv_B * 2;

lv_C := 0;

IF (lv_B > 0) THEN lv_C := lv_C + lv_B mod 10;

lv_B := lv_B / 10;

END IF;

lv_C := lv_C + lv_A;

lv_D := 10 - (lv_C mod 10);

IF (lv_D = 10) THEN lv_D := 0;

END IF;

lv_the_number := CAST(SUBSTR(p_id_number, 13, 1) AS NUMBER);

IF lv_the_number = lv_D THEN

lv_is_valid := 1;

lv_rply := TRUE;

END IF;

RETURN lv_rply;

-- ************************************

-- ** Handle an unexpected exception **

-- ************************************

EXCEPTION

/* When this function throws an exception

outside its exception block via the exception

procedure will it catch its own exception. To avaoid

this the following statement is required.

*/

WHEN no_data_found THEN

lv_rply := FALSE;

return lv_rply;

WHEN OTHERS THEN

cs_raise_exception(SQLCODE, SQLERRM, 'CS_VALID_SA_ID_NUMBER');

END;

CREATE OR REPLACE FUNCTION FN_VALID_SA_ID_NUMBER

( p_id_number IN VARCHAR2

)

RETURN BOOLEAN

AS

/* =====================================================================

This function was adapted from a TSQL function written by Craig Peacock on

http://geekswithblogs.net/willemf/archive/2005/10/30/58561.aspx

Adapted: Donal Slemon

Date: 2008/08/12

Description

-----------

Validates an SA ID number. (Returns 1=valid; 0=invalid)

=====================================================================

*/

lv_A NUMBER := 0; -- Holds Negative Index numbers (in odd number position)

lv_B VARCHAR2(7) := null; -- Holds Positive Index numbers (in even number position)

lv_B_num number(8,0) := 0; -- Holds Positive Index numbers

lv_C NUMBER;

lv_D NUMBER := -1; -- ~The check digit variable

lv_I NUMBER; -- Counter Variable

lv_dob NUMBER;

lv_valid_dob BOOLEAN := FALSE;

lv_is_valid NUMBER;

lv_last_number NUMBER;

lv_rply BOOLEAN := FALSE;

lv_length NUMBER;

lv_length_err EXCEPTION;

BEGIN

-- check length not <> 13

lv_length := LENGTH(p_id_number);

IF lv_length <> 13 THEN

lv_is_valid := 0;

RAISE lv_length_err ;

--RETURN lv_rply;

END IF;

-- check if first 6 digits are valid date (not strictly speaking necessary)

lv_dob := substr(p_id_number,0,6);

IF lv_dob IS NOT NULL AND to_date(lv_dob,'YYMMDD') IS NOT NULL THEN

lv_valid_dob := TRUE;

ELSE RETURN lv_rply;

END IF;

lv_I := 0 ;

-- adding every odd position digit (starting pos 1)(result goes into lv_A)

WHILE (lv_I < 6) LOOP

lv_A := lv_A + to_number(SUBSTR(p_id_number, 2 * lv_I + 1, 1));

lv_I := lv_I + 1;

END LOOP;

lv_I := 1;

-- Concatenating every even position digit (starting pos 2)

WHILE (lv_I < 7) LOOP

lv_B := lv_B || SUBSTR(p_id_number, 2 * lv_I, 1);

lv_I := lv_I + 1;

END LOOP;

-- multiply Concatenated number by two

lv_B_num := to_number(lv_B) * 2;

lv_C := 0;

-- Add up all the digits of the result in lv_B_num (result goes into lv_C)

WHILE (lv_B_num > 0) LOOP

lv_C := lv_C + lv_B_num mod 10;

lv_B_num := FLOOR(lv_B_num / 10);-- have to use FLOOR function here to prevent MOD function from rounding.

END LOOP;

/*WHILE (lv_B_num > 0) LOOP

lv_C := lv_C + lv_B_num mod 10;

lv_B_num := ROUND(lv_B_num / 10);

END LOOP; --WHILE

*/

-- Add answer of lv_A to answer of lv_C

-- Subtract the second digit (e.g. 3) from 10. The number must tally with the last number in the ID Number.

-- If the result is 2 digits, the last digit is used to compare against the last number in the ID Number.

-- If the answer differs, the ID number is invalid.

lv_C := lv_C + lv_A;

lv_D := 10 - (lv_C mod 10);

IF (lv_D = 10) THEN lv_D := 0;

END IF;

-- compare value in lv_D with lv_last_number

lv_last_number := CAST(SUBSTR(p_id_number, 13, 1) AS NUMBER);

IF (lv_last_number = lv_D) THEN

lv_is_valid := 1;

lv_rply := TRUE;

END IF;

RETURN lv_rply;

-- ************************************

-- ** Handle an unexpected exception **

-- ************************************

EXCEPTION

WHEN lv_length_err THEN

lv_rply := FALSE;

return lv_rply;

WHEN no_data_found THEN

lv_rply := FALSE;

return lv_rply;

--custom exception (place your own methods here)

--WHEN OTHERS THEN

-- raise_exception(SQLCODE, SQLERRM, 'FN_VALID_SA_ID_NUMBER');

END;

I need to find my fathers ID number as he has passed away but i have NO details about him, Is there anyway i could get that ?

Many thanks

Marc

I am a technical consultant and would like to know what the SSS as well as the A (8 & 9 in the id) and the z stands for.

Please also confirm whether the the intelligence built in the South African Id number remains the same!!!!

Regards;

candice

long oddNumberSum = 0;

long evenNums = 0;

//Getting the sum of odd numbers excluding the last digit

for(int i = 0; i < idnumber.length() - 1; i+=2){

oddNumberSum+= Long.parseLong(String.valueOf(idnumber.charAt(i)));

}

//Getting all the even numbers

StringBuilder evenNumsStr = new StringBuilder();

for(int i = 1; i < idnumber.length(); i+=2){

evenNumsStr.append(idnumber.charAt(i));

}

evenNums = Long.parseLong(evenNumsStr.toString().trim());

long dblEvenNums = evenNums * 2;

long dblEvensSum = 0;

for(int i = 0; i < String.valueOf(dblEvenNums).length(); i++){

dblEvensSum += Long.parseLong(String.valueOf(String.valueOf(dblEvenNums).charAt(i)));

}

long oddsPlusDblEvens = oddNumberSum + dblEvensSum;

long controlDigitCheck = 10 - Long.parseLong(String.valueOf(oddsPlusDblEvens).substring(String.valueOf(oddsPlusDblEvens).length() - 1));

if(controlDigitCheck == 10){

controlDigitCheck = 0;

}

if(controlDigitCheck != Long.parseLong(idnumber.substring(idnumber.length() - 1))){

return false;

}

else{

return true;

}

Use http://www.carlosag.net/Tools/CodeTranslator/ to convert your code from c# to Vb.Net

You can even convert a section not the whole Method

As explained in the post, the 'Z' is a check digit, generated from the other 12 digits using the coded algorithm.

function validateID(idnum) {

idnum = idnum.toString().replace(" ","");

r = /^\d{10}[0-1]\d{2}$/;

if (! r.test(idnum)) return false;

n = idnum;

p1 = parseInt(n[0]) + parseInt(n[2]) + parseInt(n[4]) + parseInt(n[6]) + parseInt(n[8]) + parseInt(n[10]);

p2 = (parseInt(n[1] + n[3] + n[5] + n[7] + n[9] + n[11]) * 2).toString();

p3 = 0;

for (i=0; i < p2.length; i++) {

p3+= parseInt(p2[i]);

}

check = 10 - (p1 + p3).toString()[(p1 + p3).toString().length -1];

check_char = check > 9 ? check.toString()[1] : check.toString();

if (check_char != idnum[12]) return false;

return true;

}

How 'bout a Java version from somebody who has made it word?

int a=0;

for (int i=0;i<12;i+=2){

a+=Integer.parseInt(ids.charAt(i)+"");

}

String bStr="";

int b=0;

for (int i=1;i<12;i+=2){

bStr+=ids.charAt(i);

}

b=Integer.parseInt(bStr);

b*=2;

int d;

int c = 0;

do

{

c += b % 10;

b = b / 10;

}

while(b > 0);

c += a;

d = 10 - (c % 10);

if(d == 10) d = 0;

return d;

}

Takes the ID number as a string parameter, returns the control digit as an integer. I've not added any error checking, so add that as needed. :)

This blog ran from 2006 and is still active...

When something's good, the thing's good...

Thanks guys, this is helping a lot of us...

Function CheckIDNumber(ByVal sIDNommer)

If sIDNommer = "1111111111111" Or sIDNommer = "6666666666666" Then

Return False

Exit Function

Else

If sIDNommer.ToString.Substring(2, 2) > 12 Or sIDNommer.ToString.Substring(4, 2) > 31 Then

Return False

Exit Function

Else

If sIDNommer.ToString.Substring(2, 2) = 2 And sIDNommer.ToString.Substring(4, 2) > 29 Then

Return False

Exit Function

Else

End If

End If

End If

Dim idNo

Dim a As Integer = 0

Dim b As Integer = 0

Dim c As Integer = 0

Dim d As Integer = -1

Dim sIDNom As String = ""

Dim iVal As Integer = 0

If Len(sIDNommer) <> 13 Then

CheckIDNumber = False

Else

For i = 1 To Len(sIDNommer)

sIDNom = sIDNom & Mid(sIDNommer, i, 1) & ":"

Next

idNo = Split(sIDNom, ":")

For i = 0 To 5

iVal = i * 2

On Error Resume Next

a = a + CInt(idNo(iVal))

Next

b = 0

For i = 0 To 5

iVal = 2 * i + 1

b = b * 10 + CInt(idNo(iVal))

Next

b = b * 2

c = 0

Do

c = c + (b Mod 10)

b = Fix(b / 10)

Loop While b > 0

c = c + a

d = 10 - (c Mod 10)

If (d = 10) Then d = 0

CheckIDNumber = d

If d = CInt(idNo(12)) Then

CheckIDNumber = True

Else

CheckIDNumber = False

End If

End If

End Function

Why does this sort of information have to be provided by Joe public? must be a big secret..

function validateID (idnum) {

idnum = idnum.toString().replace(" ","");

r = /^\d{10}[0-1]\d{2}$/;

if (idnum == '0000000000000') return false;

if (! r.test(idnum)) return false;

n = idnum;

p1 = parseInt(n[0],10) + parseInt(n[2],10) + parseInt(n[4],10) + parseInt(n[6],10) + parseInt(n[8],10) + parseInt(n[10],10);

p2 = (parseInt(n[1] + n[3] + n[5] + n[7] + n[9] + n[11],10) * 2).toString();

p3 = 0;

for (i=0; i < p2.length; i++) {

p3+= parseInt(p2[i]);

}

check = 10 - (p1 + p3).toString()[(p1 + p3).toString().length -1];

check_char = check > 9 ? check.toString()[1] : check.toString();

if (check_char != idnum[12]) return false;

return true;

}

private static bool IdNo_IsValid(String ids)

{

bool valid = false;

int a = 0;

int b = 0;

int d;

int c = 0;

int s = ids.Length;

String bStr = "";

if ((s == 13) & (ids != "0000000000000") & (ids != "6666666666666"))

{

for (int i = 0; i < 12; i += 2)

{

a += int.Parse(ids.Substring(i, 1) + "");

}

for (int i = 1; i < 12; i += 2)

{

bStr += ids.Substring(i, 1);

}

b = int.Parse(bStr);

b *= 2;

do

{

c += b % 10;

b = b / 10;

}

while (b > 0);

c += a;

d = 10 - (c % 10);

if (d == 10) d = 0;

if (Convert.ToInt16(ids.Substring(s - 1, 1)) == d)

{

valid = true;

}

}

return valid;

}

http://geekswithblogs.net/willemf/archive/2005/10/30/58561.aspx#118884

I was wondering if anyone could help me by telling me where to put the vb.net code for ID validation.

Thank you

am developing a CRM call center system how can i have a validate user ID by referencing @ their gender and date of birth

i lost my south african id

i need to know how can i get it back

7804126195187 this is my id no

$id="*****SA ID*****";

$odd=$id['0']+$id['2']+$id['4']+$id['6']+$id['8'];

$even_sum=$id['1'].$id['3'].$id['5'].$id['7'].$id['9'].$id['11'];

$even=$even_sum*2;

$even=$even."";

$temp=0;

$i=0;

echo $even."<br/>";

while($i < (strlen($even))){

$temp=$temp+$even[$i];

$i++;

}

$even=$temp;

$total=$odd+$even;

$total=$total."";

if($total[1]>0){

$test=10-$total[1];

}else{$test=0;}

if($test==$id[12]){

echo "Valid Id";

} else {

echo "Invalid Id";

}

I need to find out how could a female and a male share the same identity number?

We all know that female ID numbers start with the number 0 after date of birth and the male ID numbers start with the number 5.

This is a worrying situation, what can I do?????????

def validateID(IDNum):

"""Validates a South African ID Number"""

if len(IDNum) != 13:

return False

if IDNum[10] > 1:

return False

d = -1

a = 0

for i in range(0,6):

a += int(IDNum[2*i])

b = 0

for i in range(0,6):

b = b * 10 + int(IDNum[2*i+1])

b *= 2

c = 0

while b > 0:

c += b % 10

b = b / 10

c += a

d = 10 - (c % 10)

if d == 10:

d = 0

return(str(d) == IDNum[12])

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

static short checkDigit(const char *q)

{

short sRetCode = 0;

unsigned char c;

while (*q)

{

c = *q;

sRetCode = isdigit(c);

if (sRetCode == 0)

break;

q++;

}

return sRetCode;

}

static short CheckForValidID(const char *ID)

{

short sRetCode = 1, i = 0;

char TempArr1[8];

char TempArr2[8];

long lResult1 = 0;

long lResult2 = 0;

long lResult = 0;

short CheckDigit = 0;

const char *p = NULL;

memset(TempArr1,0x00,strlen(TempArr1));

memset(TempArr2,0x00,strlen(TempArr2));

p = ID;

if (strlen(ID) != (size_t) 13) /* Check if ID length is equal to 13 characters. */

return 0;

if (checkDigit(ID) == 0) /* Check if ID is all digits. No alphanumeric values allowed. */

return 0;

for (i = 0;i < 6;i++)

{

ID = p +(2*i);

TempArr1[i] = *ID;

lResult1 = lResult1 + (long)atoi(&TempArr1[i]);

}

for (i = 0;i < 6;i++)

{

ID = p + ((2*i) + 1);

TempArr2[i] = *ID;

}

lResult2 = 2 *(atoi(TempArr2));

lResult = lResult1;

while (lResult2 > 0)

{

lResult += (lResult2 % 10);

lResult2 = lResult2 / 10;

}

CheckDigit = 10 - (lResult % 10);

if (CheckDigit == 10)

CheckDigit = 0;

ID = (p + 12);

if (CheckDigit == atoi(ID))

sRetCode = 1;

else

sRetCode = 0;

return sRetCode;

}

ALTER FUNCTION [dbo].[CheckSumID]

(

@id nvarchar(13)

)

RETURNS integer

AS

BEGIN

DECLARE @Result integer = 0, @rem integer = 0, @odd integer = 0,

@i integer = 12, @even integer = 0

IF (@id IS NOT NULL) AND (LEN(@id) = 13) AND (ISNUMERIC(@id) = 1)

BEGIN

WHILE @i > 0

BEGIN

IF (@i % 2) = 0

BEGIN

SELECT @even = @even + @rem + ((CONVERT(integer, SUBSTRING(@id, @i, 1)) * 2) % 10)

SELECT @rem = (CONVERT(integer, SUBSTRING(@id, @i, 1)) * 2) / 10

END ELSE SELECT @odd = @odd + CONVERT(integer, SUBSTRING(@id, @i, 1))

SELECT @i = @i - 1

END

SELECT @Result = 10 - ((@even + @odd + @rem) % 10)

END ELSE SELECT @Result = NULL

RETURN @Result

END

----

SA_ID_REGEX = /^(\d{2})(\d{2})(\d{2})(\d{1})\d{3}(\d{1})\d{1}(\d{1})$/

def validate(id)

id = id.to_s.gsub(/\s/, "") # Convert to String, strip out all whitespace

return false unless id =~ SA_ID_REGEX

a = 0 # Add all the digits in the odd positions.

b = 0 # Stack the even positions and multiply by 2.

0.upto(5) do |i|

a += id[2*i].chr.to_i

b = b*10 + id[2*i + 1].chr.to_i

end

b = b*2

c = 0

while b > 0

c += b % 10

b = b / 10

end

c += a

d = (10 - (c % 10)) % 10 # Subtract second digit from 10. If result is 2 digits, use last digit.

id.scan(SA_ID_REGEX) do |yy, mm, dd, gender, citizen, control|

# Do other stuff here with date of birth, etc. if you like

return (d == control.to_i)

end

end

----

I also did a purely Integer-based calculation (with lots of modulus) but it came out slower on the benchmark strangely, even though this method includes regex matching. If you're interested, it was based around this function:

class Integer

def pos(n) # get the digit at position (n), starting from the back

(self % (10 ** n)) / (10 ** (n-1))

end

end

Oh, and lastly, @Sarel (7/21/2010 11:05 AM): Get a sex change. ;)

<Script LANGUAGE="JavaScript">

function GetControlDigit(ParsedIdString)

{

var d = -1;

var a = 0;

for(var i = 0; i < 6; i++)

{

a += parseInt(ParsedIdString.substring(2*i,2*i+1));

}

var b = 0;

for(var i = 0; i < 6; i++)

{

b = b*10 + parseInt(ParsedIdString.substring(2*i+1,2*i+1+1));

}

b *= 2;

var c = 0;

do{

c += parseInt(b) % 10;

b = parseInt(b) / 10;

}while(b > 0);

c += parseInt(a);

d = 10 - (parseInt(c) % parseInt(10));

if(d == 10) d = 0;

return d;

}

</script>

FYI .. a bit of useless information:

All functions should check if the Date of birth is correct!!!

I repeat: Check if the date of birth exists otherwise you will get a few that validate even if they aren't valid ...

Have created a SQL function similar to these on this site ... Working on a database of over 10 million ID numbers so please check the date of birth is valid:

i.e. 200231******* will validate but the date of birth is incorrect .. there is not 31 days in February.

(Yep when I tried to derive the age of a few I got a few more that was now invalid on a legacy system, so please validate with a date of birth check first ... )

My two cents

please advise how I can find this number.

I am also looking for passport details etc for myself born 1953, my mother born 1929 and my father a south african citizen but born in Lithuania.

Can you help me or lead me in the right direction.

Thank You

?

How will I validate Namibian Id numbers

Thanks

Function ID_Valid(ID As String) As String

'This algoritm test the validity of a South African ID number

Dim D(13, 2) As Integer, N As Integer, Check As String

'delete spaces

ID_Valid = Replace(ID, " ", "")

For N = 1 To 12

D(N, 1) = Val(Mid(ID_Valid, N, 1))

If N Mod 2 = 0 Then

D(N, 2) = D(N, 1) * 2

If D(N, 2) >= 10 Then

D(N, 2) = Int(D(N, 2) / 10) + (D(N, 2) - Int(D(N, 2) / 10) * 10)

End If

Else

D(N, 2) = D(N, 1)

End If

D(0, 0) = D(0, 0) + D(N, 2)

Next N

Check = CStr(D(0, 0) * 9)

Check = Right(Check, 1)

If Check = Right(ID_Valid, 1) Then

ID_Valid = "ID number OK"

Else

ID_Valid = "ID number Error"

End If

End Function

i want to check if it is holding my name

The requested URL could not be retrieved

While trying to retrieve the URL:

http://www.dha.gov.za/enquiry/marital/status/marital_status.asp

The following error was encountered:

Unable to forward this request at this time.

This request could not be forwarded to the origin server or to any

parent caches. The most likely cause for this error is that:

The cache administrator does not allow this cache to make

direct connections to origin servers.

All configured parent caches are currently unreachable.

Your cache administrator is webmaster.

Ek kan nie meer oopmaak om te sien of persoon volgens ID nommer getroud, geskei of enkellopend is nie, al wat ek kry is bostaande --------------------------------------------------------------------------------

Generated Thu, 08 Mar 2012 06:54:24 GMT by inv-proxy.dha.gov.za (squid)

function Modules10SARSValidID(const ANumber: String): Boolean;

var

TotalStr: String;

TotalLength: Integer;

CheckDigit: Integer;

ANumberLength: Integer;

ErrMsg: String;

EvenString: String;

OddTotal, EvenTotal: Integer;

Total: Integer;

i, j: Integer;

begin

ErrMsg := '';

ValidateString(ANumber, vo_Numbers, '', ErrMsg);

Result := (ErrMsg = '');

if (Result) then begin

EvenString := '';

OddTotal := 0;

EvenTotal := 0;

for i := 1 to Length(ANumber) do begin

if (not (Odd(i))) then

EvenString := EvenString + ANumber[i]

else

if (i <> 13) then

OddTotal := OddTotal + StrToInt(ANumber[i]);

end;

if (EvenString > '') then

EvenTotal := (StrToInt(EvenString) * 2);

EvenString := FloatToStr(EvenTotal);

EvenTotal := 0;

for j := 1 to Length(EvenString) do begin

EvenTotal := EvenTotal + StrToInt(EvenString[j]);

end;

Total := OddTotal + EvenTotal;

TotalStr := IntToStr(Total);

TotalLength := Length(TotalStr);

CheckDigit := 10 - StrToInt(TotalStr[TotalLength]);

ANumberLength := Length(ANumber);

if (CheckDigit <> StrToInt(ANumber[ANumberLength])) then

Result := False;

end;

end;

calculated as follows using ID Number 800101 5009 087 as an example:

Add all the digits in the odd positions (excluding last digit).

8 + 0 + 0 + 5 + 0 + 0 = 13...................[1]

but you not adding all, which ones to add here?

====================================

Move the even positions into a field and multiply the number by 2.

011098 x 2 = 22196

here are suppose to add even numbers or odd? before we x by 2.

Kind regards

Anne

I believe they'll just get a new ID number.

(which would be based on his birthdate, etc). Original citizenship doesn't matter in RSA id numbers as far as I know.

=IF(RIGHT(A1,1)=(RIGHT(10-RIGHT((MID(A1,1,1)+MID(A1,3,1)+MID(A1,5,1)+MID(A1,7,1)+MID(A1,9,1)+MID(A1,11,1))+(IF(LEN(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2)=7,MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,1,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,2,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,3,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,4,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,5,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,6,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,7,1),IF(LEN(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2)=6,MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,1,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,2,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,3,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,4,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,5,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,6,1),MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,1,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,2,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,3,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,4,1)+MID(CONCATENATE(MID(A1,2,1),MID(A1,4,1),MID(A1,6,1),MID(A1,8,1),MID(A1,10,1),MID(A1,12,1))*2,5,1)))),1),1)),"Valid","Invalid")

I had to construct an ID validator using VB in 2006 for an app being used at certain Department Of Health sites. During the process I managed to trace the son of the developer of the original algorithm for the Department Of Home Affairs (DOHA) who in turn explained the entire algorithm to me in detail. Subsequently my code worked perfectly and was tested extensively using both old and new ID numbers.

Not long after deployment a user submitted a copy of a “valid” ID which was reported by the system as an invalid ID number. Subsequently I took my code apart, but failed to find any problem with it. Eventually I approached DOHA and after hours of failed attempts (officials blatantly refused to discuss the problem) managed to get through to an official at management level who verbally confirmed that DOHA is aware of the fact that certain ID numbers were issued incorrectly due to 1) duplicated ID numbers being used and 2) an incorrect algorithm being used to generate ID numbers. So much for validating an ID number…

Still, it appears the most secure current solution. Always add additional code to validate the date of birth, which will eliminate problem strings such as “0000000000000” and “6666666666666”.

I hope you can help.

many thanks

elsa

R.O.van Zyl

Birthdate; 29.04.1937

Died; 04.03.1980

Can you help me with code to validate Indian Passport number?

Thanks