---
# System prepended metadata

title: 'KYCC+, OCR, MRZ - Tech design'
tags: [Identities, MRZ]

---

KYCC+, OCR, MRZ - Tech design
===


## Table of Contents

[TOC]

## Background - What we have now

- Identity fields - We have now
    

| Order | CodeName         		 | Type         |
| ------| --------         		 | --------     |
| 0     | email            		 | identity     |
| 1     | given_name       		 | identity     |
| 2     | family_name      		 | identity     |
| 3     | address          		 | identity     |
| 4     | dob              		 | identity     |
| 5     | phone            		 | identity     |
| 6     | passport         		 | identity     |
| 7     | selfie           		 | identity     |
| 8     | proof_of_address 		 | identity     |
| 9     | crypto_address_eth     | extra        |
| 10    | crypto_address_btc     | extra        |
| 11    | national_id            | identity     |
| 12    | driving_license        | identity     |
| 13    | selfie_national_id     | identity     |
| 14    | selfie_driving_license | identity     |

- RootHash calculation
    
    Procedure [core code](https://github.com/blockpass-org/blockpass-api-private/blob/b3b28d3c10ef9d2cdd2765373d96dd5a954d08f1/api/services/MerkleTreeService.js#L29):
```
    1. A = Get all identities order_by `order` column
    2. A = A filter `identity` only 
    3. B = Map user hash ( leave '' if missing )
    4. Calculate tree base on B
    
```

Example:
``` mermaid
graph TD;
    Root-->L01;
    Root-->L23;

    L01--> L0
    L01--> L1
    L0--> `email`;
    L1-->`given_name`;


    L23--> L2
    L23--> L3
    L2-->`family_name`;
    L3-->`address`;

```

- Extra filed:

    - [MA]
        - Extra fields are stored same as identity fields 
        
    - [Core]
        - Extra fields aren't included in Merkle root
        - Extra fields aren't stored inside Database
        - Extra fields hash stored in `SubmitLog` - Will be deleted after disconnect
        
    - [KYCC+] 
        - Extra fields are treated same as identity fields (reject / resubmit / approve) -> included into certificate Entity

After MRZ
---
- After MA(Mobile app) implement MRZ reader Passport fields can have some metadata below [ref](https://en.wikipedia.org/wiki/Machine-readable_passport)

    - MRZ
    - Expiration date
    - Name
    - Surname(s)
    - Date of birth
    - Issuing country
    - Nationality
    - Passport number
    - Gender

Proposal - MRZ field treated as 'extra'
---

| Order | CodeName         		     | Type         |
| ------| --------         		     | --------     |
| 15    | passport_mrz               | extra        |
| 16    | passport_number            | extra        |
| 17    | passport_expiration        | extra        |
| 18    | passport_family_name       | extra        |
| 19    | passport_given_name        | extra        |
| 20    | passport_dob               | extra        |
| 21    | passport_issuing_country   | extra        |
| 22    | passport_nationality       | extra        |
| 23    | passport_gender            | extra        |

- Onfido Cert
    - passport
    - passport_*  - To be discuss *
    - selfie(Passport)


- Pros: 
    - Core doesn't store those data permanently (only in `SubmitLog`)
    - It almost same with others identities (approve, reject, certificate 's Entity)
    - Free to add more fields no need re-calculate merkle root
    - [Toan] Easy for MA to upgrade from old version to new one 
    
- Cons:
    - Core can't check identity duplication (don't have mrz hash)
    - Core can't validate `Passport` vs `Passport-Data` integrity without **Onfido Cert**
    - [Toan] extra fields must be handled explicitly from DP & MA
    - [Toan] user will need to take photo of passport again for the MRZ fields (in case the MRZ lib does not support scanning offline picture, or the quality is bad)

- KYCConnect - Procedure to detect duplicate
    - Minimum Requirement:
        - OnfidoCert
        - passport
        - passport_mrz
    - Check
```
    1. Verify signature OnfidoCert => false return
    2. check hash(passport_mrz) === cert.Entity.passport_mrz && hash(passport) === cert.Entity.passport => false return
    3.(extra) Check with Core if passport doesn't have any updates
    
=> Now can trust and check passport_mrz duplicate inside database
```

Proposal - MRZ field treated as 'attribute' of passport
---
The `passport` field will be converted to JSON format, each MRZ meta is stored as sub-attribute of it
```
{
    passport: {
        image: 'image_base64_encoded',
        name: 'string',
        sur_name: 'string'
        mrz: 'string',
        expiration: 'string',
        dob: 'string',
        issuing_country: 'country_code_3',
        nationality: 'country_name',
        number: 'string',
        gender: 'string'
    }
}
```
- Onfido cert:
    - passport (new format)
    - selfie (with passport)
- Pros:
    - If a Service requires `passport`, it automatically receives all related meta data
- Cons:
    - If a Service requires `passport`, it is forced to receive all related meta data. No way to require meta data individually
    - The hash in Onfido cert is for whole `passport` field (including meta), unless we modify the way we hash identity fields
    - Hard to check for passport duplication
    - Hard for MA to convert & KYCC to handle different version of `passport` fields

## Reference

- Product design - https://docs.google.com/document/d/1Trq-WIAfrsf1sC1P7z7b4nDRpbTqywVNJLIJ9OrT1Lc/edit#
:::info
**Find this document incomplete?** Leave a comment!
:::

###### tags: `MRZ` `Identities`
