{"id":7985,"date":"2023-09-18T18:28:31","date_gmt":"2023-09-18T09:28:31","guid":{"rendered":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=7985"},"modified":"2023-09-19T11:59:22","modified_gmt":"2023-09-19T02:59:22","slug":"nfc-%ec%b9%b4%eb%93%9c-%ec%9d%bd%ea%b8%b0","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=7985","title":{"rendered":"NFC \uce74\ub4dc \uc77d\uae30"},"content":{"rendered":"<h1>NFC \uce74\ub4dc \uc77d\uae30<\/h1>\n<h2>\uaddc\uaca9<\/h2>\n<p>ISO-7816-4<\/p>\n<p><a href=\"https:\/\/cardwerk.com\/iso-7816-part-4\">\ucc38\uc870<\/a><\/p>\n<h2>Answer to reset(ATR)<\/h2>\n<p>\uce74\ub4dc \uae30\ubcf8\uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub294 Response \ub370\uc774\ud0c0.<br \/>\n\uce74\ub4dc \uc885\ub958 \/ \uc81c\uc870\uc0ac \ub4f1\uc758 \uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub2e4.<\/p>\n<p><code>ATR: 3B 8F 80 01 80 4F 0C A0 00 00 03 06 03 00 03 00 00 00 00 68<\/code><br \/>\n<code>ATR: 3B 8F 80 01 80 4F 0C \/ A0 00 00 03 06 \/ 03 \/ 00 03 \/ 00 00 00 00 68<\/code><\/p>\n<p>Card Type : 3B 8F 80 01 80 4F 0C<br \/>\nRID(Registered Application Provider Identifier)  : A0 00 00 03 06<br \/>\n<a href=\"https:\/\/pcsc-tools.apdu.fr\/smartcard_list.txt\">\ucc38\uc870<\/a><\/p>\n<p>Standard(SS) = 03 (ISO 14443A , Part3)<br \/>\nCard Name = {00 03} (MIFARE Ultralight)<\/p>\n<p>Card Name (C0 .. C1)<br \/>\n00 01: MIFARE Classic 1K 00 38: MIFARE Plus SL2 2K<br \/>\n00 02: MIFARE Classic 4K 00 39: MIFARE Plus SL2 4K<br \/>\n00 03: MIFARE Ultralight 00 30: Topaz and Jewel<br \/>\n00 26: MIFARE Mini 00 3B: FeliCa<br \/>\n00 3A: MIFARE Ultralight C FF 28: JCOP 30<br \/>\n00 36: MIFARE Plus SL1 2K FF [SAK]: undefined tags<br \/>\n00 37: MIFARE Plus SL1 4K<\/p>\n<h2>\ub77c\uc774\ube0c\ub7ec\ub9ac<\/h2>\n<p><a href=\"https:\/\/github.com\/Rylern\/ACR122U-tutorial\">\ucc38\uc870<\/a><\/p>\n<h2>\uc0d8\ud50c\ucf54\ub4dc<\/h2>\n<p><code>MIFARE Ultralight<\/code> \uc758 \uacbd\uc6b0 \uc544\ub798 \uba85\ub839\uc774 \uce74\ub4dc UID \ub97c \uc77d\ub294 \uba85\ub839\uc774\ub2e4.<br \/>\n(\uce74\ub4dc \ub9ac\ub354\uae30 \uba54\ub274\uc5bc \ucc38\uc870)<\/p>\n<p><code>uint8_t readCommand[] = { 0xFF, 0xCA, 0x00, 0x00, 0x00 };<\/code><\/p>\n<pre><code class=\"language-c\">#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;string.h&gt;\n#include &lt;stdint.h&gt;\n#include &lt;winscard.h&gt;\n\nSCARDCONTEXT applicationContext;\nLPSTR reader = NULL;\nSCARDHANDLE connectionHandler;\nDWORD activeProtocol;\n\nvoid establishContext() {\n    LONG status = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &amp;applicationContext);\n    if (status == SCARD_S_SUCCESS) {\n        printf(&quot;Context established\\n&quot;);\n    } else {\n        printf(&quot;Establish context error: %s\\n&quot;, pcsc_stringify_error(status));\n        exit(1);\n    }\n}\n\nvoid releaseContext() {\n    LONG status = SCardReleaseContext(applicationContext);\n    if (status == SCARD_S_SUCCESS) {\n        printf(&quot;Context released\\n&quot;);\n    } else {\n        printf(&quot;Release context error: %s\\n&quot;, pcsc_stringify_error(status));\n        exit(1);\n    }\n}\n\nvoid listReaders() {\n    DWORD readers = SCARD_AUTOALLOCATE;\n    LONG status = SCardListReaders(applicationContext, NULL, (LPSTR)&amp;reader, &amp;readers);\n\n    if (status == SCARD_S_SUCCESS) {\n        char *p = reader;\n        while (*p) {\n            printf(&quot;Reader found: %s\\n&quot;, p);\n            p += strlen(p) +1;\n        }\n    } else {\n        printf(&quot;List reader error: %s\\n&quot;, pcsc_stringify_error(status));\n        exit(1);\n    }\n}\n\nvoid freeListReader() {\n    LONG status = SCardFreeMemory(applicationContext, reader);\n    if (status == SCARD_S_SUCCESS) {\n        printf(&quot;Reader list free\\n&quot;);\n    } else {\n        printf(&quot;Free reader list error: %s\\n&quot;, pcsc_stringify_error(status));\n        exit(1);\n    }\n}\n\nvoid connectToCard() {\n    activeProtocol = -1;\n\n    LONG status = SCardConnect(applicationContext, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &amp;connectionHandler, &amp;activeProtocol);\n    if (status == SCARD_S_SUCCESS) {\n        printf(&quot;Connected to card\\n&quot;);\n    } else {\n        printf(&quot;Card connection error: %s\\n&quot;, pcsc_stringify_error(status));\n        exit(1);\n    }\n}\n\nvoid disconnectFromCard() {\n    LONG status = SCardDisconnect(connectionHandler, SCARD_LEAVE_CARD);\n    if (status == SCARD_S_SUCCESS) {\n        printf(&quot;Disconnected from card\\n&quot;);\n    } else {\n        printf(&quot;Card deconnection error: %s\\n&quot;, pcsc_stringify_error(status));\n        exit(1);\n    }\n}\n\nvoid getCardInformation() {\n    BYTE ATR[MAX_ATR_SIZE] = &quot;&quot;;\n    DWORD ATRLength = sizeof(ATR);\n    char readerName[MAX_READERNAME] = &quot;&quot;;\n    DWORD readerLength = sizeof(readerName);\n    DWORD readerState;\n    DWORD readerProtocol;\n\n    LONG status = SCardStatus(connectionHandler, readerName, &amp;readerLength, &amp;readerState, &amp;readerProtocol, ATR, &amp;ATRLength);\n    if (status == SCARD_S_SUCCESS) {\n        printf(&quot;\\n&quot;);\n        printf(&quot;Name of the reader: %s\\n&quot;, readerName);\n        printf(&quot;ATR: &quot;);\n        for (int i=0; i&lt;ATRLength; i++) {\n            printf(&quot;%02X &quot;, ATR[i]);\n        }\n        printf(&quot;\\n\\n&quot;);\n    } else {\n        printf(&quot;Get card information error: %s\\n&quot;, pcsc_stringify_error(status));\n        exit(1);\n    }\n}\n\nvoid sendCommand(uint8_t command[], unsigned short commandLength) {\n    const SCARD_IO_REQUEST *pioSendPci;\n    SCARD_IO_REQUEST pioRecvPci;\n    uint8_t response[300];\n    unsigned long responseLength = sizeof(response);\n\n    switch(activeProtocol) {\n        case SCARD_PROTOCOL_T0:\n            pioSendPci = SCARD_PCI_T0;\n            break;\n        case SCARD_PROTOCOL_T1:\n            pioSendPci = SCARD_PCI_T1;\n            break;\n        default:\n            printf(&quot;Protocol not found\\n&quot;);\n            exit(1);\n    }\n\n    LONG status = SCardTransmit(connectionHandler, pioSendPci, command, commandLength, &amp;pioRecvPci, response, &amp;responseLength);\n    if (status == SCARD_S_SUCCESS) {\n        printf(&quot;Command sent: \\n&quot;);\n        for (int i=0; i&lt;commandLength; i++) {\n            printf(&quot;%02X &quot;, command[i]);\n        }\n        printf(&quot;\\nResponse: \\n&quot;);\n        for (int i=0; i&lt;responseLength; i++) {\n            printf(&quot;%02X &quot;, response[i]);\n        }\n        printf(&quot;\\n\\n&quot;);\n    } else {\n        printf(&quot;Send command error: %s\\n&quot;, pcsc_stringify_error(status));\n        exit(1);\n    }\n}\n\nvoid mifareUltralightGetSerialNumber() {\n    \/\/ Read 4 blocks (16 bytes) starting from pageNumber\n    uint8_t readCommand[] = { 0xFF, 0xCA, 0x00, 0x00, 0x00 };\n    unsigned short readCommandLength = sizeof(readCommand);\n    sendCommand(readCommand, readCommandLength);\n}\n\nvoid mifareUltralight() {\n    printf(&quot;### MIFARE Ultralight ###\\n&quot;);\n    uint8_t pageNumber = 0x04;\n\n    \/\/ Read 4 blocks (16 bytes) starting from pageNumber\n    uint8_t readCommand[] = { 0xFF, 0xB0, 0x00, pageNumber, 0x10 };\n    unsigned short readCommandLength = sizeof(readCommand);\n    sendCommand(readCommand, readCommandLength);\n\n    \/\/ \/\/ Write 1 block (4 bytes) to pageNumber\n    \/\/ uint8_t data[] = { 0x00, 0x01, 0x02, 0x03 };\n    \/\/ uint8_t writeCommand[9] = { 0xFF, 0xD6, 0x00, pageNumber, 0x04 };\n    \/\/ unsigned short writeCommandLength = sizeof(writeCommand);\n    \/\/ for (int i=0; i&lt;4; i++) {\n    \/\/  writeCommand[i+5] = data[i];\n    \/\/ }\n    \/\/ sendCommand(writeCommand, writeCommandLength);\n}\n\nvoid mifareClassic() {\n    printf(&quot;### MIFARE Classic ###\\n&quot;);\n    uint8_t blockNumber = 0x04;\n\n    \/\/ Load Authentication Keys\n    uint8_t key[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };\n    uint8_t authenticationKeysCommand[11] = { 0xFF, 0x82, 0x00, 0x00, 0x06 };\n    unsigned short authenticationKeysCommandLength = sizeof(authenticationKeysCommand);\n    for (int i=0; i&lt;6; i++) {\n        authenticationKeysCommand[i+5] = key[i];\n    }\n    sendCommand(authenticationKeysCommand, authenticationKeysCommandLength);\n\n    \/\/ Authenticate\n    uint8_t authenticateCommand[] = { 0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, blockNumber, 0x60, 0x00 };\n    unsigned short authenticateCommandLength = sizeof(authenticateCommand);\n    sendCommand(authenticateCommand, authenticateCommandLength);\n\n    \/\/ Read 1 block (16 bytes) at blockNumber\n    uint8_t readCommand[] = { 0xFF, 0xB0, 0x00, blockNumber, 0x10 };\n    unsigned short readCommandLength = sizeof(readCommand);\n    sendCommand(readCommand, readCommandLength);\n\n    \/\/ Write 1 block (16 bytes) at blockNumber\n    uint8_t data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };\n    uint8_t writeCommand[21] = { 0xFF, 0xD6, 0x00, blockNumber, 0x10 };\n    unsigned short writeCommandLength = sizeof(writeCommand);\n    for (int i=0; i&lt;16; i++) {\n        writeCommand[i+5] = data[i];\n    }\n    sendCommand(writeCommand, writeCommandLength);\n}\n\nint main() {\n    establishContext();\n    listReaders();\n    connectToCard();\n\n    getCardInformation();\n\n    \/\/ printf(&quot;Firmware command:\\n&quot;);\n    \/\/ uint8_t firmwareCommand[] = { 0xFF, 0x00, 0x48, 0x00, 0x00 };\n    \/\/ unsigned short firmwareCommandLength = sizeof(firmwareCommand);\n    \/\/ sendCommand(firmwareCommand, firmwareCommandLength);\n\n    mifareUltralightGetSerialNumber();\n    \/\/ mifareUltralight();\n    \/\/ \/\/mifareClassic();\n\n    disconnectFromCard();\n    freeListReader();\n    releaseContext();\n    return 0;\n}\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>NFC \uce74\ub4dc \uc77d\uae30 \uaddc\uaca9 ISO-7816-4 \ucc38\uc870 Answer to reset(ATR) \uce74\ub4dc \uae30\ubcf8\uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub294 Response \ub370\uc774\ud0c0. \uce74\ub4dc \uc885\ub958 \/ \uc81c\uc870\uc0ac \ub4f1\uc758 \uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub2e4. ATR: 3B 8F 80 01 80 4F 0C A0 00 00 03 06 03 00 03 00 00 00 00 68 ATR: 3B 8F 80 01 80 4F 0C \/ A0 00 00 03\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=7985\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-7985","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/7985","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7985"}],"version-history":[{"count":4,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/7985\/revisions"}],"predecessor-version":[{"id":7989,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/7985\/revisions\/7989"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7985"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7985"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7985"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}