호스트 기반 카드 에뮬레이션 개요

NFC 기능을 제공하는 많은 Android 지원 기기에서 이미 NFC 카드 에뮬레이션을 지원하고 있습니다. 대부분의 경우 카드는 보안 요소라고 하는 기기의 별도 칩에 의해 에뮬레이션됩니다. 또한 무선 이동통신사에서 제공하는 여러 SIM 카드에도 보안 요소가 포함되어 있습니다.

Android 4.4 이상에서는 보안 요소가 포함되지 않은 추가적인 카드 에뮬레이션 방법인 호스트 기반 카드 에뮬레이션을 제공합니다. 이를 통해 Android 애플리케이션에서 카드를 에뮬레이션하고 NFC 리더와 직접 통신할 수 있습니다. 이 주제에서는 Android에서 호스트 기반 카드 에뮬레이션 (HCE)이 작동하는 방식과 이 기법을 사용하여 NFC 카드를 에뮬레이션하는 앱을 개발하는 방법을 설명합니다.

보안 요소가 있는 카드 에뮬레이션

보안 요소를 사용하여 NFC 카드 에뮬레이션을 제공할 때 에뮬레이션할 카드는 Android 애플리케이션을 통해 기기의 보안 요소에 프로비저닝됩니다. 이후에 사용자가 기기를 NFC 단말기에 올려놓으면 기기의 NFC 컨트롤러가 리더의 모든 데이터를 보안 요소로 직접 라우팅합니다. 그림 1은 이 개념을 보여줍니다.

NFC 컨트롤러를 통해 보안 요소에서 정보를 가져오는 NFC 리더가 있는 다이어그램
그림 1. 보안 요소가 있는 NFC 카드 에뮬레이션

보안 요소가 직접 NFC 단말기와의 통신을 실행하며 Android 애플리케이션이 트랜잭션에 관여하지 않습니다. 거래가 완료된 후 Android 애플리케이션은 보안 요소에 트랜잭션 상태를 직접 쿼리하여 사용자에게 알릴 수 있습니다.

호스트 기반 카드 에뮬레이션

호스트 기반 카드 에뮬레이션을 사용하여 NFC 카드를 에뮬레이션할 때는 데이터가 보안 요소로 라우팅되는 대신 호스트 CPU로 직접 라우팅됩니다. 그림 2는 호스트 기반 카드 에뮬레이션의 작동 방식을 보여줍니다.

NFC 리더가 NFC 컨트롤러를 통해 CPU에서 정보를 가져오는 다이어그램
그림 2. 보안 요소가 없는 NFC 카드 에뮬레이션

지원되는 NFC 카드 및 프로토콜

HCE 프로토콜 스택을 보여주는 다이어그램
그림 3. Android의 HCE 프로토콜 스택

NFC 표준은 여러 다양한 프로토콜을 지원합니다. 그리고 에뮬레이션할 수 있는 다양한 카드 유형이 있습니다.

Android 4.4 이상에서는 오늘날 시장에서 일반적으로 사용되는 여러 프로토콜을 지원합니다. 미접촉 결제 카드와 같은 기존의 많은 미접촉 카드는 이미 이러한 프로토콜을 기반으로 하고 있습니다. 또한 오늘날 리더로 직접 작동하는 Android NFC 기기 (IsoDep 클래스 참고)를 포함하여 시장의 많은 NFC 리더도 이러한 프로토콜을 지원합니다. 이를 통해 Android 지원 기기만 사용하여 HCE를 중심으로 한 엔드 투 엔드 NFC 솔루션을 구축하고 배포할 수 있습니다.

특히 Android 4.4 이상에서는 NFC-Forum ISO-DEP 사양 (ISO/IEC 14443-4 기반)을 기반으로 하는 카드 에뮬레이션 및 ISO/IEC 7816-4 사양에 정의된 프로세스 APDU (Application Protocol Data Unit)를 지원합니다. 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 이상에서는 두 가지 카테고리를 지원합니다.

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 등록

