Willem's...

{rue if I mellow}

  Home  |   Contact  |   Syndication    |   Login
  25 Posts | 0 Stories | 120 Comments | 53 Trackbacks

News

Archives

Post Categories

Businessware Architects

XML-FX.COM

[South African Specific]

SAIDValidator Webservice

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:

South African Department of Home Affairs

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:

How to validate SA Identity Numbers

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:

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 
// valid digits in position 0 through 12.

// Stored in a property 'ParseIdString'.

// Returns: the valid digit between 0 and 9, or

// -1 if the method fails.
private int GetControlDigit()
{
int d = -1;
try { int a = 0;
for(int i = 0; i < 6; i++)
{
a += int.Parse(this.ParsedIdString[2*i].ToString());
}
int b = 0;
for(int i = 0; i < 6; i++)
{
b = b*10 + int.Parse(this.ParsedIdString[2*i+1].ToString());
}
b *= 2;
int c = 0;
do
{
c += b % 10;
b = b / 10;
}
while(b > 0);
c += a;
d = 10 - (c % 10);
if(d == 10) d = 0;
}
catch {/*ignore*/} return d;
}
posted on Sunday, October 30, 2005 6:58 PM

Feedback

# re: How to validate SA Identity Numbers 12/8/2005 4:58 AM Clive
I needed to convert to vb.net so here is my code if anybody needs a conversion in a hurry:

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

# re: How to validate SA Identity Numbers 12/8/2005 7:55 AM Willem
Clive, thanks for the contribution!

# re: How to validate SA Identity Numbers 12/9/2005 11:06 AM Willem
James, v.cool - thanks!

# How to validate Namibian Identity Numbers 1/4/2006 2:08 PM Hannes
Is their a similar procedure available to validate Namibian ID numbers?

# Namibian ID numbers 1/31/2006 11:50 AM Willem
Not sure - definitely *NO* info out there... won't it be similar to SA ID numbers? ..remember SA governed Namibia not so long ago when it was South West Africa.

# re: How to validate SA Identity Numbers 3/16/2006 4:48 PM Patrick Maloney
Does anybody know of a readily accessible portal at which a ID number can be checked against a known identity (without having to subscribe to ITC). The www.elections.org.za worked fine for me in order to confirm identity, as you could enter a valid ID and it would return First names and Surname along with voting district. I ran a small hot script that would post ID number to the URL and checked relevant returned html text for match. Recently (probably because elections are passed) the site stopped supplying names, but only confimed whether registered or not...Any ideas...

# re: How to validate SA Identity Numbers 8/4/2006 8:44 AM Louise
You guys are stars thank you!!!!. the vb conversion made a huge difference to my friday :D

# re: How to validate SA Identity Numbers 1/17/2007 2:58 PM Amnon
Any ideas on whether there is something similar to an ID number for Kenya.

# re: How to validate SA Identity Numbers 1/17/2007 2:59 PM Amnon
Any ideas on whether there is something similar to an ID number for Kenya. j1@eighty20.co.za

# re: How to validate SA Identity Numbers 1/18/2007 3:13 PM Henk Sweers
Did you know: The current SA ID Number algorithm was created by my uncle Pieter den Boer (ex Q-Data, Brainware...) while working at IBM in the 1980's. He passed away last week - I attended his funeral this morning. A great mathematical mind an Business man will sorely be missed.

# re: How to validate SA Identity Numbers 1/24/2007 10:22 AM Peter Davies
Hi all,

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

Any ideas would be great!

# re: How to validate SA Identity Numbers 1/29/2007 10:25 AM Johan Andersson
Thank you for this!

# re: How to validate SA Identity Numbers 1/29/2007 10:48 AM Willem
From 2000 on the year starts at '00', again. I assume that if there are SA citizens with an ID from the year 1900, that this would use the same year number: '00'. The 'SSS' sequence would make the number unique. However, I am not sure if you can distinguish a '1900' ID from a '2000' ID etc.
A valid year 2000 ID is:
0005205113086 for a birthdate: 20 May 2000.

