parse basic user data

This commit is contained in:
nganhkhoa 2023-03-07 21:06:01 +07:00
parent 7644e834c6
commit cb028e345d
2 changed files with 102 additions and 1 deletions

View File

@ -377,6 +377,77 @@ bytes Connector::readBinary(size_t offset, size_t length) {
#define VERBOSE_LOGGING VERBOSE_LOGGING_OFF
}
void Connector::set_user_data(bytes mrz) {
if (mrz.size() != 90) {
throw "MRZ data must be 90 bytes";
}
std::string line1(mrz.begin(), mrz.begin() + 30);
std::string line2(mrz.begin() + 30, mrz.begin() + 60);
std::string line3(mrz.begin() + 60, mrz.end());
std::string hash1 = line2.substr(line2.size()-1);
std::string data1 = line1.substr(5) + line2.substr(0, 7) + line2.substr(8, 7) + line2.substr(18, 11);
// assert(check_digit(data1) == std::stoi(hash1));
std::smatch match1;
std::regex_match(line1, match1, std::regex("ID(\\w{3})(\\d{9})(\\d)([\\w\\d<]{15})"));
passport.country = match1[1];
passport.documentNumber = match1[2];
std::string hash_id = match1[3], optional_line1 = match1[4];
// assert(check_digit(id) == std::stoi(hash_id));
std::smatch match2;
std::regex_match(line2, match2, std::regex("(\\d{2})(\\d{2})(\\d{2})(\\d)([MF])(\\d{2})(\\d{2})(\\d{2})(\\d)(\\w{3})([\\w\\d<]{11})(\\d)"));
std::string birth_year = match2[1], birth_month = match2[2], birth_day = match2[3], hash_birth = match2[4];
std::string expire_year = match2[6], expire_month = match2[7], expire_day = match2[8], hash_expire = match2[9];
std::string optional_line2 = match2[11], hash_line2 = match2[12];
passport.nationality = match2[10];
passport.gender = match2[5];
// assert(check_digit(birth_year+birth_month+birth_day) == std::stoi(hash_birth));
// assert(check_digit(expire_year+expire_month+expire_day) == std::stoi(hash_expire));
tm birth_tm = {0}, expire_tm = {0};
birth_tm.tm_year = std::stoi(birth_year) + 100;
if (birth_tm.tm_year > (2023 - 1900)) {
birth_tm.tm_year -= 100;
}
birth_tm.tm_mon = std::stoi(birth_month) - 1;
birth_tm.tm_mday = std::stoi(birth_day);
expire_tm.tm_year = std::stoi(expire_year) + 100;
expire_tm.tm_mon = std::stoi(expire_month) - 1;
expire_tm.tm_mday = std::stoi(expire_day);
passport.birthDate = mktime(&birth_tm);
passport.expiryDate = mktime(&expire_tm);
// trim ending <
line3.erase(std::find_if(line3.rbegin(), line3.rend(), [](unsigned char ch) {
return ch != '<';
}).base(), line3.end());
auto nameparser = std::istringstream(line3);
std::string familyname;
std::getline(nameparser, familyname, '<');
nameparser.get();
std::vector<std::string> name_components;
for (std::string tmp; std::getline(nameparser, tmp, '<'); ) {
name_components.push_back(tmp);
}
}
void Connector::set_user_picture(bytes dg2) {
auto pattern1 = bytes{0xFF, 0xD8, 0xFF, 0xE0};
auto pattern2 = bytes{0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50};
auto im_start = std::search(dg2.begin(), dg2.end(), pattern1.begin(), pattern1.end());
if (im_start == dg2.end()) {
im_start = std::search(dg2.begin(), dg2.end(), pattern2.begin(), pattern2.end());
}
passport.portrait = bytes(dg2.begin() + std::distance(dg2.begin(), im_start), dg2.end());
}
void Connector::readEFCOM() {
auto content = readFileBySFI(EFCOM_SFI);
LOGI("FILE COM size %d", content.size());
@ -389,6 +460,12 @@ void Connector::readEFDG1() {
LOGI("FILE DG1 size %d", content.size());
logBytes("FILE DG1 sha256 %s", digest);
calculatedDigests[1] = digest;
// skip 2 bytes application data
// skip 2 bytes tag 5f1f
// skip 1 byte length
content.erase(content.begin(), content.begin() + 5);
set_user_data(content);
}
void Connector::readEFDG2() {
auto content = readFileBySFI(EFDG2_SFI);
@ -396,6 +473,7 @@ void Connector::readEFDG2() {
SHA256(content.data(), content.size(), digest.data());
LOGI("FILE DG2 size %d", content.size());
logBytes("FILE DG2 sha256 %s", digest);
set_user_picture(content);
calculatedDigests[2] = digest;
}
void Connector::readEFDG13() {

View File

@ -12,6 +12,19 @@
#include "utils.h"
#include "des.h"
struct PassportData {
std::string country;
std::string documentNumber;
std::string gender;
std::string nationality;
std::string familyName;
std::vector<std::string> nameComponents;
time_t birthDate;
time_t expiryDate;
bytes portrait;
};
class TLV {
public:
@ -230,9 +243,12 @@ private:
bytes readFileBySFI(int sfi);
bytes readBinary(size_t offset, size_t length);
void set_user_data(bytes data);
void set_user_picture(bytes data);
std::unordered_map<int, bytes> calculatedDigests;
// chip's public key
bytes dg15;
public:
@ -241,7 +257,14 @@ public:
int readAheadLength = 8;
Connector(transceive_type transceive) : transceive(transceive) {}
std::string passcode;
public:
bool ready = false;
PassportData passport;
Connector(transceive_type transceive, std::string passcode) : transceive(transceive), passcode(passcode) {}
bool selectDf1();
void initBAC();