평소와 같이 매니페스트에서 서비스를 선언해야 하지만 서비스 선언에도 일부 추가 부분을 추가해야 합니다.

  1. 플랫폼에 서비스가 HostApduService 인터페이스를 구현하는 HCE 서비스임을 알리려면 서비스 선언에 SERVICE_INTERFACE 작업의 인텐트 필터를 추가합니다.

  2. 이 서비스에서 요청한 AID 그룹을 플랫폼에 알리려면 서비스 선언에 SERVICE_META_DATA <meta-data> 태그를 포함하고 HCE 서비스에 관한 추가 정보가 있는 XML 리소스를 가리킵니다.

  3. 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는 다음 단계에 따라 호출할 서비스를 결정합니다.

  1. 사용자가 선택한 기본 지갑 앱이 AID를 등록한 경우 해당 앱이 호출됩니다.
  2. 기본 월렛 앱이 AID를 등록하지 않은 경우 AID를 등록한 서비스가 호출됩니다.
  3. 두 개 이상의 서비스가 AID를 등록한 경우 Android는 사용자에게 호출할 서비스를 묻습니다.

포그라운드 서비스 환경설정

포그라운드의 앱은 setPreferredService를 호출하여 특정 활동이 포그라운드에 있는 동안 선호해야 하는 카드 에뮬레이션 서비스를 지정할 수 있습니다. 이 포그라운드 앱 환경설정은 AID 충돌 해결보다 우선합니다. 앱에서 사용자가 NFC 카드 에뮬레이션을 사용할 수 있다고 예상하는 경우에 권장됩니다.

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 이상에는 사용자가 설정 > 앱 > 기본 앱으로 이동하여 선택할 수 있는 기본 월렛 앱 역할이 포함되어 있습니다. 결제 단말기를 탭할 때 호출할 기본 지갑 애플리케이션을 정의합니다. Android는 결제 카테고리가 있는 AID 그룹을 선언한 HCE 서비스를 월렛 애플리케이션으로 간주합니다.

앱이 기본 월렛 앱인지 확인

앱은 RoleManager.ROLE_WALLETRoleManager.isRoleHeld()에 전달하여 기본 지갑 앱인지 확인할 수 있습니다.

앱이 기본 앱이 아닌 경우 RoleManager.ROLE_WALLETRoleManager.createRequestRoleIntent()에 전달하여 기본 지갑 역할을 요청할 수 있습니다.

지갑 애플리케이션의 필수 애셋

시각적으로 더 매력적인 사용자 환경을 제공하기 위해 HCE 지갑 애플리케이션은 서비스 배너를 제공해야 합니다.

관찰 모드

Android 15에서는 관찰 모드 기능을 도입합니다. 관찰 모드를 사용 설정하면 기기가 NFC 폴링 루프를 관찰하고 적절한 HostApduService 구성요소에 관해 알림을 전송하여 지정된 NFC 단말기와 상호작용할 준비를 할 수 있습니다. HostApduServicetruesetObserveModeEnabled()에 전달하여 기기를 관찰 모드로 전환할 수 있습니다. 이렇게 하면 NFC 스택에 NFC 트랜잭션을 허용하지 않고 대신 폴링 루프를 수동으로 관찰하도록 지시합니다.

폴링 루프 필터

다음 방법 중 하나를 사용하여 HostApduService의 폴링 루프 필터를 등록할 수 있습니다.

폴링 루프 필터가 비표준 폴링 프레임과 일치하면 NFC 스택은 processPollingFrames() 메서드를 호출하여 이러한 폴링 프레임을 해당 HostApduService로 라우팅합니다. 이를 통해 서비스는 사용자가 거래할 준비가 되었는지 확인하고 거래할 의도가 있는지 확인하는 데 필요한 조치를 취할 수 있습니다(예: 사용자 인증). NFC 리더가 폴링 루프에서 표준 프레임만 사용하는 경우 NFC 스택은 해당 서비스가 포그라운드에 있는 경우 선호하는 포그라운드 서비스로, 그렇지 않은 경우에는 기본 지갑 역할 홀더로 이러한 폴링 프레임을 라우팅합니다.