Anyone with clarity on this???

# re: How to validate SA Identity Numbers 2/2/2007 12:49 PM Johan
When passed an input string which is the IDNumber, how can I return a valid vb.net date?

# re: How to validate SA Identity Numbers 2/7/2007 4:19 AM HeinRich
If you are looking for a specific person's ID number, I can help.

# re: How to validate SA Identity Numbers 5/2/2007 6:28 AM James
Dept of Home Affairs has a tool you can at least use to verify marital status (hence existence) at http://www.dha.gov.za/enquiry/marital/status/marital_status.asp

# re: How to validate SA Identity Numbers 5/2/2007 11:30 AM Willem Fourie
James, Nice link - not only confirms whether the person attached to the ID number is married/single, but also whether the entered ID number is (a) valid, and (b) if valid whether it is a real live ID number.

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!

# re: How to validate SA Identity Numbers 5/5/2007 12:45 PM Peter
An old ex Zimbo friend of mine is a permanant resident but long time ago lost his ID book. When he wanted to replace it 10 years later DHA are demanding his ID number. He has long forgotton it! Can anyone help using his DOB or permanant residence number. He does not want to go back to DHA.

# re: How to validate SA Identity Numbers 5/10/2007 7:09 AM Clive
I have had to modify my original VB.NET post to cater for erroneous idNo's like 0000000024588

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

# re: How to validate SA Identity Numbers 7/16/2007 6:29 AM dawit
Here is the same routine in PHP,

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;
}

# IDENTITY NUMBERS SHARED 7/30/2007 1:45 AM Monnapule Norman Nosi
On Saturday, 28 July 2007, my wife (PG Nosi) and bought a television. We found out that she shares her identity number (7602210298085) with a certain Mr Paul Nkosi.

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

# re: How to validate SA Identity Numbers 8/10/2007 2:52 AM Kats
Hi there,

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

Thanks
K

# re: How to validate SA Identity Numbers 8/10/2007 3:19 AM Willem Fourie
Hi Kats,

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

# re: How to validate SA Identity Numbers 9/3/2007 6:15 AM Sarika Maharaj
How do I determine the race group from the id?

# re: How to validate SA Identity Numbers 9/4/2007 7:09 AM Willem Fourie
As far as I know the race-group info is NOT encoded into the id number.

# re: How to validate SA Identity Numbers 10/3/2007 8:17 AM Philip
hello all i was wondering if you can tell a persons race from the South African ID number

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


any one know??




# re: How to validate SA Identity Numbers 10/4/2007 1:08 AM Willem
Philip, I don't think the new numbers carry any race info, if it does it certainly is not documented anywhere that I could find...

# PHP Script and dates 10/4/2007 7:37 AM Philip
hello again

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

# re: How to validate SA Identity Numbers 10/9/2007 2:16 AM Craig Peacock
Hi Guys, I tried to find a SQL Implementation of this function but Google failed me but I still know one exists. Anyway, I wrote the SP myself. Let me know what you think:



-- =============================================
-- 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

# re: How to validate SA Identity Numbers 10/9/2007 2:51 AM Willem
Thanks Craig - my original blog had a SQL implementation contributed by another reader...lost it when I moved the blog. Glad to have another one!

Will check it out soon and let you know..

# re: How to validate SA Identity Numbers 11/2/2007 9:18 AM Martin
Here is a Javascript version I wrote about 5 years ago, still seems to work...

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;
}
}
}

# re: How to validate SA Identity Numbers 11/7/2007 3:01 AM Phillip
Here's another Javascript version:

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;
}
}

# re: How to validate SA Identity Numbers 12/17/2007 4:54 AM David
Willem and Craig, I tried the SQL previously on the blog and it worked (old and new numbers). Craig's one doesn't seem to work though (unless it is a SQL version problem). But that's not the real problem. It would appear that the tried and trusted rules don't work for ID numbers of people born after 1/1/2000. I tried a few permutations but it doesn't seem straightforward. Any ideas? Also let me know if you want a copy of the old SQL - still have that.

