Closed puneetmahali closed 4 years ago
Sorry, I'm not quite sure what you mean.
I'm can't say what checks you should or would need to carry out - that's totally up to you and what your requirements are!
For example if you needed to verify that a passport was genuine and not forged then you would want to do passive and active authentication, plus check revocation lists, and what ever checks you feel you would need to do. The code currently can do passive and active with - which includes verifying hashes of the datagroups to check for tampering and checking the certificates on the passport, but as mentioned before doesn't yet check revocation lists.
If however you just wanted to read the passport data and didn't actually care if the document is valid then you could skip the checks.
I'd recommend reading the ICAO documentation on epassports (I think I've linked it from github bit of not then a simple google search will find it). That goes into much more detail on what security checks should be done by dedicated readers which may help.
Cheers Andy
Sent from my iPhone
On 7 Jan 2020, at 18:01, Puneet Mahali notifications@github.com wrote:
Hi @AndyQ , Can you please let me know if I need to give some security checks with backend then which data(Something like Json data) need to validate with the DB? I mean like somehow we can validate DG(all Data Groups e.g. DG1, DG2......DG15) or after tag detecting we can store all chip data somewhere and validate it from the database.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.
Hi Andy, Yeah I read the ICAO 9303 but my question is: After detecting the tag from the passport chip. Is there any way to see all detected data groups data in array / dictionary format like name, address, Date of birth etc etc. so , I can send the all data into the database?
Sent from my iPhone
On 7. Jan 2020, at 7:09 PM, Andy Qua notifications@github.com wrote:
Sorry, I'm not quite sure what you mean.
I'm can't say what checks you should or would need to carry out - that's totally up to you and what your requirements are!
For example if you needed to verify that a passport was genuine and not forged then you would want to do passive and active authentication, plus check revocation lists, and what ever checks you feel you would need to do. The code currently can do passive and active with - which includes verifying hashes of the datagroups to check for tampering and checking the certificates on the passport, but as mentioned before doesn't yet check revocation lists.
If however you just wanted to read the passport data and didn't actually care if the document is valid then you could skip the checks.
I'd recommend reading the ICAO documentation on epassports (I think I've linked it from github bit of not then a simple google search will find it). That goes into much more detail on what security checks should be done by dedicated readers which may help.
Cheers Andy
Sent from my iPhone
On 7 Jan 2020, at 18:01, Puneet Mahali notifications@github.com wrote:
Hi @AndyQ , Can you please let me know if I need to give some security checks with backend then which data(Something like Json data) need to validate with the DB? I mean like somehow we can validate DG(all Data Groups e.g. DG1, DG2......DG15) or after tag detecting we can store all chip data somewhere and validate it from the database.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.
Yes that's in the Passport model returned.
There are a couple of methods that may help: The dataGroupsPresent property says which datagroups were read (may be less that you requested if they weren't present) The getDataGroup method will get the raw datagroup.
If you want a different cut of this then you would probably need to modify the code to return what you need.
Cheers Andy
Sent from my iPhone
On 7 Jan 2020, at 18:55, Puneet Mahali notifications@github.com wrote:
Hi Andy, Yeah I read the ICAO 9303 but my question is: After detecting the tag from the passport chip. Is there any way to see all detected data groups data in array / dictionary format like name, address, Date of birth etc etc. so , I can send the all data into the database?
Sent from my iPhone
On 7. Jan 2020, at 7:09 PM, Andy Qua notifications@github.com wrote:
Sorry, I'm not quite sure what you mean.
I'm can't say what checks you should or would need to carry out - that's totally up to you and what your requirements are!
For example if you needed to verify that a passport was genuine and not forged then you would want to do passive and active authentication, plus check revocation lists, and what ever checks you feel you would need to do. The code currently can do passive and active with - which includes verifying hashes of the datagroups to check for tampering and checking the certificates on the passport, but as mentioned before doesn't yet check revocation lists.
If however you just wanted to read the passport data and didn't actually care if the document is valid then you could skip the checks.
I'd recommend reading the ICAO documentation on epassports (I think I've linked it from github bit of not then a simple google search will find it). That goes into much more detail on what security checks should be done by dedicated readers which may help.
Cheers Andy
Sent from my iPhone
On 7 Jan 2020, at 18:01, Puneet Mahali notifications@github.com wrote:
Hi @AndyQ , Can you please let me know if I need to give some security checks with backend then which data(Something like Json data) need to validate with the DB? I mean like somehow we can validate DG(all Data Groups e.g. DG1, DG2......DG15) or after tag detecting we can store all chip data somewhere and validate it from the database.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.
I tried with the getDataGroup methods but I didn't get the data over there on debug time but anyway I will try it tomorrow again. Basically I need some kind of json data so I can validate from the backend(my own backend) so I can check the security checks somehow.
For e.g.:- When I read the Passport tag then it's detect the DG1, DG2 & DG14. So, I want these DG's(datagroups) to send into the my database. or as you said the getDataGroup will provide the raw data. So, I am assuming that raw data should be in array or dictionary format which holds the all chip datagroup details.
PS:-Can you please add some comment on case no. #30 . About:- I want to create my own pods with the help of your code in Swift but In framework project I am unable to set up / install the OpenSSL. Can you please explain the installation steps. I will be so thankful to you.
So once you have a specific DataGroup - you have two fields you have access to: body - a UInt8 array containing the raw data that makes up the datagroup (including header) data - a UInt8 array containing the raw datagroup data (what the hashes are calculated from)
You could create your own Json request based on that - but what extra things are you trying to validate above what is currently done?
if you want the entire raw data you could also just capture the byte stream before it gets parsed out into DataGroups if you really wanted to.
Hi @AndyQ ,
Thanks for the answer on #30 .
In this case, I don't want to use x.509 certificates n all at the moment.
I am using the method like:-
// If we want to read only specific data groups we can using: let dataGroups : [DataGroupId] = [.COM, .SOD, .DG1, .DG2, .DG7, .DG11, .DG12, .DG14, .DG15] passportReader.readPassport(mrzKey: mrzKey, tags:dataGroups, completed: { (passport, error) in if let passport = passport { // All good, we got a passport DispatchQueue.main.async { self.passportDetails.passport = passport self.showDetails = true }
Here I am getting the data from passport(means passport.dataGroupsRead) it hold the five array of the detected Groups COM,.SOD, DG1, DG2, DG14. Noe the DG1 holds the 15 elements dictonary like: ▿ 15 elements ▿ 0 : 2 elements
So once you have a specific DataGroup - you have two fields you have access to: body - a UInt8 array containing the raw data that makes up the datagroup (including header) data - a UInt8 array containing the raw datagroup data (what the hashes are calculated from)
You could create your own Json request based on that - but what extra things are you trying to validate above what is currently done?
if you want the entire raw data you could also just capture the byte stream before it gets parsed out into DataGroups if you really wanted to.
I saw this comment lil late. Anyway, At the moment I need the detected groups data in a Json form with the hash keys. For example- If I detected the DG1 then I need all DG1 group detected data like id, Document_Type, Issuing State etc etc in a proper format which is mentioned in this document page no. 35. The Dict should hold the Key like DG1 and value says like filed, field value from the Passport chip & Hash Key.
OK, so DG1 is held internally as LDS tag identifiers (see ICAO 9303 Page doc 10 pages 15-18 for specific details but for example, 5A is the document number, 5F1F are the MRZ data elements, 5F03 is the document type, etc.
If you look a the top of the NFCPassportModel, you can see how the main elements from DG1 are extracted from the passportDataElements (DG1) You could get checksums out using keys 5F04, 5F05, 5F06, and. 5F07 (page 17 of above doc)
So that should give you pretty much what you need.
Yeah I already work with PassportModel Class and try to figure it out how can I deal with that? Yes, on page number 17 there is all data checksums of these things but Somehow I need to make a Json (5A is the document number, 5F1F are the MRZ data elements, 5F03 is the document type, etc.) with document number, mrz data element document type etc. Also I am not getting the hash keys. Please let me know how can I get the HAsh Keys. I know in PassportModel class have the function:
`public func getHashesForDatagroups( hashAlgorythm: String ) -> [DataGroupId:[UInt8]] { var ret = [DataGroupId:[UInt8]]()
for (key, value) in dataGroupsRead {
if hashAlgorythm == "SHA256" {
ret[key] = calcSHA256Hash(value.body)
} else if hashAlgorythm == "SHA1" {
ret[key] = calcSHA1Hash(value.body)
}
}
return ret
}`
But I am getting 0 key/value pair from this.
PS:- Somehow I need to produce the Json something like this: `{ "5B": { "name": "firstName", "data": "Puneet", "hash": "xxx" }, "5F57": { "name": "dateOfBirth", "data": "920912", "hash": "xxx" }, "5F35": { "name": "gender", "data": "M", "hash": "xxx" }, "5F2C": { "name": "nationality", "data": "D", "hash": "xxxx" }, "59": { "name": "documentExpiryDate", "data": "241217", "hash": "xxx" }
}`
Please correct me if I am wrong, for each filed we have different hash key?
Ahh you won't get hashes for the individual fields unless you calculate those yourself.
The hashes stored in the Document Security Object (SOD) are for the each datagroup as a whole so you compare the calculated hash of the DataGroup data against the one stored in the SOD.
Also, you obviously need to have read the SOD to get the hashes out.
From this function right?
`private func parseSODSignatureContent( _ content : String ) throws -> (String, [DataGroupId : String]){ var currentDG = "" var sodHashAlgo = "" var sodHashes : [DataGroupId : String] = [:]
let lines = content.components(separatedBy: "\n")
let dgList : [DataGroupId] = [.COM,.DG1,.DG2,.DG3,.DG4,.DG5,.DG6,.DG7,.DG8,.DG9,.DG10,.DG11,.DG12,.DG13,.DG14,.DG15,.DG16,.SOD]
}`
Yup - well thats were I extract all the hashes.
However thats only done IF you have a valid master list added and passive authentication is done (which I may change at some point to always do that if we a SOD read).
Anyway, if we did do passive authentication, then both the SOD hashes and the calculated DG hashes plus whether they match can be retrieved from the dataGroupHashes variable on the NFCPassportModel.
Well. As I said earlier I am not using any certificates and Master list. Therefore without those how can we get the hash keys. I am lil confuse here. I am just read the specific data groups and wants the hash key somehow.
At the moment NFCPassportModel not reading the SOD that's why not getting the hash keys right.
As per the documentation: PassiveAuthentication Passive Authentication is now part of the main library and can be used to ensure that an E-Passport is valid and hasn't been tampered with.
So, I don't have Master list but after passive authentication the hash keys should be present.
Yup but currently I only extract the hashes from the SOD IF you have a master list (even though I don't think the master list isn't needed for the hash check)
This possibly isn't desirable and I'll look at changing that to always extract the hashes and checking them if possible.
I'll try to take a look tomorrow and see if that works.
Thanks @AndyQ .Yes please check it how can we achieve the hash keys without master list. So we can get the hash key when we read only specific data groups.
I will be so thankful to you if you have a look into it.
OK, I've updated to 1.0.6 - the SOD Hashes are now always extracted and checked (if the SOD was read) even if the master list isn't provided.
Thanks @AndyQ . I will going to check it out. One more quick question, I want to remove the OpenSSL as well. So, Will it affect anything to get the data? because I think OpenSSL will help to get the certificates file right. As I said earlier I am not using any kind of certificates and try to get the specific data groups only then doesn't make sense to use the OpenSSL. Right?
Well, you'd need to write your own ASN1 parser as I use the one in OpenSSL to extract the hashes from the SOD.
So, You mean need to add one more file for example replacing the OpenSSLUtils file which having my own ASN1 parser. Do you have an idea how can I write the ASN1 parser? I mean any clue or more description will be helpful. Thanks a lot...!!
Sadly no - I used the one in OpenSSL so I didn't have to ! Its not a trivial thing to do and you'll need to really understand the certificate format too to make sense of the data.
There are a couple of ASN1 parsers for iOS on GitHub but I haven't looked at them in any detail.
Thanks @AndyQ , I will check it out and if I have some problem then I will let you know.
Hi @AndyQ
I need one more help. From NFCPassportModel class I need to access:
public func getDataGroup( _ id : DataGroupId ) -> DataGroup? { return dataGroupsRead[id] }
`public func getHashesForDatagroups( hashAlgorythm: String ) -> [DataGroupId:[UInt8]] { var ret = [DataGroupId:[UInt8]]()
for (key, value) in dataGroupsRead {
if hashAlgorythm == "SHA256" {
ret[key] = calcSHA256Hash(value.body)
} else if hashAlgorythm == "SHA1" {
ret[key] = calcSHA1Hash(value.body)
}
}
return ret
}`
I need these Func data with passport image and want to save into one dict / array. So I can produce the single Json with all data. Can you please let me know how can I do that?
@AndyQ
Somehow I need to create a like below Josn pattern:
{ "DG1": { "sodHash": "xxxxxxx", "53" : { "personalNumber": "<<<<<<<<<<<<<<" }, "59" : { "documentExpiryDate": "270528" }, "5F03" : { "documentSubType": "P<" }, "5A" : { "documentNumber": "<<<<<<<<<<<<<<" }, "5F06" : { "xxx": "3" }, "5F02" : { "personalNumber": "<" }, "5F35" : { "gender": "F" }, "5B" : { "lastName": "<<<<<<<<<<<<<<<<<<<<<<<<" }, "5F05" : { "personalNumber": "5" }, "5F28" : { "issuingAuthority": "D<<" }, "5F57" : { "dateOfBirth": "641012" }, "5F2C" : { "nationality": "D<<" }, "5F04" : { "personalNumber": "3" }, "5F07" : { "personalNumber": "4" }, "5F1F" : { "passportMRZ": "P<D<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<4" } } }
from Passport Data elements I am getting something like: { "53": "<<<<<<<<<<<<<<", "59": "270528", "5F1F": "P<D<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<4", "5F06": "3", "5A": "C01X12122", "5F02": "<", "5F35": "F", "5B": "<<<<<<<<<<<<<<<<<<<<<<<<", "5F05": "5", "5F28": "D<<", "5F2C": "D<<", "5F04": "3", "5F57": "641012", "5F07": "4", "5F03": "P<" }
So, I need to merge the sodHashKey & description of the Key like 5F, 5F15 etc etc. Please give me an Idea so I can produce the Json. Thanks in advance.
You could also do it by using the existing methods on the NFCPassportModel class - BUT you'd have to have to hardcode the associated tag number e.g. you'd need to manually set "5A" to be the document number which isn't great - but the tag numbers and what they map to are shown in the NFCPassportModel
Ideally though you'd want direct access to the underlying DataGroups.which currently isn't exposed through the passport model, however it should be.
I'll make a version available shortly which exposes the dataGroupsRead as a read only public property on the model so you can get access to the underlying datagroup values. (You already have access to the hashes.
Hi @AndyQ Thanks for your quick reply. Yes that's what I want. So, at the moment I have Hashes data into one dict which types is Struct and another dict is String type. For example:- var passportDataElementDictionary : [String:String] = [:] var dataGroupHashDictionary : [DataGroupId: DataGroupHash] = [:] // DataGroupId is enum and DataGroupHash is struct type.
So, now I need to merge these two dictionaries so I can parse into the single json. But unfortunately I am not able to do because the passport manager classes doesn't allow me also the dictionaries is different data types.
Can you please give me an idea for this or would be great if you can update the library. Thanks in advance!
I've just pushed out 1.0.7 which allows access to the underlying datagroups through the dataGroupsRead property.
I've also made the getName() property on DataGroupId public too so you can get the String name of a DataGroupId item.
let me check.
Hi @AndyQ , Thanks for the update. Still I am on the same point. I am already make public and get access to those properties / functions.
**In NFCPassportModel class - line number 73(public private(set) var dataGroupHashes = [DataGroupId: DataGroupHash]()) & line number 104 `public var passportDataElements : [String:String]? { guard let dg1 = dataGroupsRead[.DG1] as? DataGroup1 else { return nil }
return dg1.elements
}
So, I need to merge these two dictionaries**`
How can I merge these two dictionaries and save into one json.
If you really need the above JSON format then you would probably need to do something like:
guard let dg1 = passportModel.dataGroupsRead[.DG1] as? DataGroup1,
let sodHash = passportModel.dataGroupHashes[.SOD] else { return nil }
var dg1Val : [String:Any] = ["sodHash" : sodHash]
// These map from passport key to key description and should contain all the keys you want in the final doc
let passportDesc = ["53" : "personalNumber", "59" : "documentExpiryDate", .......]
for (key,val) in passportDesc {
print( "key - \(key), val - \(val)")
if let passportVal = dg1.elements[key] {
dg1Val[key] = [val:passportVal]
}
}
var jsonDoc = ["DG1": dg1Val]
guard let dg1 = passportModel.dataGroupsRead[.DG1] as? DataGroup1, let sodHash = passportModel.dataGroupHashes[.SOD] else { return nil }
here return nil gives the error - unexpected non-void return value in void function
because I called in main async thread and there is no completion handler, I think so...
I am not getting sodHashes also from here: let sodHash = passportModel.dataGroupHashes[.SOD] It should be comes but I don't know why it comes nil.
Ahhh - just realised! the SOD itself doesn't have a hash! Only the Datagroup hashes are stored in the SOD!
Which makes sense when you think about it as how could you store the hash of the SOD inside itself?
Yeah make sense I am not check that anyway it's working now. If I cancel the session it's not handling the session error like Invalidate session or something similar. Can you please check it?
Can't replicate that - I'm getting the didInvalidateWithError called when I cancel the session.
I'm closing this bug now - if you are still not getting the Invalidate - could you please raise a new bug with some more details?
Hi @AndyQ , Can you please let me know if I need to give some security checks with backend then which data(Something like Json data) need to validate with the DB? I mean like somehow we can validate DG(all Data Groups e.g. DG1, DG2......DG15) or after tag detecting we can store all chip data somewhere and validate it from the database.