/// <summary> /// Parses a MRZ string. /// </summary> /// <param name="mrz">The MRZ string to parse.</param> /// <returns>The parsed MRZ data.</returns> /// <seealso> /// https://en.wikipedia.org/wiki/Machine-readable_passport /// https://www.icao.int/publications/Documents/9303_p3_cons_en.pdf /// </seealso> public static MrzData Parse(string mrz) { if (mrz == null) { throw new ArgumentNullException(mrz); } else if (mrz.Length != 88) { throw new ArgumentException($"MRZ length is not valid. Should be 88 but it is {mrz.Length}", nameof(mrz)); } var output = new MrzData { DocumentType = ParseDocumentType(mrz), Gender = ParseGender(mrz), ExpireDate = ParseExpireDate(mrz), IssuingCountryIso = ParseIssuingCountryIso(mrz), FirstName = ParseFirstName(mrz), LastName = ParseLastName(mrz), DocumentNumber = ParseDocumentNumber(mrz), NationalityIso = ParseNationalityIso(mrz), DateOfBirth = ParseDateOfBirth(mrz), }; return(output); }
/// <summary> /// Creates an MRZ string from MRZ data. /// </summary> /// <param name="mrzData">The MRZ data.</param> /// <returns>The MRZ string.</returns> public static string CreatMrz(MrzData mrzData) { if (string.IsNullOrEmpty(mrzData.IssuingCountryIso)) { throw PropertyArgumentException(mrzData.IssuingCountryIso, nameof(mrzData)); } else if (string.IsNullOrEmpty(mrzData.LastName)) { throw PropertyArgumentException(mrzData.LastName, nameof(mrzData)); } else if (string.IsNullOrEmpty(mrzData.FirstName)) { throw PropertyArgumentException(mrzData.FirstName, nameof(mrzData)); } else if (string.IsNullOrEmpty(mrzData.DocumentNumber)) { throw PropertyArgumentException(mrzData.DocumentNumber, nameof(mrzData)); } else if (string.IsNullOrEmpty(mrzData.NationalityIso)) { throw PropertyArgumentException(mrzData.NationalityIso, nameof(mrzData)); } else if (string.IsNullOrEmpty(mrzData.Gender)) { throw PropertyArgumentException(mrzData.Gender, nameof(mrzData)); } else if (mrzData.DateOfBirth.Year < 1901) { throw new ArgumentException($"The {nameof(mrzData.DateOfBirth)} is less than 1901.", nameof(mrzData)); } else if (mrzData.ExpireDate.Year < 1901) { throw new ArgumentException($"The {nameof(mrzData.ExpireDate)} is less than 1901.", nameof(mrzData)); } var docType = mrzData.DocumentType; if (docType.Length < 2) { docType += "<"; } var line1 = docType + mrzData.IssuingCountryIso + (mrzData.LastName + "<<" + mrzData.FirstName).Replace(" ", "<"); line1 = line1.PadRight(44, '<').Replace("-", "<"); if (line1.Length > 44) { line1 = line1.Substring(0, 44); } var line2 = mrzData.DocumentNumber.PadRight(9, '<') + GetCheckDigit(mrzData.DocumentNumber.PadRight(9, '<')) + mrzData.NationalityIso + mrzData.DateOfBirth.ToString(DateFormat) + GetCheckDigit(mrzData.DateOfBirth.ToString(DateFormat)) + mrzData.Gender.Substring(0, 1) + mrzData.ExpireDate.ToString(DateFormat) + GetCheckDigit(mrzData.ExpireDate.ToString(DateFormat)); line2 = line2.PadRight(42, '<') + "0"; var compositeCheckDigit = GetCheckDigit(line2.Substring(0, 10) + line2.Substring(13, 7) + line2.Substring(21, 22)); line2 += compositeCheckDigit.Replace("-", "<"); return(line1 + line2); }