gematik / ref-OpenHealthCardKit

Controlling/Use-case framework for accessing smart cards of the telematic infrastructure. API Documentation: https://gematik.github.io/ref-OpenHealthCardKit
Apache License 2.0
15 stars 6 forks source link

How to extract personal information of egk? #9

Closed caijunjieNick closed 10 months ago

caijunjieNick commented 11 months ago

Hello, may i ask, wheter i can get the personal information such as insuranceId, name from the eGK with nfc by using the library?

sigabrtz commented 10 months ago

You (almost) certainly can to some extend. (We are not doing that exactly so some implementation details could be missing).

The eGK's file system content is described in a document "Spezifikation der eGK Objektsystem" https://www.vesta-gematik.de/standards/detail/standards/spezifikation-der-egk-objektsystem-1/

The files MF / DF.HCA / EF.VD and MF / DF.HCA / EF.GVD might be of interest for you. Basic steps are 1) Establish a secure channel 2) SELECT yourself through the file tree until you reach the file 3) use some Command like READBINARY

To read MF / DF.HCA / EF.GVD you also have to transmit the card's PIN beforehand since it's protected.

Each of these steps is either performed by the NFCDemo target or there are examples for them in the unit tests and integration tests of the HealthCardControl layer.

caijunjieNick commented 8 months ago

func test() -> AnyPublisher<Data, Swift.Error> { flatMap { secureCard in //EgkFileSystem.DF.MF.aid, fid: EgkFileSystem.EF.hcaVD.fid secureCard.selectDedicated( file: DedicatedFile(aid: EgkFileSystem.DF.HCA.aid, fid: EgkFileSystem.EF.hcaVD.fid), fcp: true ) .tryMap { (status, fcp) in guard let fcp = fcp, let readSize = fcp.readSize else { throw ReadError.fcpMissingReadSize(state: status) } return readSize } .flatMap { (readSize: UInt) in secureCard.readSelectedFile(expected: Int(readSize)) .map { data1 in data1 } } .eraseToAnyPublisher() }.eraseToAnyPublisher()`` I used this code to select file that i want. But always get Error "The operation couldn't be completed. (HealthCardControl.SelectError error)"

caijunjieNick commented 8 months ago

should i use HealthCardCommand.Select.selectFile or .selectEf? @sigabrtz

sigabrtz commented 8 months ago

Possibly the value for EgkFileSystem.DF.HCA.aid is still the buggy one. If you use the newest master commit that includes this recent change, we have at least one (if not the) problem solved.

caijunjieNick commented 8 months ago

Possibly the value for EgkFileSystem.DF.HCA.aid is still the buggy one. If you use the newest master commit that includes this recent change, we have at least one (if not the) problem solved.

Thanks for reply, after using the newest master commit, it finally works, but i am stuck in READBINARY, i have used secureCard.readSelectedFile to get the Data, but i still cannot figure it out, how to transform it into the personal information such as insuranceId

sigabrtz commented 8 months ago

it finally works

That's a big win!

how to transform it into the personal information such as insuranceId

The files of interest should be EF.GVD, EF.VD and EF.PD .. Those are actually .xml files (maybe you have to try out different encodings). In "Schnittstellen­definitionen im XSD- und WSDL-Format für den PTV3-Konnektor" from here you can check the files' schema definitions (look for file UC_PersoenlicheVersichertendatenXML.xsd).

caijunjieNick commented 8 months ago

it finally works

That's a big win!

how to transform it into the personal information such as insuranceId

The files of interest should be EF.GVD, EF.VD and EF.PD .. Those are actually .xml files (maybe you have to try out different encodings). In "Schnittstellen­definitionen im XSD- und WSDL-Format für den PTV3-Konnektor" from here you can check the files' schema definitions (look for file UC_PersoenlicheVersichertendatenXML.xsd).

Thanks, i really appreciate it:)

caijunjieNick commented 8 months ago

@sigabrtz Hello, sorry to bother u again. I just search out that the content is a gzipped ISO5589-15 encoded XML. so i used secureCard.readSelectedFile(expected: Int(readSize)) .map { data in if let xmlString = String(data: data, encoding:.isoLatin1) { Swift.print("Read XML OutputData of MF/DF.HCA/EF.hcaPD: \(xmlString)") } else { Swift.print("cannot be transformed ") } return data } } But i cannot really understand the string âôÛl<½E??hXÓÅR4)ýøð3æ+²éû¼&¸S°‰µmØ0_H|wnØ«Ür<’7EÑíu»ƒÁ!¿{¸µç$žÓí:¤È®ÖVÃ~ÁMÂŒ œ²$ç>ܒë̽ÍN­6Úg¤Ýc6o¶,óJÄ+U5ÛÕYøãîïžZ‡;”ecÕªš$'­Ú®Â¹Ndä(ä/Kœ¥ b$w\♽û˜ éô¨#zÃOŸö0œ†$Ï ¹È·X!´%^rJ¯}ã"ӌâ((p $Gÿƒ^Z^õåuPnE&rù›Þ`¼PëèÖÖr=„wՎó×:¼½;ìgø1ò"»”2024-01-12 could you give me some ideas? thanks

caijunjieNick commented 8 months ago

@sigabrtz Hi, finally i got the data in the format of XML. Thanks so much!

caijunjieNick commented 8 months ago

Man bekommt die kompletten Daten. Also bei der KVK liefert ReadKVK alle auf der Karte vorhandenen Daten; bei der eGK liefert ReadPD die persönlichen Versichertendaten und ReadVD die allgemeinen Versicherungsdaten und die geschützten Versichertendaten.

Allerdings kann man das Result-Array nicht einfach so in einen String umwandeln:

Bei der KVK ist das Result eine Aneinanderreihung von 1 Byte Tag (z.B 8016 für "KrankenkassenName"), 1-3 Bytes Länge des Elements und Wert des Elements (DIN_66003-codiert).

Bei der eGK: PD enthält 2 Bytes Längenabgabe für den Inhalt, dann ein ZIP-Komprimiertes XML-Dokument (ISO-8859-15 codiert). VD enthält jeweils 2 Bytes Offset für Start & Ende der VD, sowie je 2 Bytes Offset für Start & Ende der GVD. (Die GVD lassen sich in den Musterkarten noch Auslesen, bei den "echten" eGKarten kommt man aber nicht ran.

priska96 commented 12 hours ago

@caijunjieNick Hey darf ich fragen, wie du den hexString von PD dekodieren konntest Ich komme da einfach nicht weiter.

caijunjieNick commented 1 hour ago
` flatMap { (readSize: UInt) in
              secureCard.readSelectedFile(expected: Int(readSize))
                  .map { data in
                              let lengthBytes = data.prefix(2)
                              let length = UInt16(lengthBytes.withUnsafeBytes { $0.load(as: UInt16.self) })
                              let compressedData = data.suffix(from: 2).prefix(Int(length))
                              guard let uncompressedData = try? compressedData.gunzipped() else {
                                  fatalError("Error decompressing gzip data")
                              }

                              if let xmlString = String(data: uncompressedData, encoding: .isoLatin1) {
                                  Swift.print(xmlString)
                              } else {
                                  fatalError("Error converting data to string")
                              }

                              return data
                          }` 

meinst du das oder? xmlString ist die dekodierten Daten von PD