Passport MRZ Scanner

Using python and external APIs calls, I created a passport MRZ scanner.

Background

I took this project because I am eager to expand my knowledge and skills surrounding the integration and uses of APIs and back-end functional programming. I wanted to understand how everyday digital security verification processes take place, and whether I could combine my research into cyber security and knowledge of python programming to create a working example of how a verification process can take place.

I wanted to recreate the digital verification process, although I thought this to be too simple. I discovered the idea of relieving a user of having to manually type the details of a passport, in order to provide an easy to use and fluid feeling program. Manually typing details could result in human error and therefore details would have to be typed again. Therefore I decided to create a machine that scans people's passports and verifies it for them.

The Aim

The aim of this project was to create a mock environment where the user can compare input data and a passport picture document, provided through a tkinter user interface, to verify they match one another. The user enters their data relevant to the passport document, in this case their name and date of birth, then the data from the input data fields and the picture file is cross-checked to ensure passport validity.

To solve whether the passport is valid, the idea is to analyse the bottom level of the MRZ code from the passport is legitimate. As an MRZ code is 44 characters long it is a particularly unsatisfactory journey for the user to have to input. Additionally, having to manually input 44 characters invites the possibility of a human error causing them to have to reinput the code, therefore the picture of the passport is to be scanned and the MRZ validation made a quick and easy process. Overall, through successful cross-checks and a successful check digit algorithm on the bottom level MRZ code, I can establish whether the user data submitted is legitimate.

Research

In this project the following resources enbaled me to construct and develop the algorithm:

A website I discovered enabled me to view the properties of a passport, which in turn assisted in determining what would be the best content to analyse. This resource explained how the bottom level of the MRZ of a passport works. This assisted me to program my own version of an authenticator to ensure that everything checked out when submitting a bottom level MRZ string, through both manual and automated testing of real documents.

http://www.highprogrammer.com/alan/numbers/mrp.html

...

During my development process, I had access to some test APIs on a sandbox environment that allowed me to upload a photo of a passport and give me all the characters back. I had to utilise 2 API calls for my project. One was to authenticate the use of the service which I had access to; the other was to actually upload an image of a passport and to give me the OCR (optical character recognition) extracted fields back which makes it easy for the user to input their MRZ and also check amongst other fields. The API is provided with a step-by-step guide for integration and gives good direction on how to operate its OCR capabilities.

https://docs.idscan.com/docs/ieos-web-api-9-2-21-4/

Development

I first started with the construction of the MRZ check digit algorithm, the centrepiece within the project, ensuring the functionality of this algorithm was essential. I manually input MRZ codes from the test MRZ listed on the API website previous referenced, and also used my own to assure external existing passports worked also. Passports contain sensitive information which can lead to identity theft or other illicit activity, to ensure the algorithm complies with data protection laws I installed the base64 module, which encodes the data and decodes it upon its return from the APIs. Some basic validation to ensure that MRZ number was the correct size was also factored in at this stage before this became redundant on the photo upload stage a little later on in my project.

I first started with the construction of the MRZ check digit algorithm, the centrepiece within the project, ensuring the functionality of this algorithm was essential. I manually input MRZ codes from the test MRZ listed on the API website previous referenced, and also used my own to assure external existing passports worked also. Passports contain sensitive information which can lead to identity theft or other illicit activity, to ensure the algorithm complies with data protection laws I installed the base64 module, which encrypts the data and decrypts it upon its return from the APIs. In my algorithm, I would check 4 different check digits on the MRZ number. These would initialise as False until each part had been examined, as to be valid they were all need to correspond with each other and the code executes synchronously. The MRZ in question would also factor in all the initialised string variables such as 'passNumber' or 'personalNumber'. Each would be scrutinised at some point and I decided it would be easier to extract each segment separately by string variable manipulation on the MRZ in the next section.

The following code demonstrates the initialisation of the checks to be carried out by the APIs OCR system. Having periodical checks at different intervals ensures the validity of the data in correspondence to the input data provided manually by the user. The 'for' range is limited to 44 as that is the number of characters in an MRZ. This is an example of the data being compared to that of the data retrieved by the OCR. The data is transmitted and communicated back to the variables via JSON.

...

The data is extracted and decoded using the base64 package, then outputted back to the user using the variables they are assigned to.

The nature of the algorithm meant that I needed to give each instance of an alpha character a numeric value for the algorithm to do its relevant calculations. I created a function to output the relevant numeric value when a letter was given e.g. when GBR would be present in the MRZ number, I would need to convert this to '16 11 27'. Creating this function allowed me to abstract the process and not create separate code for each letter in question.

The way the algorithm works is dependant using iterations of the numbers above in a constant loop. Each numeric number in question would need to be multiplied by a single value in the array above incrementally e.g. character 1 of the MRZ would be multiplied by index 0 of the multiplications table, then character 2 of the MRZ would be multiplied by index 1 of the multiplications table, then character 3 of the MRZ would be multiplied by index 2 of the multiplications table, then character 4 of the MRZ would be multiplied by index 0 once again as the loop resets and this would continue through the whole of the MRZ until the end.

...

The algorithm is then carried out as explained in the supported resource in each stage. A total value is calculated and then a MOD 10 is applied to the result. The result of the total MOD 10 should then equal the check digit. If this does, then the check digit will possess a value of True. This process is replicated for each of the other check digits below.

...

The final section of the process finishes with the status checks. As a result of all the check digits, if each is flagged as 'True', the user can then confirm that the MRZ entered was valid and displays the correct message and thus the algorithm is complete.

GUI

A simple GUI was created using an inbuilt python module called Tkinter. This was built for the purpose of demonstrating the use of a form to the user, not necessarily in a way that looks appealing but more so focused on the functionality.

A simple form is displayed to the user requesting the Forename, Surname, Date of birth and an Image File Path.

API: OCR Extraction

The nature of the character extraction will occur through third party APIs. An image of an ID document is sent to this API and then the results of the OCR extraction are then fed back as a JSON response. To first use this, I must authenticate the use of the service through credentials I have been given sandbox access to.

The getCookie code was created using a supporting piece of software called Postman. I had to select the appropriate payload and headers, and this was then generated into a Python format. An access token was granted for usage of the main API call.

When sending the image, the jpg must first be encoded in a base64 format so that it fits the API schema. The path is collected from the GUI and the program will assume the path to the file leads to an image file. It will then encode this image file into a base64 format ready for submission.

The parameter format information granted within the APIs general information was extensively analysed to ensure code compatibility with the API, such as specific data type requirements.

A separate function has been created for the sending of the passport to the service. Once again, postman has supported me in generating the API call in a Python format. The function will take the access token created in the other API call and the base64 encoded image to parse into the payload. A separate token is also required for usage and this is requested in the CLI. The response will then feedback the results of the passport.

...
...

The token expires every 24 hours and requires a new token to be able to request their API, as demonstrated.

...

The code successfully executes and as shown, the data is in order and as expected. Through completion of this project I have achieved a more fulfilled understanding of API integrations, which I am confident will provide good experience for future ambitions.