shakes1
Expert Member
Thank you, will happily buy you a coffee once doneIf I have time I may decide to turn this into an app![]()
South Africa’s biggest forum. Discuss, discover, and connect with thousands of members.
Thank you, will happily buy you a coffee once doneIf I have time I may decide to turn this into an app![]()
I was talking more about storing the data.Remember the barcode only includes information also visible on the front of the ID or Driver's license. When you hand your ID/Driver's to someone to scan you are giving them consent to view this information. Since the package does not entail the storage of any of the data I don't believe it goes against the POPI act.
If someone ends up using the package and subsequently storing the data, that's a different story.
The first block of 128 (from the above) that needs to be decrypted is as follows:I used this code, it did not fail however this doesn't decrypt it, almost looks more encryptedwill still play around but here is the base64 for the first 128 bytes after your code. Will this be UTF7, UTF8 UTF32 or ASCII
Input: 019b0945000060e9a27a1e475f89af17cb3a5ae86bd91152d22fbca1f462ba8bd39e9341bb26ad82e3ab1b4e68069247b75286edb64fed476c1a444bba7ffeca8ac9ddcf629ac582a865b8eefec682f33de40e68a6fc08265df86ad058376db56e4a9d2a2da285d11f408493fb4706abc346632a156b517c87b58372a3afda8be11dbae4a8f5a3d1881559ce0c69acd026770fd9e75c28c4abd0b2796e70eca894d8546bd8456bdcd9af0aa112f78b56523471b46805ae844a66108ba2f12a28180e5ddded48436239eae212c6193d351201e6a24613d2482ddae552bf7e21729246667a9cd5c730ba4b80736586f5f90894b1017fcea7b299cd6241a266c4b7b28b704de1f0266025358d134686e1cac2ba9af74ea16b9524f4fca20792d2618beec8499dbab596f5a56531f26462c996dad5e1278400a5266c5b5aed2dd3cae135821148bdfd3d564ac127c90d3a125031cb263e63879dfdd10725dc80225a700e5d259a5a1d2340d7bd2d3fecc9b078e1726661e2c51b945b56d762fa3067f2b926dd2707a74e1535abf1a7ee09b0ec40689cd3b3b9995dfdda9b5f33482f1441afa48304a68b24b942464d0334d4b20c17a6f09d5db119257212f7b2d48860e22c64924dc53c03557624a020b175ef47553946ce2e60c3f2ba95865d73b2d440c2fd3eb3c9850447c249c869444dbc103d8197c5556355e6c46455b61aa0b176bcc73290b532726d4339bb35b144fecf5c5d4c5e90aef23fc9c9375ae7206f9ea5a22255365f7e0728e3360cb78562c805a4f9a2b4a674eb5af30b598b98b16227a223505e2e013e426296e8f3d1ff03d6506fa431162438afabbc4e8b9626e8821d6bd264ff9d35a2df90e2be27e0297c162a0a6bbc937f349d31413484b52ca27255b2263abde2793cb946387685de9662777cdf6808a18c3a25759ed4e6ab6410f7881b655421be87e3f3df100062f12ae806059ca3e11248557080a64e4ec6e0a46697cae4c5c5197e3defdc
Output
WBGeyAilMi+CTwZUipZQxUgJV1jC3vbnIaV36erGswFimTiae8+NCw9ge9M5OLvxBZAKJb3VFU1OrAtTMLgm/3/K7rzVm0oDf9Oy+FMzvaKVcaNNWlNg3JVd2CedHLfatq++o09nlYzkb6OzNP1ZK+jvROBz6nFgipf2x2t//2w=
For anyone still interested, I have written an open source Dart package which provides the means to gather the information from a Driver's license barcode: https://pub.dev/packages/rsa_identification
Please leave a like on the package if you find it useful.
Thank you, will happily buy you a coffee once done
Hi Marcus,
Would you like to handle the scanning natively on the android devices?Hey guys. Does anyone understand if this tech / service is commercially available via api and who in South Africa provides the barcode decode service. I have a commercial use case but I need it to be legal and legit. I know Regula has an iOS app that reads the barcode on an ID quite efficiently but their costs at $8000 is prohibitive. Any insights would be appreciated.
So far I've gotten a 100% decode rate but admittedly the is on quite a small sample of around 10 driver's licences that I've triedHi Marcus,
Do you get a 100% decode rate, as for some reason, some licenses that i scan fail to decode.
They also start with 01 9b 09 45 followed by 00 but the rest does not decode according to the script.
By any chance do you know what could be the issue or have you encountered this as well?
So far I've gotten a 100% decode rate but admittedly the is on quite a small sample of around 10 driver's licences that I've tried![]()
Feel free to post it ...I also have the entire decryption and parsing ported to c#(portable to Xamarin android/ xamarin ios and linux)
I was thinking more in the line of selling copies of it. PM me your email address and i will send along a screen recoding of the decryption and parsing with my visual studio open.Feel free to post it ...
drive.google.com
Not worth it, new licenses coming in. Few will part with money for the old drivers license.I was thinking more in the line of selling copies of it. PM me your email address and i will send along a screen recoding of the decryption and parsing with my visual studio open.
bandicam 2021-06-15 13-24-02-563.mp4
drive.google.com
I know this is a bit old but this is what is inside your raw string (I have replaced some of it with "x" so that I can obfuscate some "sensitive" information:Hi,
I am also trying to get this problem solved on C#. I can get the sample that is given to work but as soon as I use my own I get gibberish again, would you mind 'testing' the hex I received and check if it decodes?
Raw:
019b09450000afc6a4c2ebd0768005365d9cdb4dba5bf649ab4084ac3abee3ec2ffe9a6502a3785daa72f0b766ca26067799ba7c7006b4febd906b7c92d72cf104f6bab63676fb0c861c24a1abe30177e4b54e6889a274aead70689d25e15077f53e3ee26c065208fdb3fe5a5502f228b0728414b7d5f5d7ee97af3ee39a5535c7955ab77e374453a3f5224e717684e716099453d5167dab4824c8a98acdea3630c805960ca147092b00169f28ce69feb07309d5272151fe69d74c89c1e6ea8ad94983bd744b741de582c9d202bc83f9e95ac79864d58ed225e4204b12083c4b198dfb5e14364ca362a0583cb66a73dc567e22c5c6c75963e47c8b9db69e36024b6669f20bc0aa56ea9b6b4a0f2fe4ae8144eb5d49a5af4a672904ede4230a82f4fc807b858e167038fd780d23a84311abbf243a8b845dfc180aa1b999b675c0ffe0b27419ec5d5b99ae0242850a074a3604e763c6a76bb5ce2389967e39ad5dfc240a2312038ac8f18808a11be7bdfc5b7cf546845d77ece574751a47296eb61b09c8d94ba261fbc5b0de393e465d2080b3bff9838953b8acd3c072247216970c979d93b3996112fe3ac28a96fec91b019afdeb71d186fd55e6766089ef560924d59ac0787b7ea634d5887febfb32c1770f8adb50e3e516b5b42d9cdecd39217c60373805ec20080a442533a3ce58cf1d5fea2fae0db971ac71a5deb5b00c06c37cfc171d5e8e36887ad1a160e7de6778114f8eb0dd88e5c2a0286466b6aadf8cf0ec61a57734023054d265b6c2494071ae82fe2632a020b1fedc418650407bf02e238ff5c5fa28cfbb649bd0c71b8040a4a5bb850b31f333b3e8a5d93df03b28d6c8d6bbe8d4123393a74545b26c77c489d30b0af9cea5425795ef66fdc2e8fcb5ea3e20d1445e73906b82bcaa91fab9d22dbc8bbf55fbb2d2a20792fbfd8464b85ee9e6ef33993ea4f14dbe4f261fc7cc2a95070e34ff1763b9596460cd0725c54dfc1880b70de453a470b3496ca5
Any help will be greatly appreciated!


#If Java
import java.lang.StringBuffer;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.StringReader;
import java.math.BigInteger;
import java.security.interfaces.RSAPublicKey;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import java.util.Base64;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.Provider;
import java.security.Security;
//import org.bouncycastle.jce.provider.JDKKeyFactory;
//import org.bouncycastle.jce.provider.JDKKeyFactory.RSA;
static{
Provider BC = new BouncyCastleProvider();
Security.addProvider(BC);
}
private static RSAPublicKey pubKey;
//Unsigned integer types have no direct equivalent in Java:
public static byte[] GetPaddedValue(BigInteger value, int length) {
//Unsigned integer types have no direct equivalent in Java:
byte[] result = value.toByteArray();
if (result[0] == 0) {
byte[] padded = new byte[length];
for (int i = 0; i < 128; i++) {
padded[i] = result[i+1];
}
return padded;
} else {
byte[] padded = new byte[length];
System.arraycopy(result, 0, padded, (length - result.length), result.length);
return padded;
}
}
public static byte[] EncryptValue(byte[] rgb, BigInteger e, BigInteger n, int size) {
BigInteger input = new BigInteger(rgb);
BigInteger output = input.modPow(e, n);
byte[] result = GetPaddedValue(output, size);
return result;
}
//Version 2 code for first 5 blocks of 128 bytes
public static String decodeVersion2First5Blocks(byte[] mybyte) {
String longKey = "-----BEGIN RSA PUBLIC KEY-----" + "\r\n" +
"MIGWAoGBAMqfGO9sPz+kxaRh/qVKsZQGul7NdG1gonSS3KPXTjtcHTFfexA4MkGA" + "\r\n" +
"mwKeu9XeTRFgMMxX99WmyaFvNzuxSlCFI/foCkx0TZCFZjpKFHLXryxWrkG1Bl9+" + "\r\n" +
"+gKTvTJ4rWk1RvnxYhm3n/Rxo2NoJM/822Oo7YBZ5rmk8NuJU4HLAhAYcJLaZFTO" + "\r\n" +
"sYU+aRX4RmoF" + "\r\n" +
"-----END RSA PUBLIC KEY-----";
String base64 = null;
try {
StringReader reader = new StringReader(longKey);
PEMReader pem = new PEMReader(reader);
pubKey = (RSAPublicKey) new PEMReader(reader).readObject();
RSAKeyParameters o = new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());
//Unsigned integer types have no direct equivalent in Java:
byte[] data = mybyte;
//Unsigned integer types have no direct equivalent in Java:
byte[] decrypted = EncryptValue(data, o.getExponent(), o.getModulus(), 128);
base64 = Base64.getEncoder().encodeToString(decrypted);
} catch (Exception e) {
BA.Log("RSA decryption error : " + e);
}
return base64;
}
#End If
#Region Project Attributes
#MainFormWidth: 600
#MainFormHeight: 600
#End Region
#AdditionalJar: bcprov-jdk16-1.43
Sub Process_Globals
Private fx As JFX
Private MainForm As Form
Private xui As XUI
Dim su As StringUtils
Dim dl As String = ""
Dim nativeMe As JavaObject
Private TextArea1 As TextArea
Private Button1 As Button
Private ListView1 As ListView
End Sub
Sub AppStart (Form1 As Form, Args() As String)
MainForm = Form1
MainForm.RootPane.LoadLayout("Layout1")
MainForm.Show
nativeMe = Me
TextArea1.Text = "019b0945000060e9a27a1e475f89af17cb3a5ae86bd91152d22fbca1f462ba8bd39e9341bb26ad82e3ab1b4e68069247b75286edb64fed476c1a444bba7ffeca8ac9ddcf629ac582a865b8eefec682f33de40e68a6fc08265df86ad058376db56e4a9d2a2da285d11f408493fb4706abc346632a156b517c87b58372a3afda8be11dbae4a8f5a3d1881559ce0c69acd026770fd9e75c28c4abd0b2796e70eca894d8546bd8456bdcd9af0aa112f78b56523471b46805ae844a66108ba2f12a28180e5ddded48436239eae212c6193d351201e6a24613d2482ddae552bf7e21729246667a9cd5c730ba4b80736586f5f90894b1017fcea7b299cd6241a266c4b7b28b704de1f0266025358d134686e1cac2ba9af74ea16b9524f4fca20792d2618beec8499dbab596f5a56531f26462c996dad5e1278400a5266c5b5aed2dd3cae135821148bdfd3d564ac127c90d3a125031cb263e63879dfdd10725dc80225a700e5d259a5a1d2340d7bd2d3fecc9b078e1726661e2c51b945b56d762fa3067f2b926dd2707a74e1535abf1a7ee09b0ec40689cd3b3b9995dfdda9b5f33482f1441afa48304a68b24b942464d0334d4b20c17a6f09d5db119257212f7b2d48860e22c64924dc53c03557624a020b175ef47553946ce2e60c3f2ba95865d73b2d440c2fd3eb3c9850447c249c869444dbc103d8197c5556355e6c46455b61aa0b176bcc73290b532726d4339bb35b144fecf5c5d4c5e90aef23fc9c9375ae7206f9ea5a22255365f7e0728e3360cb78562c805a4f9a2b4a674eb5af30b598b98b16227a223505e2e013e426296e8f3d1ff03d6506fa431162438afabbc4e8b9626e8821d6bd264ff9d35a2df90e2be27e0297c162a0a6bbc937f349d31413484b52ca27255b2263abde2793cb946387685de9662777cdf6808a18c3a25759ed4e6ab6410f7881b655421be87e3f3df100062f12ae806059ca3e11248557080a64e4ec6e0a46697cae4c5c5197e3defdc"
End Sub
Private Sub Button1_Click
Dim ss As String
ss = TextArea1.Text.Trim
ListView1.Items.Clear
Log("ss = " & ss)
Log("ss length = " & ss.Length)
Dim block1 As String = ss.SubString2(10,268)
Dim conv As ByteConverter
Dim mybyte() As Byte = conv.HexToBytes(block1)
Log("MYSTRING LENGTH = " & block1.Length)
Dim returnedstring As String
returnedstring = nativeMe.RunMethod("decodeVersion2First5Blocks", Array(mybyte))
Dim MyBase64String As String = returnedstring
Dim MyBase64StringAsBytes() As Byte = su.DecodeBase64(MyBase64String)
Log("LENGTE = " & MyBase64StringAsBytes.Length)
Dim s As String = BytesToString(MyBase64StringAsBytes, 0, MyBase64StringAsBytes.Length, "ISO8859_1")
Dim karak(128) As String
Dim finalstring As String = ""
For i = 0 To s.Length - 1
Dim c As Char = s.CharAt(i)
Dim ub As Int = Bit.And(0xff, MyBase64StringAsBytes(i))
karak(i) = Bit.ToHexString(ub)
If karak(i).Length = 1 Then karak(i) = "0" & karak(i)
finalstring = finalstring & karak(i)
Log("char = " & c & " karak = " & karak(i) & " MyBase64StringAsBytes(" & i & ") = " & karak(i))
Next
Dim section1_length As Int = Bit.ParseInt(karak(10), 16)
Dim section2_length As Int = Bit.ParseInt(karak(12), 16)
Dim section1 As String = ""
For i = 15 To (15 + section1_length)
If karak(i).Trim = "e0" Then
karak(i) = ","
section1 = section1 & karak(i)
else if karak(i).Trim = "e1" Then
karak(i) = "[]"
section1 = section1 & karak(i)
Else
Dim c As Char = s.CharAt(i)
section1 = section1 & c
End If
Next
section1 = section1
Log("section1 = " & section1)
section1 = section1.Replace("[][][]", ",,,,")
section1 = section1.Replace("[][]", ",,,")
section1 = section1.Replace("[]", ",,")
Log("section1 = " & section1)
Dim headings() As String = Array As String("License type 1: ", "License type 2: ", "License Type 3: ", "License Type 4: ", _
"Surname: ", "Initials: ", "PrDP Code: ", "ID Country of Issue: ", "License Country of Issue: ", _
"Vehicle Restriction L1: ", "Vehicle Restriction L2: ", "Vehicle Restriction L3: ", "Vehicle Restriction L4: ", _
"License Number: ", "ID Number: ")
DateTime.DateFormat = "yyyy/MM/dd"
ListView1.Items.Add("Date: " & DateTime.Date(DateTime.Now))
ListView1.Items.Add("Time: " & DateTime.Time(DateTime.Now))
Dim Lines() As String = Regex.Split(",",section1)
For i = 0 To Lines.Length - 1
ListView1.Items.Add(headings(i) & Lines(i))
Log(""& headings(i) & " " & Lines(i))
Next
Dim section2 As String = ""
For i = (15 + section1_length) To (15 + section1_length + section2_length - 1)
If i = 15 + section1_length Then
section2 = section2 & karak(i).Trim
End If
If i > 15 + section1_length Then
If karak(i).Trim.SubString2(0,1) = "a" Then
section2 = section2 & "."
Else
section2 = section2 & karak(i).Trim.SubString2(0,1)
End If
If karak(i).Trim.SubString2(1,2) = "a" Then
section2 = section2 & "."
Else
section2 = section2 & karak(i).Trim.SubString2(1,2)
End If
End If
Next
If section2.EndsWith(".") = True Then
section2 = section2.SubString2(0, section2.Length - 1)
End If
Dim amendedSection2 As String = ""
For i = 0 To section2.Length - 1
If section2.SubString2(i, i+1) <> "." Then
amendedSection2 = amendedSection2 & section2.SubString2(i, i+1)
Else
amendedSection2 = amendedSection2 & "........"
End If
Next
Dim idType As String = amendedSection2.SubString2(0,2)
Dim issueDate1 As String = amendedSection2.SubString2(2, 10)
Dim issueDate2 As String = amendedSection2.SubString2(10,18)
Dim issueDate3 As String = amendedSection2.SubString2(18, 26)
Dim issueDate4 As String = amendedSection2.SubString2(26, 34)
Dim driverRestrictions As String = amendedSection2.SubString2(34, 36)
Dim PrDPdate As String = amendedSection2.SubString2(36, 44)
Dim licenseIssueNumber As String = amendedSection2.SubString2(44, 46)
Dim birthDate As String = amendedSection2.SubString2(46, 54)
Dim validFrom As String = amendedSection2.SubString2(54, 62)
Dim validTo As String = amendedSection2.SubString2(62, 70)
Dim gender As String = amendedSection2.SubString2(70, 72)
ListView1.Items.Add("ID Number Type: " & idType)
Log("ID Number Type: " & idType)
ListView1.Items.Add("Issue Date L1: " & issueDate1)
Log("Issue Date L1: " & issueDate1)
ListView1.Items.Add("Issue Date L2: " & issueDate2)
Log("Issue Date L2: " & issueDate2)
ListView1.Items.Add("Issue Date L3: " & issueDate3)
Log("Issue Date L3: " & issueDate3)
ListView1.Items.Add("Issue Date L4: " & issueDate4)
Log("Issue Date L4: " & issueDate4)
ListView1.Items.Add("Driver Restrictions: " & driverRestrictions)
Log("Driver Restrictions: " & driverRestrictions)
ListView1.Items.Add("PrDP Expiry Date: " & PrDPdate)
Log("PrDP Expiry Date: " & PrDPdate)
ListView1.Items.Add("License Issue Number: " & licenseIssueNumber)
Log("License Issue Number: " & licenseIssueNumber)
ListView1.Items.Add("Birth Date: " & birthDate)
Log("Birth Date: " & birthDate)
ListView1.Items.Add("Valid From: " & validFrom)
Log("Valid From: " & validFrom)
ListView1.Items.Add("Valid To: " & validTo)
Log("Valid To: " & validTo)
If gender = "01" Then gender = "Male" Else gender = "Female"
ListView1.Items.Add("Gender: " & gender)
Log("Gender: " & gender)
End Sub