# re: How to validate SA Identity Numbers 12/18/2007 9:00 AM David
OK so I found the problem with my logic. Let me know if you want the old SQL code - it's here if you need it.

# re: How to validate SA Identity Numbers 1/28/2008 2:04 AM Gremlin1708
Hi There everyone...
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.




# re: How to validate SA Identity Numbers 4/26/2008 2:09 AM Jan Kruger
Hi All,
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)))
}]

# Last two digits are different. Please help 5/7/2008 11:15 AM Joe Jameson
Hi, please can someone help with out with this problem:

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.

# re: How to validate SA Identity Numbers 5/23/2008 3:26 PM Terrie
Can anyone tell me how I can verify an S.A. Id # to the picture and name of the person on it so I know if the person I am dealing with is legitimate or just using an valid ID # with his picture on it . Thanks for any help


# re: How to validate SA Identity Numbers wheather is married or not 6/11/2008 8:29 AM Boh
I like this site it's usefull ,thank

# re: How to validate SA Identity Numbers 6/27/2008 3:03 AM Errol
Hi,
could anyone help me with a procedure to calculate the validity of ID numbers in an MS-ACCESS database, returning invalid IDs?
Thank you

# re: How to validate SA Identity Numbers 7/20/2008 12:56 PM Home Affairs Agent (MTM)
To check on the status of your application for ID and/or Passport, please click on:

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

Cheers.

PS: You can also verify your Status

# re: How to validate SA Identity Numbers 7/21/2008 5:23 AM Willem Fourie
Thanks for this link - it has given me the inspiration to clean up this blog entry - I have also added the link at the top of the text - hopefully there will be less enquiries for ID status etc. assistance flooding this blog.

Willem



# re: How to validate SA Identity Numbers 7/23/2008 8:05 AM Ian Steadman
This is a great tool, thanks. Why is it that the last three digits of my ID number were changed - I think it was in the 1994 elections - from 007 to 080?

# re: How to validate SA Identity Numbers 7/24/2008 1:08 AM Willem Fourie
I think the pre-94 ids did have person racial info encoded in it, which was removed in the post-94 ids. Exactly how this worked then and now, I'm not sure.

Willem

# re: How to validate SA Identity Numbers 7/31/2008 6:32 AM Joe
pre 94 the 2nd&3rd last digits indicated race, with 00 being white, etc. My original ID book is long gone, so I do not have the full list anymore :)


# re: renewal off passport 8/8/2008 1:24 AM Tanya Muller
I requested a renewal for a passport in March. My husband received his two months ago and I am still waiting. Please could you let me know the status of mine. ID 6904100087087.

# re: How to validate SA Identity Numbers 8/13/2008 4:31 AM Donal
This is really useful. I'm trying to convert Craig Peacocks SQL version to PL/SQL function and not getting anywhere. Seems to return false all the time. Anybody out there able to help pls?

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;



# re: How to validate SA Identity Numbers 8/18/2008 3:24 AM Donal
OK, I've seen the errors of my ways and got it to work! (Thanks Craig Peacock for your T-SQL). Here's the Oracle PL/SQL code:

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;

# re: How to validate SA Identity Numbers 8/20/2008 1:05 PM Marc Nothnagel
Hi,

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

# re: How to validate SA Identity Numbers 9/8/2008 9:43 AM Candice
Hi there

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

# re: How to validate SA Identity Numbers 9/11/2008 9:13 AM Colile
thank you the information was very useful

# re: How to validate SA Identity Numbers 9/12/2008 8:18 AM mike
id validity enquire

# re: How to validate SA Identity Numbers 9/18/2008 4:37 AM Sibusiso
why? is it possible for people to make fake id numbers?

# re: How to validate SA Identity Numbers 10/27/2008 5:27 AM Fana Sithole
Java Implementation:

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;
}

