키 증명은 앱에서 사용하는 키가 기기의 하드웨어 기반 키 저장소에 저장되도록 보장합니다. 다음 섹션에서는 하드웨어 기반 키의 속성을 확인하는 방법과 증명 인증서의 확장 데이터 스키마를 해석하는 방법을 설명합니다.
참고: 기기의 하드웨어 기반 키의 속성을 프로덕션 수준의 환경에서 확인하려면 먼저 기기에서 하드웨어 수준 키 증명을 지원하는지 확인해야 합니다. 이렇게 하려면, 증명 인증서 체인에 Google 증명 루트 키로 서명된 루트 인증서가 포함되어 있고 키 설명 데이터 구조 내의 attestationSecurityLevel
요소가 TrustedEnvironment 보안 수준으로 설정되어 있는지 확인해야 합니다.
또한, 인증서 체인에 있는 서명을 확인하고 인증서 취소 상태 목록을 확인하여 체인에 취소된 키가 없는지 확인하는 것이 중요합니다. 모두 유효하며 루트가 위에 언급된 Google 루트 키인 경우가 아니면 증명을 완전히 신뢰해서는 안 됩니다. 하지만 취소된 인증서가 포함된 기기는 적어도 소프트웨어 증명만 지원하는 기기만큼 신뢰할 수 있습니다. 완전히 유효한 증명은 신뢰할 수 있음을 강력하게 알려주는 긍정 지표입니다. 유효한 증명이 하나도 없는 경우는 중립(부정적이지 않음) 지표입니다.
하드웨어 기반 키 쌍 검색 및 확인
키 증명 중에 키 쌍의 별칭을 지정합니다. 그러면 증명 도구가 인증서 체인을 제공하며, 이 체인을 사용해 키 쌍의 속성을 확인할 수 있습니다.
기기에서 하드웨어 수준 키 증명을 지원하는 경우, 이 체인 내의 루트 인증서는 증명 루트 키를 사용하여 서명됩니다. 이 루트 키는 제조업체가 공장에서 기기의 하드웨어 기반 키 저장소에 주입합니다.
참고: 하드웨어 수준 키 증명, Android 7.0(API 레벨 24) 이상, Google Play 서비스와 함께 배송되는 기기의 루트 인증서는 Google 증명 루트 키로 서명됩니다. 이 루트 인증서가 아래 표시된 인증서인지 확인해야 합니다.
키 증명을 구현하려면 다음 단계를 완료해야 합니다.
KeyStore
객체의getCertificateChain()
메서드를 사용하여 하드웨어 기반 키 저장소와 연결된 X.509 인증서 체인의 참조를 가져옵니다.-
X509Certificate
객체의checkValidity()
메서드를 사용하여 각 인증서의 유효성을 확인합니다. 또한, 루트 인증서를 신뢰할 수 있는지 확인합니다.주의: 앱 내에서 이 프로세스를 직접 완료할 수 있지만, 신뢰하는 별도 서버에서 인증서 취소 상태를 확인하는 것이 더 안전합니다.
-
신뢰하는 별도 서버에서 도구 모음에 가장 적합한 ASN.1 파서 라이브러리 참조를 가져옵니다. 이 파서를 사용하여 인증서 체인의 첫 번째 요소 내에 표시되는 증명 인증서 확장 데이터를 추출합니다.
키 증명 샘플은 Bouncy Castle의 ASN.1 파서를 사용해 증명 인증서의 확장 데이터를 추출합니다. 자체 파서를 만들기 위한 참조로 이 샘플을 사용할 수 있습니다.
확장 데이터의 스키마에 관한 자세한 내용은 인증서 확장 데이터 스키마를 참조하세요.
-
ASN.1 파서에서 가져온 확장 데이터를 하드웨어 기반 키에 포함될 것으로 예상되는 값 집합과 비교합니다.
주의: 이 과정을 앱에서 직접 완료할 수 있지만 신뢰하는 별도 서버에서 인증서의 확장 데이터를 확인하는 것이 더 안전합니다.
루트 인증서
증명의 신뢰성은 체인의 루트 인증서에 따라 결정됩니다. Google Play를 비롯하여 Google의 앱 제품군을 보유하는 데 필요한 테스트를 통과했으며, Android 7.0(API 레벨 24) 이상이 포함되어 출시된 Android 기기는 Google 하드웨어 증명 루트 인증서로 서명된 증명 키를 사용해야 합니다. 이 인증서는 다음과 같습니다.
-----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIJAOj6GWMU0voYMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV BAUTEGY5MjAwOWU4NTNiNmIwNDUwHhcNMTYwNTI2MTYyODUyWhcNMjYwNTI0MTYy ODUyWjAbMRkwFwYDVQQFExBmOTIwMDllODUzYjZiMDQ1MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEAr7bHgiuxpwHsK7Qui8xUFmOr75gvMsd/dTEDDJdS Sxtf6An7xyqpRR90PL2abxM1dEqlXnf2tqw1Ne4Xwl5jlRfdnJLmN0pTy/4lj4/7 tv0Sk3iiKkypnEUtR6WfMgH0QZfKHM1+di+y9TFRtv6y//0rb+T+W8a9nsNL/ggj nar86461qO0rOs2cXjp3kOG1FEJ5MVmFmBGtnrKpa73XpXyTqRxB/M0n1n/W9nGq C4FSYa04T6N5RIZGBN2z2MT5IKGbFlbC8UrW0DxW7AYImQQcHtGl/m00QLVWutHQ oVJYnFPlXTcHYvASLu+RhhsbDmxMgJJ0mcDpvsC4PjvB+TxywElgS70vE0XmLD+O JtvsBslHZvPBKCOdT0MS+tgSOIfga+z1Z1g7+DVagf7quvmag8jfPioyKvxnK/Eg sTUVi2ghzq8wm27ud/mIM7AY2qEORR8Go3TVB4HzWQgpZrt3i5MIlCaY504LzSRi igHCzAPlHws+W0rB5N+er5/2pJKnfBSDiCiFAVtCLOZ7gLiMm0jhO2B6tUXHI/+M RPjy02i59lINMRRev56GKtcd9qO/0kUJWdZTdA2XoS82ixPvZtXQpUpuL12ab+9E aDK8Z4RHJYYfCT3Q5vNAXaiWQ+8PTWm2QgBR/bkwSWc+NpUFgNPN9PvQi8WEg5Um AGMCAwEAAaOBpjCBozAdBgNVHQ4EFgQUNmHhAHyIBQlRi0RsR/8aTMnqTxIwHwYD VR0jBBgwFoAUNmHhAHyIBQlRi0RsR/8aTMnqTxIwDwYDVR0TAQH/BAUwAwEB/zAO BgNVHQ8BAf8EBAMCAYYwQAYDVR0fBDkwNzA1oDOgMYYvaHR0cHM6Ly9hbmRyb2lk Lmdvb2dsZWFwaXMuY29tL2F0dGVzdGF0aW9uL2NybC8wDQYJKoZIhvcNAQELBQAD ggIBACDIw41L3KlXG0aMiS//cqrG+EShHUGo8HNsw30W1kJtjn6UBwRM6jnmiwfB Pb8VA91chb2vssAtX2zbTvqBJ9+LBPGCdw/E53Rbf86qhxKaiAHOjpvAy5Y3m00m qC0w/Zwvju1twb4vhLaJ5NkUJYsUS7rmJKHHBnETLi8GFqiEsqTWpG/6ibYCv7rY DBJDcR9W62BW9jfIoBQcxUCUJouMPH25lLNcDc1ssqvC2v7iUgI9LeoM1sNovqPm QUiG9rHli1vXxzCyaMTjwftkJLkf6724DFhuKug2jITV0QkXvaJWF4nUaHOTNA4u JU9WDvZLI1j83A+/xnAJUucIv/zGJ1AMH2boHqF8CY16LpsYgBt6tKxxWH00XcyD CdW2KlBCeqbQPcsFmWyWugxdcekhYsAWyoSf818NUsZdBWBaR/OukXrNLfkQ79Iy ZohZbvabO/X+MVT3rriAoKc8oE2Uws6DF+60PV7/WIPjNvXySdqspImSN78mflxD qwLqRBYkA3I75qppLGG9rp7UCdRjxMl8ZDBld+7yvHVgt1cVzJx9xnyGCC23Uaic MDSXYrB4I4WHXPGjxhZuCuPBLTdOLU8YRvMYdEvYebWHMpvwGCF6bAx3JBpIeOQ1 wDB5y0USicV3YgYGmi+NZfhA4URSh77Yd6uuJOJENRaNVTzk -----END CERTIFICATE-----
수신하는 증명 체인의 루트 인증서가 위의 인증서이고 체인에 취소된 인증서가 없는 경우 다음을 알 수 있습니다.
- 키가 Google에서 안전하다고 신뢰하는 하드웨어에 있습니다.
- 루트 인증서에 증명 인증서에서 설명한 속성이 있습니다.
증명 체인에 다른 루트 인증서가 있는 경우 Google에서는 하드웨어의 보안에 대해 어떠한 주장도 하지 않습니다. 그렇다고 해서 키가 손상되었다는 것은 아니며, 증명이 키가 안전한 하드웨어에 있음을 입증하지 못한다는 의미에 불과하므로 보안 가정을 적절하게 조정해야 합니다.
루트 인증서가 위의 인증서가 아니라면 다음 두 가지 이유가 있을 수 있습니다.
- 가장 가능성이 높은 이유는 기기가 Android 버전 7.0 미만으로 실행되었으며, 기기에서 하드웨어 증명을 지원하지 않는 것입니다. 이 경우 Android에 같은 종류의 증명 인증서를 생성하지만 Android 소스 코드에 하드코딩된 키로 서명된 증명 소프트웨어가 구현되어 있습니다. 이 서명 키는 비밀이 아니므로, 공격자가 안전한 하드웨어를 제공하는 것으로 가장하여 만든 증명일 수 있습니다.
- 가능성이 있는 다른 이유는 기기가 Google Play 기기가 아니기 때문입니다. 이 경우 기기 제조업체는 자유롭게 자체 루트를 만들고 증명의 의미에 대해 어떤 주장이든 할 수 있습니다. 기기 제조업체의 문서를 참조하세요. 이 문서가 작성되는 시점에 Google은 어떤 기기 제조업체에서 이와 같은 작업을 했는지 알지 못합니다.
인증서 취소 상태 목록
증명 키는 잘못된 처리나 공격자의 의심되는 추출 등 여러 가지 이유로 취소될 수 있습니다. 따라서, 증명 체인의 각 인증서 상태를 공식 인증서 취소 상태 목록과 비교하여 확인해야 합니다. 이 목록은 Google에서 관리하며 https://android.googleapis.com/attestation/status에 게시됩니다. 이 URL은 정상적으로 유효한 상태가 아닌 인증서의 취소 상태가 포함된 JSON 파일을 반환합니다. JSON 파일의 형식은 다음 JSON 스키마(초안 07) 정의를 따릅니다.
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "entries": { "description" : "Each entry represents the status of an attestation key. The dictionary-key is the certificate serial number in lowercase hex.", "type": "object", "propertyNames": { "pattern": "^[a-f0-9]*$" }, "additionalProperties": { "type": "object", "properties": { "status": { "description": "[REQUIRED] Current status of the key.", "type": "string", "enum": ["REVOKED", "SUSPENDED"] }, "expires": { "description": "[OPTIONAL] UTC date when certificate expires in ISO8601 format (YYYY-MM-DD). Can be used to clear expired certificates from the status list.", "type": "string", "format": "date" }, "reason": { "description": "[OPTIONAL] Reason for the current status.", "type": "string", "enum": ["UNSPECIFIED", "KEY_COMPROMISE", "CA_COMPROMISE", "SUPERSEDED", "SOFTWARE_FLAW"] }, "comment": { "description": "[OPTIONAL] Free form comment about the key status.", "type": "string", "maxLength": 140 } }, "required": ["status"], "additionalProperties": false } } }, "required": ["entries"], "additionalProperties": false }
다음은 인증서 해지 상태 목록의 예입니다.
{ "entries": { "2c8cdddfd5e03bfc": { "status": "REVOKED", "expires": "2020-11-13", "reason": "KEY_COMPROMISE", "comment": "Key stored on unsecure system" }, "c8966fcb2fbb0d7a": { "status": "SUSPENDED", "reason": "SOFTWARE_FLAW", "comment": "Bug in keystore causes this key malfunction b/555555" } } }
기존 CRL
기존 증명 인증서에 삽입된 CRL URL은 계속 작동합니다. 새 증명 인증서에는 CRL URL 확장 프로그램이 더 이상 포함되지 않습니다. 기존 인증서 상태도 증명 상태 목록에 포함되므로 개발자가 새 인증서와 기존 인증서 모두의 증명 상태 목록을 사용하는 것으로 안전하게 전환할 수 있습니다. Android 증명 키를 올바르게 확인하는 방법에 관한 예는 키 증명 샘플에 포함되어 있습니다.
인증서 확장 데이터 스키마
키 증명은 기기의 하드웨어 기반 키 저장소의 체인에 있는 첫 번째 인증서에 나타나는 확장 데이터를 확인합니다. 인증서는 ASN.1 스키마에 따라 정보를 저장합니다. 사용 중인 증명 버전에 해당하는 스키마를 보려면 다음 스키마 목록에서 적절한 탭을 선택하세요.
버전 3
KeyDescription ::= SEQUENCE { attestationVersion 3, attestationSecurityLevel SecurityLevel, keymasterVersion INTEGER, keymasterSecurityLevel SecurityLevel, attestationChallenge OCTET_STRING, uniqueId OCTET_STRING, softwareEnforced AuthorizationList, teeEnforced AuthorizationList, } SecurityLevel ::= ENUMERATED { Software (0), TrustedEnvironment (1), StrongBox (2), } AuthorizationList ::= SEQUENCE { purpose [1] EXPLICIT SET OF INTEGER OPTIONAL, algorithm [2] EXPLICIT INTEGER OPTIONAL, keySize [3] EXPLICIT INTEGER OPTIONAL, digest [5] EXPLICIT SET OF INTEGER OPTIONAL, padding [6] EXPLICIT SET OF INTEGER OPTIONAL, ecCurve [10] EXPLICIT INTEGER OPTIONAL, rsaPublicExponent [200] EXPLICIT INTEGER OPTIONAL, rollbackResistance [303] EXPLICIT NULL OPTIONAL, activeDateTime [400] EXPLICIT INTEGER OPTIONAL, originationExpireDateTime [401] EXPLICIT INTEGER OPTIONAL, usageExpireDateTime [402] EXPLICIT INTEGER OPTIONAL, noAuthRequired [503] EXPLICIT NULL OPTIONAL, userAuthType [504] EXPLICIT INTEGER OPTIONAL, authTimeout [505] EXPLICIT INTEGER OPTIONAL, allowWhileOnBody [506] EXPLICIT NULL OPTIONAL, trustedUserPresenceRequired [507] EXPLICIT NULL OPTIONAL, trustedConfirmationRequired [508] EXPLICIT NULL OPTIONAL, unlockedDeviceRequired [509] EXPLICIT NULL OPTIONAL, allApplications [600] EXPLICIT NULL OPTIONAL, applicationId [601] EXPLICIT OCTET_STRING OPTIONAL, creationDateTime [701] EXPLICIT INTEGER OPTIONAL, origin [702] EXPLICIT INTEGER OPTIONAL, rootOfTrust [704] EXPLICIT RootOfTrust OPTIONAL, osVersion [705] EXPLICIT INTEGER OPTIONAL, osPatchLevel [706] EXPLICIT INTEGER OPTIONAL, attestationApplicationId [709] EXPLICIT OCTET_STRING OPTIONAL, attestationIdBrand [710] EXPLICIT OCTET_STRING OPTIONAL, attestationIdDevice [711] EXPLICIT OCTET_STRING OPTIONAL, attestationIdProduct [712] EXPLICIT OCTET_STRING OPTIONAL, attestationIdSerial [713] EXPLICIT OCTET_STRING OPTIONAL, attestationIdImei [714] EXPLICIT OCTET_STRING OPTIONAL, attestationIdMeid [715] EXPLICIT OCTET_STRING OPTIONAL, attestationIdManufacturer [716] EXPLICIT OCTET_STRING OPTIONAL, attestationIdModel [717] EXPLICIT OCTET_STRING OPTIONAL, vendorPatchLevel [718] EXPLICIT INTEGER OPTIONAL, bootPatchLevel [719] EXPLICIT INTEGER OPTIONAL, } RootOfTrust ::= SEQUENCE { verifiedBootKey OCTET_STRING, deviceLocked BOOLEAN, verifiedBootState VerifiedBootState, verifiedBootHash OCTET_STRING, } VerifiedBootState ::= ENUMERATED { Verified (0), SelfSigned (1), Unverified (2), Failed (3), }
버전 2
KeyDescription ::= SEQUENCE { attestationVersion 2, attestationSecurityLevel SecurityLevel, keymasterVersion INTEGER, keymasterSecurityLevel SecurityLevel, attestationChallenge OCTET_STRING, uniqueId OCTET_STRING, softwareEnforced AuthorizationList, teeEnforced AuthorizationList, } SecurityLevel ::= ENUMERATED { Software (0), TrustedEnvironment (1), } AuthorizationList ::= SEQUENCE { purpose [1] EXPLICIT SET OF INTEGER OPTIONAL, algorithm [2] EXPLICIT INTEGER OPTIONAL, keySize [3] EXPLICIT INTEGER OPTIONAL, digest [5] EXPLICIT SET OF INTEGER OPTIONAL, padding [6] EXPLICIT SET OF INTEGER OPTIONAL, ecCurve [10] EXPLICIT INTEGER OPTIONAL, rsaPublicExponent [200] EXPLICIT INTEGER OPTIONAL, activeDateTime [400] EXPLICIT INTEGER OPTIONAL, originationExpireDateTime [401] EXPLICIT INTEGER OPTIONAL, usageExpireDateTime [402] EXPLICIT INTEGER OPTIONAL, noAuthRequired [503] EXPLICIT NULL OPTIONAL, userAuthType [504] EXPLICIT INTEGER OPTIONAL, authTimeout [505] EXPLICIT INTEGER OPTIONAL, allowWhileOnBody [506] EXPLICIT NULL OPTIONAL, allApplications [600] EXPLICIT NULL OPTIONAL, applicationId [601] EXPLICIT OCTET_STRING OPTIONAL, creationDateTime [701] EXPLICIT INTEGER OPTIONAL, origin [702] EXPLICIT INTEGER OPTIONAL, rollbackResistant [703] EXPLICIT NULL OPTIONAL, rootOfTrust [704] EXPLICIT RootOfTrust OPTIONAL, osVersion [705] EXPLICIT INTEGER OPTIONAL, osPatchLevel [706] EXPLICIT INTEGER OPTIONAL, attestationApplicationId [709] EXPLICIT OCTET_STRING OPTIONAL, attestationIdBrand [710] EXPLICIT OCTET_STRING OPTIONAL, attestationIdDevice [711] EXPLICIT OCTET_STRING OPTIONAL, attestationIdProduct [712] EXPLICIT OCTET_STRING OPTIONAL, attestationIdSerial [713] EXPLICIT OCTET_STRING OPTIONAL, attestationIdImei [714] EXPLICIT OCTET_STRING OPTIONAL, attestationIdMeid [715] EXPLICIT OCTET_STRING OPTIONAL, attestationIdManufacturer [716] EXPLICIT OCTET_STRING OPTIONAL, attestationIdModel [717] EXPLICIT OCTET_STRING OPTIONAL, } RootOfTrust ::= SEQUENCE { verifiedBootKey OCTET_STRING, deviceLocked BOOLEAN, verifiedBootState VerifiedBootState, } VerifiedBootState ::= ENUMERATED { Verified (0), SelfSigned (1), Unverified (2), Failed (3), }
버전 1
KeyDescription ::= SEQUENCE { attestationVersion 1, attestationSecurityLevel SecurityLevel, keymasterVersion INTEGER, keymasterSecurityLevel SecurityLevel, attestationChallenge OCTET_STRING, uniqueId OCTET_STRING, softwareEnforced AuthorizationList, teeEnforced AuthorizationList, } SecurityLevel ::= ENUMERATED { Software (0), TrustedEnvironment (1), } AuthorizationList ::= SEQUENCE { purpose [1] EXPLICIT SET OF INTEGER OPTIONAL, algorithm [2] EXPLICIT INTEGER OPTIONAL, keySize [3] EXPLICIT INTEGER OPTIONAL, digest [5] EXPLICIT SET OF INTEGER OPTIONAL, padding [6] EXPLICIT SET OF INTEGER OPTIONAL, ecCurve [10] EXPLICIT INTEGER OPTIONAL, rsaPublicExponent [200] EXPLICIT INTEGER OPTIONAL, activeDateTime [400] EXPLICIT INTEGER OPTIONAL, originationExpireDateTime [401] EXPLICIT INTEGER OPTIONAL, usageExpireDateTime [402] EXPLICIT INTEGER OPTIONAL, noAuthRequired [503] EXPLICIT NULL OPTIONAL, userAuthType [504] EXPLICIT INTEGER OPTIONAL, authTimeout [505] EXPLICIT INTEGER OPTIONAL, allowWhileOnBody [506] EXPLICIT NULL OPTIONAL, allApplications [600] EXPLICIT NULL OPTIONAL, applicationId [601] EXPLICIT OCTET_STRING OPTIONAL, creationDateTime [701] EXPLICIT INTEGER OPTIONAL, origin [702] EXPLICIT INTEGER OPTIONAL, rollbackResistant [703] EXPLICIT NULL OPTIONAL, rootOfTrust [704] EXPLICIT RootOfTrust OPTIONAL, osVersion [705] EXPLICIT INTEGER OPTIONAL, osPatchLevel [706] EXPLICIT INTEGER OPTIONAL, } RootOfTrust ::= SEQUENCE { verifiedBootKey OCTET_STRING, deviceLocked BOOLEAN, verifiedBootState VerifiedBootState, } VerifiedBootState ::= ENUMERATED { Verified (0), SelfSigned (1), Unverified (2), Failed (3), }
다음 목록은 스키마 내의 각 요소에 대한 설명을 나타냅니다.
KeyDescription
이러한 값의 시퀀스는 키 증명을 통해 확인되는 키 쌍에 관한 일반적인 정보를 표시하며, 추가 세부정보에 쉽게 액세스할 수 있는 권한을 제공합니다.
-
attestationVersion
- 키 증명 기능의 버전입니다.
-
attestationSecurityLevel
-
증명의 보안 수준입니다.
경고: Android 시스템에 저장된 키를 증명하는 것은 가능하겠지만(즉,
attestationSecurityLevel
값이 Software로 설정된 경우), Android 시스템이 손상된 경우에는 이러한 증명을 신뢰할 수 없습니다. -
keymasterVersion
- Keymaster HAL(하드웨어 추상화 계층)의 버전입니다. 버전 0.2 또는 0.3을 나타내려면 0, 버전 1.0을 나타내려면 1, 버전 2.0을 나타내려면 2를 사용합니다.
-
keymasterSecurityLevel
- Keymaster 구현의 보안 수준입니다.
-
uniqueId
- 이 값은 제한된 기간에만 기기를 식별합니다. 이 값은 계산되며 시스템 앱에서만 사용합니다. 다른 앱에서는
uniqueId
가 비어 있습니다. -
softwareEnforced
- 선택사항입니다. 기기의 TEE가 아니라 Android 시스템에서 시행하는 Keymaster 승인 목록입니다.
-
teeEnforced
- 선택사항입니다. 기기의 TEE에서 시행하는 Keymaster 승인 목록입니다.
SecurityLevel
이 데이터 구조는 기기 내의 위치에 따라 소프트웨어 기능(예: 키 쌍)이 보호되는 정도를 나타냅니다.
이 데이터 구조는 열거형이므로, 정확히 다음 값 중 하나를 취합니다.
- Software
- 기능을 만들고 관리하는 로직이 Android 시스템에서 구현됩니다. 키 쌍을 만들고 저장하는 용도의 경우, 이 위치는 TEE보다는 덜 안전하지만, 앱의 프로세스 공간보다는 더 안전합니다.
- TrustedEnvironment
- 기능을 만들고 관리하는 로직이 안전한 하드웨어(예: TEE)에서 구현됩니다. 키 쌍을 만들고 저장하는 용도의 경우, 안전한 하드웨어는 원격 손상에 잘 견디므로 이 위치가 더 안전합니다.
- StrongBox
- 기능을 만들고 관리하는 로직이 전용 하드웨어 보안 모듈에서 구현됩니다. 키 쌍을 만들고 저장하는 용도의 경우, 이 위치는 모듈에 대한 원격 손상 및 하드웨어 공격에 잘 견디므로 더 안전합니다.
AuthorizationList
이 데이터 구조에는 Keymaster 하드웨어 추상화 계층(HAL)에 정의된 키 쌍의 속성 자체가 포함되어 있습니다. 이 값을 기기의 현재 상태와 비교하거나 예상되는 값 집합과 비교하여 앱에서 사용하기에 키 쌍이 계속 유효한지 확인할 수 있습니다.
각 필드 이름은 유사한 이름의 Keymaster 승인 태그에 대응됩니다.
예를 들어, 승인 목록의 keySize
필드는 Tag::KEY_SIZE
Keymaster 승인 태그에 대응됩니다.
다음 목록의 각 필드는 선택사항입니다.
-
purpose
Tag::PURPOSE
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 1을 사용합니다.-
algorithm
-
Tag::ALGORITHM
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 2를 사용합니다.증명
AuthorizationList
객체에서 알고리즘 값은 항상RSA
또는EC
입니다. -
keySize
Tag::KEY_SIZE
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 3을 사용합니다.-
digest
Tag::DIGEST
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 5를 사용합니다.-
padding
Tag::PADDING
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 6을 사용합니다.-
ecCurve
-
Tag::EC_CURVE
Keymaster 태그에 대응하며, 이 태그는 태그 ID 값으로 10을 사용합니다.Android 시스템 키 저장소에서 서명 및 확인을 위해 ECDSA를 사용하는 타원 곡선(EC) 키 쌍을 생성하는 데 사용되는 매개변수 집합입니다.
-
rsaPublicExponent
Tag::RSA_PUBLIC_EXPONENT
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 200을 사용합니다.-
rollbackResistance
-
키 증명 버전 3에만 있습니다.
Tag::ROLLBACK_RESISTANT
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 303을 사용합니다. -
activeDateTime
Tag::ACTIVE_DATETIME
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 400을 사용합니다.-
originationExpireDateTime
Tag::ORIGINATION_EXPIRE_DATETIME
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 401을 사용합니다.-
usageExpireDateTime
Tag::USAGE_EXPIRE_DATETIME
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 402를 사용합니다.-
noAuthRequired
-
Tag::NO_AUTH_REQUIRED
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 503을 사용합니다. -
userAuthType
Tag::USER_AUTH_TYPE
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 504를 사용합니다.-
authTimeout
Tag::AUTH_TIMEOUT
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 505를 사용합니다.-
allowWhileOnBody
-
Tag::ALLOW_WHILE_ON_BODY
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 506을 사용합니다.사용자가 기기를 계속 몸에 착용하고 있으면 인증 시간 제한 후 키를 사용하도록 허용합니다. 안전한 신체용 센서는 기기가 사용자의 신체에 착용 되어 있는지 확인합니다.
-
trustedUserPresenceRequired
-
키 증명 버전 3에만 있습니다.
Tag::TRUSTED_USER_PRESENCE_REQUIRED
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 507을 사용합니다.사용자가 실제 존재 증거를 제공한 경우에만 이 키를 사용할 수 있음을 지정합니다. 몇 가지 예는 다음과 같습니다.
- StrongBox 키의 경우 하드웨어 버튼이 StrongBox 기기의 핀에 내장되어 있습니다.
- TEE 키의 경우 TEE에서 스캐너를 독점적으로 제어하고 지문 일치 프로세스를 시행하는 한 지문 인증이 존재 증명을 제공합니다.
-
trustedConfirmationRequired
-
키 증명 버전 3에만 있습니다.
Tag::TRUSTED_CONFIRMATION_REQUIRED
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 508을 사용합니다.사용자가 승인 토큰을 사용해 서명될 데이터를 확인하는 경우에만 키를 사용할 수 있음을 지정합니다. 사용자의 확인을 받는 방법에 관한 자세한 내용은 Android 보안 확인을 참조하세요.
참고: 이 태그는
SIGN
목적으로 사용되는 키에만 적용할 수 있습니다. -
unlockedDeviceRequired
-
키 증명 버전 3에만 있습니다.
Tag::UNLOCKED_DEVICE_REQUIRED
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 509를 사용합니다. -
allApplications
-
Tag::ALL_APPLICATIONS
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 600을 사용합니다.기기의 모든 앱이 키 쌍에 액세스할 수 있는지 나타냅니다.
-
applicationId
Tag::APPLICATION_ID
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 601을 사용합니다.-
creationDateTime
Tag::CREATION_DATETIME
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 701을 사용합니다.-
origin
-
Tag::ORIGIN
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 702를 사용합니다. -
rollbackResistant
-
키 증명 버전 1과 2에만 있습니다.
Tag::ROLLBACK_RESISTANT
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 703을 사용합니다. -
rootOfTrust
-
Tag::ROOT_OF_TRUST
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 704를 사용합니다.자세한 내용은 RootOfTrust 데이터 구조를 설명하는 섹션을 참조하세요.
-
osVersion
-
Tag::OS_VERSION
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 705를 사용합니다.Keymaster와 연결된 Android 운영체제의 버전으로, 6자리 정수로 지정됩니다. 예를 들어, 버전 8.1.0은 080100으로 나타냅니다.
Keymaster 버전 1.0 이상에서만 승인 목록에 이 값을 포함합니다.
-
osPatchLevel
-
Tag::PATCHLEVEL
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 706을 사용합니다.Keymaster에서 사용되는 보안 패치와 연결된 월과 연도로, 6자리 정수로 지정됩니다. 예를 들어, 2018년 8월 패치는 201808로 나타냅니다.
Keymaster 버전 1.0 이상에서만 승인 목록에 이 값을 포함합니다.
-
attestationApplicationId
-
키 증명 버전 2와 3에만 있습니다.
Tag::ATTESTATION_APPLICATION_ID
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 709를 사용합니다.자세한 내용은 AttestationApplicationId 데이터 구조를 설명하는 섹션을 참조하세요.
-
attestationIdBrand
-
키 증명 버전 2와 3에만 있습니다.
Tag::ATTESTATION_ID_BRAND
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 710을 사용합니다. -
attestationIdDevice
-
키 증명 버전 2와 3에만 있습니다.
Tag::ATTESTATION_ID_DEVICE
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 709를 사용합니다. -
attestationIdProduct
-
키 증명 버전 2와 3에만 있습니다.
Tag::ATTESTATION_ID_PRODUCT
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 712를 사용합니다. -
attestationIdSerial
-
키 증명 버전 2와 3에만 있습니다.
Tag::ATTESTATION_ID_SERIAL
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 713을 사용합니다. -
attestationIdImei
-
키 증명 버전 2와 3에만 있습니다.
Tag::ATTESTATION_ID_IMEI
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 714를 사용합니다. -
attestationIdMeid
-
키 증명 버전 2와 3에만 있습니다.
Tag::ATTESTATION_ID_MEID
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 715를 사용합니다. -
attestationIdManufacturer
-
키 증명 버전 2와 3에만 있습니다.
Tag::ATTESTATION_ID_MANUFACTURER
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 716을 사용합니다. -
attestationIdModel
-
키 증명 버전 2와 3에만 있습니다.
Tag::ATTESTATION_ID_MODEL
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 717을 사용합니다. -
vendorPatchLevel
-
키 증명 버전 3에만 있습니다.
Tag::VENDOR_PATCHLEVEL
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 718을 사용합니다.이 키를 사용할 기기에 설치되어야 하는 공급업체 이미지 보안 패치 수준을 지정합니다. 값은 YYYYMMDD 형식으로 표시되며, 공급업체 보안 패치의 날짜를 나타냅니다. 예를 들어 공급업체의 2018년 8월 1일 보안 패치가 설치된 Android 기기에서 키가 생성된 경우 이 값은 20180801이 됩니다.
-
bootPatchLevel
-
키 증명 버전 3에만 있습니다.
Tag::BOOT_PATCHLEVEL
Keymaster 승인 태그에 대응하며, 이 태그는 태그 ID 값으로 719를 사용합니다.이 키를 사용할 기기에 설치되어야 하는 커널 이미지 보안 패치 수준을 지정합니다. 값은 YYYYMMDD 형식으로 표시되며, 시스템 보안 패치의 날짜를 나타냅니다. 예를 들어 시스템의 2018년 8월 5일 보안 패치가 설치된 Android 기기에서 키가 생성된 경우 이 값은 20180805가 됩니다.
RootOfTrust
이 값 모음은 기기 상태에 관한 키 정보를 정의합니다.
다음 목록의 각 필드는 필수입니다.
-
verifiedBootKey
-
시스템 이미지를 확인하는 키의 안전한 해시. 이 해시에는 SHA-256 알고리즘을 사용하는 것이 좋습니다.
-
deviceLocked
- 기기의 부트로더가 잠긴 경우 참이며, 이 경우 자체 검사 부팅 확인을 사용 설정하고, 서명되지 않은 기기 이미지가 기기에 플래시되지 않도록 합니다. 이 기능에 관한 자세한 내용은 자체 검사 부팅 문서를 참조하세요.
-
verifiedBootState
- 자체 검사 부팅 기능에 따른 기기의 부팅 상태입니다.
-
verifiedBootHash
-
키 증명 버전 3에만 있습니다.
자체 검사 부팅으로 보호되는 모든 데이터의 다이제스트입니다. 자체 검사 부팅의 Android 자체 검사 부팅 구현을 사용하는 기기의 경우 이 값에 VBMeta 구조체의 다이제스트 또는 자체 검사 부팅 메타데이터 구조가 포함됩니다.
이 값을 계산하는 방법에 관한 자세한 내용은 VBMeta 다이제스트를 참조하세요.
VerifiedBootState
이 데이터 구조는 기기의 현재 부팅 상태를 제공하며, 이는 기기 부팅이 완료된 후 사용자와 앱에 제공되는 보호 수준을 나타냅니다. 이 기능에 관한 자세한 내용은 자체 검사 부팅 문서 내 부팅 상태 섹션을 참조하세요.
이 데이터 구조는 열거형이므로, 정확히 다음 값 중 하나를 취합니다.
- 확인됨
-
신뢰할 수 있는 전체 체인을 나타내며, 여기에는 부트로더, 부트 파티션 및 확인된 모든 파티션이 포함됩니다.
기기가 이 부팅 상태에 있으면,
verifiedBootKey
는 기기에 삽입된 인증서의 해시이며, 이것은 공장에서 기기 제조업체가 기기의 ROM에 추가하는 것입니다. - SelfSigned
-
기기에 삽입된 인증서가 기기의 부트 파티션을 확인했고 서명이 유효함을 나타냅니다.
기기가 이 부팅 상태에 있으면,
verifiedBootKey
는 사용자가 설치한 인증서의 해시이며, 이것은 제조업체가 제공한 원본 부트 파티션 대신에 사용자가 기기에 추가한 부트 파티션에 서명합니다. - Unverified
- 사용자가 기기를 자유롭게 수정할 수 있음을 나타냅니다. 따라서, 기기의 무결성을 확인하는 것은 사용자의 책임입니다.
- Failed
- 기기가 확인에 실패했음을 나타냅니다. 증명 인증서는 이 값을
VerifiedBootState
에 사용해서는 절대 안 됩니다.
AttestationApplicationId
이 데이터 구조는 증명 중인 비밀 키 머티리얼을 사용하도록 허용된 앱에 대한 Android 플랫폼의 신뢰를 반영합니다. 여러 패키지가 동일한 UID를 공유하는 경우에만 ID가 여러 패키지를 구성할 수 있습니다. 옥텟 문자열 자체는 다음 ASN.1 스키마에 따라 형식이 지정됩니다.
AttestationApplicationId ::= SEQUENCE { package_infos SET OF AttestationPackageInfo, signature_digests SET OF OCTET_STRING, } AttestationPackageInfo ::= SEQUENCE { package_name OCTET_STRING, version INTEGER, }
- package_infos
AttestationPackageInfo
객체의 집합으로, 각 패키지의 이름과 버전 번호를 제공합니다.- signature_digests
-
getPackageInfo()
호출 시 반환되는PackageInfo
의signatures
필드에 포함된 것으로 앱 서명 blob의 SHA-256 다이제스트 집합입니다. 다음 코드 스니펫에서는 예 집합을 보여줍니다.{SHA256(PackageInfo.signature[0]), SHA256(PackageInfo.signature[1]), ...}