폴링 프레임 알림에는 getVendorSpecificGain()를 호출하여 가져올 수 있는 공급업체별 필드 강도 측정도 포함됩니다. 공급업체는 단일 바이트에 맞는 한 자체 눈금을 사용하여 측정값을 제공할 수 있습니다.

폴링 루프에 응답하고 관찰 모드에서 전환

서비스가 거래할 준비가 되면 falsesetObserveModeEnabled()에 전달하여 관찰 모드를 종료할 수 있습니다. 그러면 NFC 스택에서 거래를 진행할 수 있습니다.

HostApduService 구성요소는 매니페스트에서 shouldDefaultToObserveModetrue로 설정하거나 CardEmulation.setShouldDefaultToObserveModeForService()를 호출하여 선호되는 결제 서비스일 때마다 관찰 모드를 사용 설정해야 한다고 나타낼 수 있습니다.

HostApduServiceOffHostApduService 구성요소는 수신된 폴링 루프 프레임과 일치하는 폴링 루프 필터가 매니페스트의 PollingLoopFilter 선언에서 autoTransacttrue로 설정하여 관찰 모드를 자동으로 사용 중지하고 트랜잭션이 진행되도록 허용해야 함을 나타낼 수도 있습니다.

포그라운드 서비스 환경설정

포그라운드의 앱은 setPreferredService를 호출하여 특정 활동이 포그라운드에 있는 동안 선호해야 하는 카드 에뮬레이션 서비스를 지정할 수 있습니다. 이 포그라운드 앱 환경설정은 특정 서비스의 shouldDefaultToObserveMode 값에 해당하는 기기의 관찰 모드 상태를 재정의하며, 다음 방법 중 하나로 설정할 수 있습니다.

화면 꺼짐 및 잠금 화면 동작

HCE 서비스의 동작은 기기에서 실행되는 Android 버전에 따라 다릅니다.

Android 15 이상

기본 월렛 앱이 이를 지원하는 기기에서 관찰 모드를 사용 설정하면 거래가 진행될 수 있는 시점을 제어하므로 해당 앱이 잠금 해제 및 화면 끄기 동작을 재정의합니다. 관찰 모드에서 식별 가능한 폴링 루프 패턴을 감지하지 못한 경우 일부 월렛 앱에서는 거래를 진행하기 전에 기기를 잠금 해제해야 할 수 있습니다.

개발자는 리더 기기를 사용하여 식별 가능한 폴링 루프 패턴을 내보내고 앱에서 이러한 패턴을 처리하도록 등록하는 것이 좋습니다.

Android 12 이상

Android 12 (API 수준 31) 이상을 타겟팅하는 앱에서는 requireDeviceScreenOnfalse로 설정하여 기기 화면이 켜지지 않은 상태에서 NFC 결제를 사용 설정할 수 있습니다.

Android 10 이상

Android 10 (API 수준 29) 이상을 실행하는 기기는 보안 NFC를 지원합니다. 보안 NFC가 사용 설정되어 있으면 기기 화면이 꺼져 있을 때 모든 카드 에뮬레이터 (호스트 애플리케이션 및 오프 호스트 애플리케이션)를 사용할 수 없습니다. 보안 NFC가 사용 중지되어 있으면 기기 화면이 꺼져 있을 때 오프 호스트 애플리케이션을 사용할 수 있습니다. isSecureNfcSupported()를 사용하여 보안 NFC 지원을 확인할 수 있습니다.

Android 10 이상을 실행하는 기기에서는 android:requireDeviceUnlocktrue로 설정하는 동일한 기능이 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는 이 아키텍처를 보여줍니다.

보안 요소와 CPU 모두와 통신하는 NFC 리더가 포함된 다이어그램
그림 4. 보안 요소와 호스트 카드 에뮬레이션 모두와 작동하는 Android

또한 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 Forum 요구사항을 충족해야 하므로 NFC 리더는 HCE 기기에 관한 NFC Forum 요구사항에 따라 설정되는 이러한 매개변수를 신뢰할 수 있습니다.

아래 섹션에서는 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 기기에서 작동하지 않습니다.