# re: How to validate SA Identity Numbers 12/3/2008 3:12 AM zikona
Can you please email me a code that checks the 7th digit in RSA`s id numbers and determines the gender in VB.net

# re: How to validate SA Identity Numbers 12/3/2008 4:29 AM Musa
Zikona...
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

# re: How to validate SA Identity Numbers 1/6/2009 2:22 AM Willem
There is no way you can do this by looking at the number itself - there is no 'allocated flag' or any data built into the number. The only way is to use the Home Affairs link at the top of this post.

# re: How to validate SA Identity Numbers 1/16/2009 2:35 AM Martine Jackson
WHAT DOES THE 'A' and 'Z' (last 2 digits) stand for?

# re: How to validate SA Identity Numbers 1/16/2009 4:48 AM Willem
I do not know what the 'A' digit represents - for the old blue book id numbers, this digit is often other values (specially '0'). For the new id's, this is almost always '8' or '9'. The 'A' digit may have represented a racial classification code, although I cannot confirm this - read some of the comments in this post for more information.

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

# re: How to validate SA Identity Numbers 1/30/2009 8:09 AM Benny
Hi

It seems not working 100% in Java!!!

# re: How to validate SA Identity Numbers 2/5/2009 1:51 AM Jasper
More javascript if anyone cares. Only tested in firefox.


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;
}



# re: How to validate SA Identity Numbers 2/13/2009 2:20 AM prince tj
am a south african citizen but i lost my parents,pls smone could help me to get an id

# re: How to validate SA Identity Numbers 2/23/2009 1:55 AM Fana Sithole
Hi Benny, where does the Java code break?

# re: How to validate SA Identity Numbers 3/5/2009 3:05 AM Maxi
Nice site!

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

# re: How to validate SA Identity Numbers 3/22/2009 12:18 PM James
private static int testIdStr(String ids){
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. :)

# re: How to validate SA Identity Numbers 3/25/2009 5:09 AM Shepard Sithole
WOW!
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...

# re: How to validate SA Identity Numbers 4/7/2009 5:12 AM Giel
Hi

Here is the code for ASP or VB6


Function CheckIDNumber(ByVal sIDNommer)
Dim idNo
d = -1
a = 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

# re: How to validate SA Identity Numbers 4/7/2009 8:08 AM Jaco
Hi guys, well here is an updated piece of code in VB be it VB.NET, VB6, MS ACCESS OR ASP. I added a couple of my own checks for certain errors like the idnumber 0000000000000 or 6666666666666 which is also verified as valid. Erm. And then what if dates are incorrect aswell. Please note that no Y2K Leapyear cheacks are performed.


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


# re: How can i watch my id photo 4/23/2009 12:28 PM steven phaswane
my photo

# this rocks 4/25/2009 10:11 AM simon
thanks, I am so glad this blog is here - just made my life a lot easier..
Why does this sort of information have to be provided by Joe public? must be a big secret..

# fix for Jasper's function 4/28/2009 5:09 AM simon
the javascript function Jasper posted is great (short and sweet) and I have adopted it, but found it fails on an idnumber which has 0 for a second digit, have modified it to use the radix arg to force it to use hexadecimal and now it works fine.

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;
}

# cumulative C# Id Check code 5/20/2009 3:36 AM Rob
This is a cumulative C# code (DotNet 2) update of the above postings. Has anyone seen an id number of a person born in 2000 or 2001? How is the year displayed?

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;

}



# re: Cumulative C# Id Check code 6/25/2009 11:06 AM Willem
Hi Rob, did some checking - I observed that there seems to be *NO* digit modification to indicate birthdays of year 2000+ vs. 1900+. I'm guessing the DOB/G sequence is just increased, and the DHA uses the ID as a key to get the persons identification record with the actual birthday? Anyway, my webservice assumes that all dates from '000101' to '090625' (today) are year 2000 onwards. Any future dates (from today) are considered 1900's dates. Although this is not full-proof, it essentially assumes that people in SA who required IDs to be validated should not be older than 100 years...(probably not a bad assumption in this day, age and country).

Post Feedback

Title:
Name:
Email: (never displayed)
Url:
Comments: