NFC 기능을 제공하는 많은 Android 지원 기기는 이미 NFC 카드 에뮬레이션을 지원합니다. 대부분의 경우 카드는 보안 요소라고 하는 기기의 별도 칩에 의해 에뮬레이션됩니다. 또한 무선 이동통신사에서 제공하는 여러 SIM 카드에도 보안 요소가 포함되어 있습니다.
Android 4.4 이상에서는 보안 요소가 포함되지 않은 추가적인 카드 에뮬레이션 방법인 호스트 기반 카드 에뮬레이션을 제공합니다. 이를 통해 모든 Android 애플리케이션이 카드를 에뮬레이션하고 NFC 리더와 직접 통신할 수 있습니다. 이 주제에서는 Android에서 호스트 기반 카드 에뮬레이션 (HCE)이 작동하는 방식과 이 기법을 사용하여 NFC 카드를 에뮬레이션하는 앱을 개발하는 방법을 설명합니다.
보안 요소가 있는 카드 에뮬레이션
보안 요소를 사용하여 NFC 카드 에뮬레이션을 제공할 때 에뮬레이션할 카드는 Android 애플리케이션을 통해 기기의 보안 요소에 프로비저닝됩니다. 그런 다음 사용자가 NFC 단말기에 기기를 갖다 대면 기기의 NFC 컨트롤러가 리더의 모든 데이터를 직접 보안 요소로 라우팅합니다. 그림 1은 이 개념을 보여줍니다.
보안 요소 자체가 NFC 단말기와의 통신을 실행하고 Android 애플리케이션이 트랜잭션에 관여하지 않습니다. 거래가 완료된 후 Android 애플리케이션은 보안 요소에 트랜잭션 상태를 직접 쿼리하여 사용자에게 알릴 수 있습니다.
호스트 기반 카드 에뮬레이션
호스트 기반 카드 에뮬레이션을 사용하여 NFC 카드를 에뮬레이션하면 데이터가 보안 요소로 라우팅되는 대신 호스트 CPU로 직접 라우팅됩니다. 그림 2는 호스트 기반 카드 에뮬레이션의 작동 방식을 보여줍니다.
지원되는 NFC 카드 및 프로토콜
NFC 표준은 다양한 프로토콜을 지원하며 에뮬레이션할 수 있는 다양한 유형의 카드가 있습니다.
Android 4.4 이상에서는 오늘날 시장에서 일반적으로 사용되는 몇 가지 프로토콜을 지원합니다. 미접촉 결제 카드와 같은 기존의 많은 미접촉 카드는 이미 이러한 프로토콜을 기반으로 합니다. 또한 오늘날 리더로 직접 작동하는 Android NFC 기기 (IsoDep
클래스 참고)를 포함하여 시장의 많은 NFC 리더도 이러한 프로토콜을 지원합니다. 이를 통해 Android 지원 기기만 사용하여 HCE를 중심으로 한 엔드 투 엔드 NFC 솔루션을 구축하고 배포할 수 있습니다.
특히 Android 4.4 이상은 NFC 포럼 ISO-DEP 사양 (ISO/IEC 14443-4 기반)을 기반으로 하는 카드 에뮬레이션과 ISO/IEC 7816-4 사양에 정의된 대로 애플리케이션 프로토콜 데이터 단위 (APDU)를 처리합니다. Android는 Nfc-A(ISO/IEC 14443-3 Type A) 기술을 기반으로 ISO-DEP를 에뮬레이션해야 합니다. Nfc-B (ISO/IEC 14443-4 Type B) 기술 지원은 선택사항입니다. 그림 3은 이러한 모든 사양의 레이어링을 보여줍니다.
HCE 서비스
Android의 HCE 아키텍처는 Android Service
구성요소 (HCE 서비스라고 함)를 기반으로 합니다. 서비스의 주요 이점 중 하나는 사용자 인터페이스 없이 백그라운드에서 실행할 수 있다는 것입니다. 따라서 충성도 또는 대중교통 카드와 같은 많은 HCE 애플리케이션에 적합하며 사용자가 서비스를 사용하기 위해 앱을 시작할 필요가 없습니다. 대신 NFC 리더에 기기를 탭하면 적절한 서비스가 시작되고(아직 실행되지 않았다면) 백그라운드에서 트랜잭션이 실행됩니다. 물론 적절한 경우 언제든지 서비스에서 추가 UI (예: 사용자 알림)를 시작할 수 있습니다.
서비스 선택
사용자가 기기를 NFC 리더에 탭하면 Android 시스템은 NFC 리더가 통신하려는 HCE 서비스를 알아야 합니다. ISO/IEC 7816-4 사양은 애플리케이션 ID (AID)를 중심으로 애플리케이션을 선택하는 방법을 정의합니다. AID는 최대 16바이트로 구성됩니다. 기존 NFC 리더 인프라에 맞춰 카드를 에뮬레이션한다면 이 리더가 찾고 있는 AID는 일반적으로 잘 알려져 있고 공개적으로 등록된 것입니다 (예: Visa 및 MasterCard와 같은 결제 네트워크의 AID).
자체 애플리케이션을 위해 새로운 리더 인프라를 배포하려면 자체 AID를 등록해야 합니다. AID 등록 절차는 ISO/IEC 7816-5 사양에 정의되어 있습니다. Android용 HCE 애플리케이션을 배포하는 경우 7816-5에 따라 AID를 등록하는 것이 좋습니다. 그러면 다른 애플리케이션과의 충돌을 피할 수 있기 때문입니다.
AID 그룹
HCE 서비스가 특정 애플리케이션을 구현하기 위해 여러 AID를 등록하고 모든 AID의 기본 핸들러로 설정해야 하는 경우도 있습니다. 그룹의 일부 AID가 다른 서비스로 이동하는 것은 지원되지 않습니다.
함께 유지되는 AID 목록을 AID 그룹이라고 합니다. AID 그룹의 모든 AID와 관련하여 Android는 다음 중 하나를 보장합니다.
- 그룹의 모든 AID가 이 HCE 서비스로 라우팅됩니다.
- 그룹의 AID가 이 HCE 서비스로 라우팅되지 않습니다 (예를 들어 사용자가 그룹 내 하나 이상의 AID를 요청한 다른 서비스도 원했기 때문에).
즉, 그룹의 일부 AID는 한 HCE 서비스로 라우팅되고 일부는 다른 HCE 서비스로 라우팅될 수 있는 중간 상태는 없습니다.
AID 그룹 및 카테고리
각 AID 그룹을 카테고리와 연결할 수 있습니다. 이렇게 하면 Android에서 HCE 서비스를 카테고리별로 함께 그룹화할 수 있으며 결과적으로 사용자가 AID 수준 대신 카테고리 수준에서 기본값을 설정할 수 있습니다. AID는 일반 사용자에게 아무 의미가 없으므로 사용자에게 표시되는 애플리케이션 요소에서는 AID를 언급하지 마세요.
Android 4.4 이상에서는 두 가지 카테고리를 지원합니다.
CATEGORY_PAYMENT
(업계 표준 결제 앱 포함)CATEGORY_OTHER
(다른 모든 HCE 앱용)
HCE 서비스 구현
호스트 기반 카드 에뮬레이션을 사용하여 NFC 카드를 에뮬레이션하려면 NFC 트랜잭션을 처리하는 Service
구성요소를 만들어야 합니다.
HCE 지원 확인
애플리케이션은 FEATURE_NFC_HOST_CARD_EMULATION
기능을 확인하여 기기가 HCE를 지원하는지 여부를 알 수 있습니다. 애플리케이션의 매니페스트에서 <uses-feature>
태그를 사용하여 앱이 HCE 기능을 사용한다는 것과 앱이 작동하는 데 HCE 기능이 필요한지 선언하세요.
서비스 구현
Android 4.4 이상에서는 HCE 서비스 구현을 위한 기반으로 사용할 수 있는 편의 Service
클래스인 HostApduService
클래스를 제공합니다.
첫 번째 단계는 다음 코드 샘플과 같이 HostApduService
를 확장하는 것입니다.
Kotlin
class MyHostApduService : HostApduService() { override fun processCommandApdu(commandApdu: ByteArray, extras: Bundle?): ByteArray { ... } override fun onDeactivated(reason: Int) { ... } }
자바
public class MyHostApduService extends HostApduService { @Override public byte[] processCommandApdu(byte[] apdu, Bundle extras) { ... } @Override public void onDeactivated(int reason) { ... } }
HostApduService
는 재정의하고 구현해야 하는 두 가지 추상 메서드를 선언합니다. 그중 하나인 processCommandApdu()
는 NFC 리더가 애플리케이션 프로토콜 데이터 단위 (APDU)를 서비스에 전송할 때마다 호출됩니다. APDU는 ISO/IEC 7816-4 사양에 정의되어 있습니다. APDU는 NFC 리더와 HCE 서비스 간에 교환되는 애플리케이션 수준의 패킷입니다. 이 애플리케이션 수준 프로토콜은 반이중입니다. 즉, NFC 리더는 명령 APDU를 전송하고 응답으로 응답 APDU를 수신할 때까지 기다립니다.
앞서 언급했듯이 Android는 AID를 사용하여 리더가 통신하려는 HCE 서비스를 결정합니다. 일반적으로 NFC 리더가 기기에 전송하는 첫 번째 APDU는 SELECT AID
APDU입니다. 이 APDU에는 리더가 통신하려는 AID가 포함되어 있습니다. Android는 APDU에서 AID를 추출하여 HCE 서비스로 확인한 후 확인된 서비스에 이 APDU를 전달합니다.
processCommandApdu()
의 응답 APDU 바이트를 반환하여 응답 APDU를 전송할 수 있습니다. 이 메서드는 애플리케이션의 기본 스레드에서 호출되며 차단해서는 안 됩니다. 응답 APDU를 즉시 계산하여 반환할 수 없다면 null을 반환합니다. 그런 다음 다른 스레드에서 필요한 작업을 실행하고 완료 시 HostApduService
클래스에 정의된 sendResponseApdu()
메서드를 사용하여 응답을 전송할 수 있습니다.
다음 중 하나가 발생할 때까지 Android는 새로운 APDU를 리더에서 서비스로 계속 전달합니다.
- NFC 리더는 또 다른
SELECT AID
APDU를 전송하며, OS는 이를 다른 서비스로 확인합니다. - NFC 리더와 기기 간의 NFC 링크가 끊어집니다.
두 가지 상황 모두에서 클래스의 onDeactivated()
구현이 두 가지 중 어느 것이 발생했는지 나타내는 인수와 함께 호출됩니다.
기존 리더 인프라에서 작업한다면 리더가 HCE 서비스에서 예상하는 기존 애플리케이션 수준 프로토콜을 구현해야 합니다.
직접 제어하는 새로운 리더 인프라도 배포한다면 고유한 프로토콜 및 APDU 시퀀스를 정의할 수 있습니다. 교환할 APDU의 양과 데이터의 크기를 제한하세요. 이렇게 하면 사용자가 기기를 NFC 리더 위에 짧은 시간 동안만 갖다 대면 됩니다. 합리적인 상한은 약 1KB의 데이터입니다. 이 크기의 데이터는 일반적으로 300ms 이내에 교환할 수 있습니다.
서비스 manifest 선언 및 AID 등록
평소와 같이 매니페스트에서 서비스를 선언해야 하지만 서비스 선언에도 일부 추가 부분을 추가해야 합니다.
플랫폼에 서비스가
HostApduService
인터페이스를 구현하는 HCE 서비스임을 알리려면 서비스 선언에SERVICE_INTERFACE
작업의 인텐트 필터를 추가합니다.이 서비스에서 요청한 AID 그룹을 플랫폼에 알리려면 서비스 선언에
SERVICE_META_DATA
<meta-data>
태그를 포함하여 HCE 서비스에 관한 추가 정보가 있는 XML 리소스를 가리킵니다.android:exported
속성을true
로 설정하고 서비스 선언에android.permission.BIND_NFC_SERVICE
권한이 필요합니다. 전자는 서비스가 외부 애플리케이션에 의해 결합될 수 있도록 합니다. 후자는android.permission.BIND_NFC_SERVICE
권한을 보유한 외부 애플리케이션만 서비스에 바인딩되도록 합니다.android.permission.BIND_NFC_SERVICE
는 시스템 권한이므로 이렇게 하면 Android OS만 서비스에 바인딩될 수 있습니다.
다음은 HostApduService
매니페스트 선언의 예입니다.
<service android:name=".MyHostApduService" android:exported="true" android:permission="android.permission.BIND_NFC_SERVICE"> <intent-filter> <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/> </intent-filter> <meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/apduservice"/> </service>
이 메타데이터 태그는 apduservice.xml
파일을 가리킵니다. 다음은 두 개의 독점 AID가 포함된 단일 AID 그룹 선언이 있는 파일의 예입니다.
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/servicedesc" android:requireDeviceUnlock="false"> <aid-group android:description="@string/aiddescription" android:category="other"> <aid-filter android:name="F0010203040506"/> <aid-filter android:name="F0394148148100"/> </aid-group> </host-apdu-service>
<host-apdu-service>
태그에는 앱 UI에 표시할 수 있는 서비스에 관한 사용자 친화적인 설명이 포함된 <android:description>
속성이 포함되어야 합니다. requireDeviceUnlock
속성을 사용하여 이 서비스를 호출하여 APDU를 처리하기 전에 기기가 잠금 해제되었다고 지정할 수 있습니다.
<host-apdu-service>
는 <aid-group>
태그를 하나 이상 포함해야 합니다. 각 <aid-group>
태그는 다음을 실행하는 데 필요합니다.
- UI에 표시하기에 적합한 사용자 친화적인 AID 그룹 설명이 있는
android:description
속성을 포함합니다. - AID 그룹이 속한 카테고리(예:
CATEGORY_PAYMENT
또는CATEGORY_OTHER
에 의해 정의된 문자열 상수)를 나타내도록android:category
속성을 설정합니다. <aid-filter>
태그를 하나 이상 포함하며 각 태그에는 단일 AID가 포함됩니다. AID는 16진수 형식으로 지정해야 하며 짝수의 문자를 포함해야 합니다.
애플리케이션은 HCE 서비스로 등록할 수 있도록 NFC
권한도 보유해야 합니다.
AID 충돌 해결
단일 기기에 여러 HostApduService
구성요소를 설치할 수 있으며 둘 이상의 서비스에서 동일한 AID를 등록할 수 있습니다. Android는 다음 단계에 따라 호출할 서비스를 결정합니다.
- 사용자가 선택한 기본 월렛 앱이 AID를 등록한 경우 이 앱이 호출됩니다.
- 기본 월렛 앱이 AID를 등록하지 않은 경우 AID를 등록한 서비스가 호출됩니다.
- 두 개 이상의 서비스가 AID를 등록한 경우 Android는 사용자에게 호출할 서비스를 묻습니다.
앱이 기본 월렛 앱인지 확인
앱은 RoleManager.ROLE_WALLET
를 RoleManager.isRoleHeld()
에 전달하여 기본 지갑 앱인지 확인할 수 있습니다.
앱이 기본 앱이 아닌 경우 RoleManager.ROLE_WALLET
를 RoleManager.createRequestRoleIntent()
에 전달하여 기본 지갑 역할을 요청할 수 있습니다.
월렛 애플리케이션
Android는 결제 카테고리가 있는 AID 그룹을 선언한 HCE 서비스를 월렛 애플리케이션으로 간주합니다. Android 15 이상에는 사용자가 설정 > 앱 > 기본 앱으로 이동하여 선택할 수 있는 기본 지갑 앱 역할이 포함되어 있습니다. 결제 단말기를 탭할 때 호출할 기본 월렛 애플리케이션을 정의합니다.
지갑 애플리케이션의 필수 애셋
시각적으로 더 매력적인 사용자 환경을 제공하려면 HCE 월렛 애플리케이션이 서비스 배너를 제공해야 합니다.
Android 13 이상
설정 UI의 기본 결제 선택 목록에 더 잘 맞도록 배너 요구사항을 정사각형 아이콘으로 조정합니다. 애플리케이션 런처 아이콘 디자인과 동일한 것이 좋습니다. 이렇게 조정하면 보다 일관되고 깔끔한 디자인을 만들 수 있습니다.
Android 12 및 이전 버전
서비스 배너의 크기를 260x96dp로 설정한 다음 드로어블 리소스를 가리키는 <host-apdu-service>
태그에 android:apduServiceBanner
속성을 추가하여 메타데이터 XML 파일에서 서비스 배너의 크기를 설정합니다. 다음은 예시입니다.
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/servicedesc" android:requireDeviceUnlock="false" android:apduServiceBanner="@drawable/my_banner"> <aid-group android:description="@string/aiddescription" android:category="payment"> <aid-filter android:name="F0010203040506"/> <aid-filter android:name="F0394148148100"/> </aid-group> </host-apdu-service>
관찰 모드
Android 15에서는 관찰 모드 기능을 도입합니다. 관찰 모드를 사용 설정하면 기기가 NFC 폴링 루프를 관찰하고 적절한 HostApduService
구성요소에 관해 알림을 전송하여 지정된 NFC 단말기와 상호작용할 준비를 할 수 있습니다. HostApduService
는 true
를 setObserveModeEnabled()
에 전달하여 기기를 관찰 모드로 전환할 수 있습니다.
이렇게 하면 NFC 스택에 NFC 트랜잭션을 허용하지 않고 대신 폴링 루프를 수동으로 관찰하도록 지시합니다.
폴링 루프 필터
다음 메서드 중 하나를 사용하여 HostApduService
의 폴링 루프 필터를 등록할 수 있습니다.
- 폴링 프레임과 정확히 일치해야 하는 필터의 경우
registerPollingLoopFilterForService()
- 폴링 프레임에 대해 정규 표현식과 일치하는 필터를 위한
registerPollingLoopPatternFilterForService()
폴링 루프 필터가 비표준 폴링 프레임과 일치하면 NFC 스택은 processPollingFrames()
메서드를 호출하여 이러한 폴링 프레임을 해당 HostApduService
로 라우팅합니다. 이를 통해 서비스는 사용자가 거래할 준비가 되어 있고 거래할 의사가 있는지 확인하는 데 필요한 모든 단계를 실행할 수 있습니다(예: 사용자 인증). NFC 리더가 폴링 루프에서 표준 프레임만 사용하는 경우 NFC 스택은 이러한 폴링 프레임을 기본 포그라운드 서비스(포그라운드에 있는 경우) 또는 기본 월렛 역할 홀더(그렇지 않으면)로 라우팅합니다.
폴링 프레임 알림에는 getVendorSpecificGain()
를 호출하여 가져올 수 있는 공급업체별 필드 강도 측정도 포함됩니다.
공급업체는 단일 바이트 내에 있는 한 자체 배율을 사용하여 측정값을 제공할 수 있습니다.
폴링 루프에 응답 및 관찰 모드에서 전환
서비스가 거래할 준비가 되면 false
를 setObserveModeEnabled()
에 전달하여 관찰 모드를 종료할 수 있습니다. 그러면 NFC 스택에서 거래를 진행할 수 있습니다.
HostApduService
구성요소는 매니페스트에서 shouldDefaultToObserveMode
를 true
로 설정하거나 CardEmulation.setShouldDefaultToObserveModeForService()
를 호출하여 선호되는 결제 서비스일 때마다 관찰 모드를 사용 설정해야 한다고 나타낼 수 있습니다.
HostApduService
및 OffHostApduService
구성요소는 수신된 폴링 루프 프레임과 일치하는 폴링 루프 필터가 매니페스트의 PollingLoopFilter
선언에서 autoTransact
를 true
로 설정하여 관찰 모드를 자동으로 사용 중지하고 트랜잭션이 진행되도록 허용해야 함을 나타낼 수도 있습니다.
화면 꺼짐 및 잠금 화면 동작
HCE 서비스의 동작은 기기에서 실행되는 Android 버전에 따라 다릅니다.
Android 12 이상
Android 12 (API 수준 31) 이상을 타겟팅하는 앱에서는 requireDeviceScreenOn
을 false
로 설정하여 기기 화면이 켜지지 않은 상태에서 NFC 결제를 사용 설정할 수 있습니다.
Android 10 이상
Android 10 (API 수준 29) 이상을 실행하는 기기는 보안 NFC를 지원합니다. 보안 NFC가 사용 설정되어 있으면 기기 화면이 꺼져 있을 때 모든 카드 에뮬레이터 (호스트 애플리케이션 및 오프 호스트 애플리케이션)를 사용할 수 없습니다. 보안 NFC가 사용 중지되어 있으면 기기 화면이 꺼져 있을 때 오프 호스트 애플리케이션을 사용할 수 있습니다. isSecureNfcSupported()
를 사용하여 보안 NFC 지원을 확인할 수 있습니다.
Android 10 이상을 실행하는 기기에서는 android:requireDeviceUnlock
를 true
로 설정하는 동일한 기능이 Android 9 이하를 실행하는 기기와 마찬가지로 적용되지만 보안 NFC가 사용 중지된 경우에만 적용됩니다. 즉, 보안 NFC가 사용 설정된 경우 android:requireDeviceUnlock
설정과 관계없이 HCE 서비스가 잠금 화면에서 작동할 수 없습니다.
Android 9 이하
Android 9 (API 수준 28) 이하를 실행하는 기기에서는 기기의 화면이 꺼질 때 NFC 컨트롤러와 애플리케이션 프로세서가 완전히 꺼집니다. 따라서 HCE 서비스는 화면이 꺼져 있을 때 작동하지 않습니다.
Android 9 이하에서도 HCE 서비스가 잠금 화면에서 작동할 수 있습니다.
그러나 이 동작은 HCE 서비스의 <host-apdu-service>
태그에서 android:requireDeviceUnlock
속성으로 제어합니다. 기본적으로 기기 잠금 해제는 필요하지 않으며 기기가 잠겨 있어도 서비스가 호출됩니다.
HCE 서비스의 android:requireDeviceUnlock
속성을 true
로 설정하면 다음과 같은 경우 Android에서 사용자에게 기기 잠금을 해제하라는 메시지를 표시합니다.
- 사용자가 NFC 리더를 탭합니다.
- NFC 리더가 서비스로 확인되는 AID를 선택합니다.
잠금 해제 후 Android는 트랜잭션을 완료하기 위해 다시 탭하라는 대화상자를 사용자에게 표시합니다. 사용자가 잠금을 해제하기 위해 기기를 NFC 리더로부터 떨어진 거리에서 움직였을 수 있기 때문에 이 메시지가 필요합니다.
보안 요소 카드와의 공존
이 섹션은 카드 에뮬레이션에 보안 요소를 사용하는 애플리케이션을 배포한 개발자에게 유용합니다. Android의 HCE 구현은 보안 요소 사용을 포함하여 카드 에뮬레이션을 구현하는 다른 방법과 동시에 작동하도록 설계되었습니다.
이 공존은 AID 라우팅이라는 원칙을 기반으로 합니다. NFC 컨트롤러는 라우팅 규칙의 (한정된) 목록으로 구성된 라우팅 테이블을 유지합니다. 각 라우팅 규칙에는 AID 및 대상이 포함됩니다. 대상은 Android 앱이 실행되고 있는 호스트 CPU 또는 연결된 보안 요소일 수 있습니다.
NFC 리더가 SELECT AID
가 있는 APDU를 전송하면 NFC 컨트롤러가 이를 파싱하여 AID가 라우팅 테이블의 AID와 일치하는지 확인합니다. 일치하면 다른 SELECT AID
APDU가 수신되거나 NFC 링크가 끊길 때까지 APDU 및 그 뒤에 오는 모든 APDU를 AID와 연결된 대상으로 전송합니다.
그림 4는 이 아키텍처를 보여줍니다.
또한 NFC 컨트롤러에는 일반적으로 APDU의 기본 경로도 포함됩니다. 라우팅 테이블에서 AID를 찾을 수 없는 경우 기본 경로가 사용됩니다. 이 설정은 기기마다 다를 수 있지만 Android 기기는 앱에서 등록 중인 AID가 호스트로 적절하게 라우팅되도록 해야 합니다.
HCE 서비스를 구현하거나 보안 요소를 사용하는 Android 애플리케이션은 라우팅 테이블 구성에 관해 신경 쓸 필요가 없습니다. 라우팅 테이블은 Android에서 자동으로 처리됩니다. Android는 어떤 AID를 HCE 서비스에서 처리할 수 있는지와 보안 요소에서 처리할 수 있는지만 알면 됩니다. 라우팅 테이블은 설치된 서비스 및 사용자가 기본으로 사용하도록 구성한 서비스에 따라 자동으로 구성됩니다.
다음 섹션에서는 카드 에뮬레이션에 보안 요소를 사용하는 애플리케이션의 AID를 선언하는 방법을 설명합니다.
보안 요소 AID 등록
카드 에뮬레이션에 보안 요소를 사용하는 애플리케이션은 매니페스트에 오프 호스트 서비스를 선언할 수 있습니다. 이러한 서비스 선언은 HCE 서비스 선언과 거의 동일합니다. 예외는 다음과 같습니다.
- 인텐트 필터에 사용되는 작업은
SERVICE_INTERFACE
로 설정해야 합니다. - 메타데이터 이름 속성을
SERVICE_META_DATA
로 설정해야 합니다. 메타데이터 XML 파일은
<offhost-apdu-service>
루트 태그를 사용해야 합니다.<service android:name=".MyOffHostApduService" android:exported="true" android:permission="android.permission.BIND_NFC_SERVICE"> <intent-filter> <action android:name="android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE"/> </intent-filter> <meta-data android:name="android.nfc.cardemulation.off_host_apdu_service" android:resource="@xml/apduservice"/> </service>
다음은 두 개의 AID를 등록하는 apduservice.xml
파일의 예입니다.
<offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/servicedesc"> <aid-group android:description="@string/subscription" android:category="other"> <aid-filter android:name="F0010203040506"/> <aid-filter android:name="F0394148148100"/> </aid-group> </offhost-apdu-service>
호스트 CPU가 트랜잭션에 관여하지 않으므로 기기가 잠겨 있을 때 보안 요소가 트랜잭션을 실행하는 것을 막을 수 없으므로 android:requireDeviceUnlock
속성은 오프 호스트 서비스에 적용되지 않습니다.
android:apduServiceBanner
속성은 결제 애플리케이션인 오프 호스트 서비스에 필요하며 기본 결제 애플리케이션으로 선택할 수 있습니다.
오프호스트 서비스 호출
Android는 '오프 호스트'로 선언된 서비스를 시작하거나 이 서비스에 결합하지 않습니다. 실제 트랜잭션은 Android 서비스가 아닌 보안 요소에 의해 실행되기 때문입니다. 서비스 선언은 단지 애플리케이션이 보안 요소에 있는 AID를 등록할 수 있게 합니다.
HCE 및 보안
HCE 아키텍처는 하나의 핵심 보안 요소를 제공합니다. 서비스는 BIND_NFC_SERVICE
시스템 권한으로 보호되므로 OS만 서비스에 결합하고 서비스와 통신할 수 있습니다.
이렇게 하면 수신하는 APDU가 실제로 OS에서 NFC 컨트롤러에서 수신한 APDU이며 다시 보낸 APDU가 OS로만 전달되고 결과적으로 APDU를 NFC 컨트롤러에 직접 전달하도록 합니다.
마지막으로 남은 문제는 앱에서 NFC 리더로 전송하는 데이터를 가져오는 부분입니다. 이 부분은 HCE 설계에서 의도적으로 분리되어 있습니다. HCE 설계에서는 데이터의 출처를 신경 쓰지 않으며 NFC 컨트롤러와 NFC 리더로까지 안전하게 전송됩니다.
HCE 서비스에서 전송하려는 데이터를 안전하게 저장하고 검색하기 위해서는 예를 들면 앱의 데이터를 다른 앱과 분리하는 Android 애플리케이션 샌드박스를 사용할 수 있습니다. Android 보안에 관한 자세한 내용은 보안 도움말을 참고하세요.
프로토콜 매개변수 및 세부정보
이 섹션은 NFC 프로토콜의 충돌 방지 및 활성화 단계 중에 HCE 기기에서 사용하는 프로토콜 매개변수를 이해하려는 개발자에게 유용합니다. 이를 통해 Android HCE 기기와 호환되는 리더 인프라를 구축할 수 있습니다.
Nfc-A(ISO/IEC 14443 Type A) 프로토콜 충돌 방지 및 활성화
Nfc-A 프로토콜 활성화 과정의 일환으로 여러 프레임이 교환됩니다.
교환의 첫 부분에서 HCE 기기는 UID를 제시합니다. HCE 기기에는 임의의 UID가 있다고 가정해야 합니다. 즉, 사용자가 탭할 때마다 리더에 제시되는 UID는 무작위로 생성된 UID입니다. 따라서 NFC 리더는 HCE 기기의 UID를 인증 또는 식별의 형태로 사용해서는 안 됩니다.
NFC 리더는 나중에 SEL_REQ
명령어를 전송하여 HCE 기기를 선택할 수 있습니다. HCE 기기의 SEL_RES
응답에는 최소한 6번째 비트(0x20)가 설정되며 이 설정은 ISO-DEP를 지원함을 나타냅니다. SEL_RES
의 다른 비트들도 설정될 수 있습니다. 예를 들어 NFC-DEP(p2p) 프로토콜 관련 지원을 나타내는 비트도 설정될 수 있습니다. 다른 비트가 설정될 수 있기 때문에 HCE 기기와 상호작용하려는 리더는 6번째 비트만 명확하게 확인해야 하며 전체 SEL_RES
를 0x20 값과 비교해서는 안 됩니다.
ISO-DEP 활성화
Nfc-A 프로토콜이 활성화되면 NFC 리더에서 ISO-DEP 프로토콜 활성화를 시작합니다. NFC 리더는 RATS (Request for Answer To Select) 명령을 전송합니다. NFC 컨트롤러는 RATS 응답인 ATS를 생성합니다. ATS는 HCE 서비스에서 구성할 수 없습니다. 하지만 HCE 구현은 ATS 응답을 위한 NFC 포럼 요구사항을 충족해야 하므로 NFC 리더는 모든 HCE 기기의 NFC 포럼 요구사항에 따라 설정되는 이러한 매개변수를 신뢰할 수 있습니다.
아래 섹션에서는 HCE 기기의 NFC 컨트롤러에서 제공하는 ATS 응답의 개별 바이트에 관해 자세히 설명합니다.
- TL: ATS 응답의 길이입니다. 길이가 20바이트보다 크면 안 됩니다.
- T0: 모든 HCE 기기에서 비트 5, 6, 7이 설정되어야 하며 이 설정은 TA(1), TB(1) 및 TC(1)이 ATS 응답에 포함되어 있음을 나타냅니다. 비트 1~4는 FSCI를 나타내며 최대 프레임 크기를 코딩합니다. HCE 기기에서 FSCI 값은 0h에서 8h 사이여야 합니다.
- T(A)1: 리더와 에뮬레이터 간의 비트 전송률 및 비대칭 가능 여부를 정의합니다. HCE 기기의 비트 전송률 요구사항이나 보증은 없습니다.
- T(B)1: 비트 1~4는 SFGI(Start-up Frame Guard time Integer)를 나타냅니다. HCE 기기에서 SFGI는 8h 이하여야 합니다. 비트 5~8은 FWI (Frame Waiting time Integer)를 나타내며 FWT (Frame Waiting Time)를 코딩합니다. HCE 기기의 FWI는 <= 8h여야 합니다.
- T(C)1: 비트 5는 '고급 프로토콜 기능' 지원을 나타냅니다. HCE 기기는 '고급 프로토콜 기능'을 지원할 수도 있고 지원하지 않을 수도 있습니다. 비트 2는 DID 지원을 나타냅니다. HCE 기기는 DID를 지원할 수도 있고 지원하지 않을 수도 있습니다. 비트 1은 NAD 지원을 나타냅니다. HCE 기기는 NAD를 지원하지 않아야 하며 비트 1을 0으로 설정해서는 안 됩니다.
- 기록 바이트: HCE 기기는 최대 15개의 기록 바이트를 반환할 수 있습니다. HCE 서비스와 상호작용하려는 NFC 리더는 기록 바이트의 내용이나 존재에 관해 가정해서는 안 됩니다.
많은 HCE 기기가 EMVCo에 통합된 결제 네트워크에서 '미접촉 통신 프로토콜' 사양에 명시한 프로토콜 요구사항을 준수할 가능성이 높습니다. 특히 다음 항목이 중요합니다.
- T0의 FSCI는 2h에서 8h 사이여야 합니다.
- T(A)1은 0x80으로 설정되어야 하며 이 설정은 106kbit/s의 비트 전송률만 지원되며 리더와 에뮬레이터 간 비대칭 비트 전송률은 지원되지 않음을 나타냅니다.
- T(B)1의 FWI는 <= 7h여야 합니다.
APDU 데이터 교환
앞서 언급했듯이 HCE 구현은 단일 논리 채널만 지원합니다. 다른 논리 채널의 애플리케이션을 선택하려고 하면 HCE 기기에서 작동하지 않습니다.