Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading UIDs of NFC Cards in iOS 13

I would like to retrive the UID of MiFare cards. I'm using an iPhone X, Xcode 11 and iOS 13.

I'm aware this wasn't possible (specifically reading the UID) until iOS 13 according to this website: https://gototags.com/blog/apple-expands-nfc-on-iphone-in-ios-13/ and this guy: https://www.reddit.com/r/apple/comments/c0gzf0/clearing_up_misunderstandings_and/

The phones NFC reader is correctly detecting the card however the unique identifier is always returned as empty or nil. I can read the payload however and irrelvant to iOS but I can do this in Android (confirms the card isn't faulty or just odd)

Apple Sample Project: https://developer.apple.com/documentation/corenfc/building_an_nfc_tag-reader_app

    func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
            if case let NFCTag.miFare(tag) = tags.first! {
                session.connect(to: tags.first!) { (error: Error?) in
                    let apdu = NFCISO7816APDU(instructionClass: 0, instructionCode: 0xB0, p1Parameter: 0, p2Parameter: 0, data: Data(), expectedResponseLength: 16)
                    tag.queryNDEFStatus(completionHandler: {(status: NFCNDEFStatus, e: Int, error: Error?) in
                        debugPrint("\(status) \(e) \(error)")
                    })
                    tag.sendMiFareISO7816Command(apdu) { (data, sw1, sw2, error) in
                        debugPrint(data)
                        debugPrint(error)
                        debugPrint(tag.identifier)
                        debugPrint(String(data: tag.identifier, encoding: .utf8))
                    }
                }
            }
        }

I'm aware these sorts of hacks: CoreNFC not reading UID in iOS

But they are closed and only apply to iOS 11 for a short time in the past.

like image 941
Sean Dev Avatar asked Sep 17 '19 16:09

Sean Dev


People also ask

Can iPhone 13 read NFC tags?

Yes. The iPhone 13, 13 Pro, 13 Pro Max and 13 mini are the fourth generation of iPhones to support native NFC tag reading. The earlier generations, the XS/XR, 11 and 12 were the first iPhones to be able to read NFC tags and the iPhone 13 range continues this functionality.

Can iPhone read NFC credit card?

Tap to Pay on iPhone, available in iOS 15.4, allows U.S. merchants to accept Apple Pay and other contactless payments by using iPhone and a partner-enabled iOS app. With this service, users with supported iPhone devices can securely accept contactless payments and Apple Pay NFC-enabled passes.


1 Answers

Ok I have an answer.

tag.identifier isn't empty -- per se -- if you examine from Xcodes debugger it appears empty (0x00 is the value!). It's type is Data and printing it will reveal the length of the Data but not how it's encoded. In this case it's a [UInt8] but stored as a bag of bits, I don't understand why Apple have done it this way -- it's clunky -- I'm sure they have good reasons. I would have stored it as a type String -- after all the whole point of a high level language like Swift is to abstract us away from such hadware implementation details.

The following code will retrive the UID from a MiFare card:

if case let NFCTag.miFare(tag) = tags.first! {
    session.connect(to: tags.first!) { (error: Error?) in
        let apdu = NFCISO7816APDU(instructionClass: 0, instructionCode: 0xB0, p1Parameter: 0, p2Parameter: 0, data: Data(), expectedResponseLength: 16)
        tag.sendMiFareISO7816Command(apdu) { (apduData, sw1, sw2, error) in
            let tagUIDData = tag.identifier
            var byteData: [UInt8] = []
            tagUIDData.withUnsafeBytes { byteData.append(contentsOf: $0) }
            var uidString = ""
            for byte in byteData {
                let decimalNumber = String(byte, radix: 16)
                if (Int(decimalNumber) ?? 0) < 10 { // add leading zero
                    uidString.append("0\(decimalNumber)")
                } else {
                    uidString.append(decimalNumber)
                }
            }
            debugPrint("\(byteData) converted to Tag UID: \(uidString)")
        }
    }
}
like image 98
Sean Dev Avatar answered Sep 28 '22 08:09

Sean Dev