Save the date! Android Dev Summit is coming to Mountain View, CA on November 7-8, 2018.

密钥认证

利用密钥认证,您可以对将应用中使用的密钥存储在设备的硬件支持的密钥库中更加放心。以下部分介绍了如何验证硬件支持的密钥的属性,以及如何解释认证证书扩展数据架构。

注:仅少部分运行 Android 7.0(API 级别 24)的设备支持硬件级密钥认证;其他所有运行 Android 7.0 的设备则使用软件级密钥认证。在生产级环境中验证设备的硬件支持的密钥之属性前,您应确保设备支持硬件级密钥认证。为此,您应确保认证证书链包含由 Google 认证根密钥签署的根证书,且密钥说明数据结构中的 attestationSecurityLevel 元素设置为 TrustedEnvironment 安全级别。

检索和验证硬件支持的密钥对

在密钥认证期间,您可以指定密钥对的别名。认证工具为此提供了一个证书链,您可以用它来验证该密钥对的属性。

如果设备支持硬件级密钥认证,将使用认证根密钥签署此链中的根证书,设备制造商已在出厂时将根密钥注入到设备的硬件支持的密钥库中。

:在附带硬件级密钥认证、Android 7.0(API 级别 24)和 Google Play 服务的设备上,根证书由 Google 认证根密钥签署。您应验证此根证书是否显示在 Google 的根证书列表中。

要实现密钥认证,请完成以下步骤:

  1. 使用 KeyStore 对象的 getCertificateChain() 方法获取指向与硬件支持的密钥库关联的 X.509 证书链的引用。
  2. 使用 CRL 对象的 isRevoked() 方法检查每个证书的有效性。

    注意:尽管您可以在应用中直接完成此流程,但在您信任的独立服务器上检查证书的调用列表更加安全。

  3. 创建一个 Attestation 对象,在证书链的第一个元素中将其作为参数传递:

    // "certificates" contains the certificate chain associated with a specific key
    // pair in the device's hardware-backed keystore.
    X509Certificate attestationCert = (X509Certificate) certificates[0];
    Attestation hardwareKeyAttestation = new Attestation(attestationCert);
    

    认证对象会提取此证书中的扩展数据,并将此信息存储为更容易访问的格式。如需了解有关扩展数据架构的更多详情,请参阅证书扩展数据架构

  4. 使用 Attestation 类中的访问器方法从证书中检索扩展数据。这些方法使用与证书扩展数据架构中相同的名称和结构层次。

    例如,要查看设备 TEE 的已验证启动密钥,请使用以下方法序列:

    // "hardwareKeyAttestation" contains the first element of the attestation
    // certificate chain.
    AuthorizationList teeAuthList = hardwareKeyAttestation.getTeeEnforced();
    RootOfTrust teeRootOfTrust = teeAuthList.getRootOfTrust();
    byte[] teeVerifiedBootKey = teeRootOfTrust.getVerifiedBootKey();
    
  5. 将来自 Attestation 对象的扩展数据与您希望硬件支持的密钥将包含的值集合进行比较。

    注意:尽管您可以在应用中直接完成此流程,但在您信任的独立服务器上检查证书的扩展数据更加安全。

证书扩展数据架构

密钥认证会对设备的硬件支持的密钥库中证书链的第一个证书中显示的扩展数据进行验证。证书按照以下 ASN.1 架构存储信息:

KeyDescription ::= SEQUENCE {
    attestationVersion  INTEGER,
    attestationSecurityLevel  SecurityLevel,
    keymasterVersion  INTEGER,
    keymasterSecurityLevel  SecurityLevel,
    attestationChallenge  OCTET_STRING,
    reserved  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,
    attestationChallenge  [708] EXPLICIT INTEGER OPTIONAL,
    attestationApplicationId  [709] EXPLICIT OCTET_STRING OPTIONAL,
}

RootOfTrust ::= SEQUENCE {
    verifiedBootKey  OCTET_STRING,
    deviceLocked  BOOLEAN,
    verifiedBootState  VerifiedBootState,
}

VerifiedBootState ::= ENUMERATED {
    Verified  (0),
    SelfSigned  (1),
    Unverified  (2),
    Failed  (3),
}

以下列表对该架构中的每个元素进行了说明。

KeyDescription

值的这一顺序提供了有关通过密钥认证进行验证的密钥对的常规信息,并且可以轻松访问其他详情。

attestationVersion
密钥认证功能的版本。应设为 1。
attestationSecurityLevel

认证的安全级别

警告:尽管可以认证存储在 Android 系统中的密钥(也就是,当 attestationSecurityLevel 的值设为 Software 时),但如果 Android 系统受到攻击,您也不能信任这些认证。

keymasterVersion
Keymaster 硬件抽象层 (HAL) 的版本。使用 0 表示版本 0.2 或 0.3,使用 1 表示版本 1.0,使用 2 表示版本 2.0。
keymasterSecurityLevel
Keymaster 实现的安全级别
attestationChallenge
与使用密钥认证验证的密钥对关联的质询字符串。
reserved
仅系统应用使用此值。在所有其他应用中,此值为空。
softwareEnforced
可选。由 Android 系统(而非设备的 TEE)强制执行的 Keymaster 授权列表
teeEnforced
可选。由设备的 TEE 强制执行的 Keymaster 授权列表

SecurityLevel

此数据结构表示密钥对等软件功能受保护的程度基于其在设备中的位置。

因为该数据结构是一个枚举,它可以准确获取以下某个值:

Software
用于创建和管理在 Android 系统中实现的功能的逻辑。如果用于创建和存储密钥对,此位置没有 TEE 安全,但比应用的进程空间安全。
TrustedEnvironment
用于创建和管理在安全硬件(如 TEE)中实现的功能的逻辑。如果用于创建和存储密钥对,此位置比较安全,因为安全硬件更能抵御远程攻击。

AuthorizationList

此数据结构包含密钥对的属性本身,如 Keymaster 硬件抽象层 (HAL) 中所定义。将这些值与设备的当前状态或预期的值集合进行比较,以验证密钥对是否仍适用于您的应用。

每个字段名称均对应一个命名方式相似的 Keymaster 标记。例如,授权列表中的 keySize 字段与 KM_TAG_KEY_SIZE Keymaster 标记对应。

以下列表中的每个字段都是可选字段:

purpose
KM_TAG_PURPOSE Keymaster 标记对应,其使用的标记 ID 值为 1。
algorithm

KM_TAG_ALGORITHM Keymaster 标记对应,其使用的标记 ID 值为 2。

AuthorizationList 对象与密钥认证关联时,此值始终为 KM_ALGORITHM_RSAKM_ALGORITHM_EC

keySize
KM_TAG_KEY_SIZE Keymaster 标记对应,其使用的标记 ID 值为 3。
digest
KM_TAG_DIGEST Keymaster 标记对应,其使用的标记 ID 值为 5。
padding
KM_TAG_PADDING Keymaster 标记对应,其使用的标记 ID 值为 6。
ecCurve

KM_TAG_EC_CURVE Keymaster 标记对应,其使用的标记 ID 值为 10。

用于生成椭圆曲线 (EC) 密钥对的参数集,在 Android 系统密钥库中它使用 ECDSA 进行签署和验证。

rsaPublicExponent
KM_TAG_RSA_PUBLIC_EXPONENT Keymaster 标记对应,其使用的标记 ID 值为 200。
activeDateTime
KM_TAG_ACTIVE_DATETIME Keymaster 标记对应,其使用的标记 ID 值为 400。
originationExpireDateTime
KM_TAG_ORIGINATION_EXPIRE_DATETIME Keymaster 标记对应,其使用的标记 ID 值为 401。
usageExpireDateTime
KM_TAG_USAGE_EXPIRE_DATETIME Keymaster 标记对应,其使用的标记 ID 值为 402。
noAuthRequired

KM_TAG_NO_AUTH_REQUIRED Keymaster 标记对应,其使用的标记 ID 值为 503。

AuthorizationList 对象与密钥认证关联时,此值始终为 true。

userAuthType
KM_TAG_USER_AUTH_TYPE Keymaster 标记对应,其使用的标记 ID 值为 504。
authTimeout
KM_TAG_AUTH_TIMEOUT Keymaster 标记对应,其使用的标记 ID 值为 505。
allowWhileOnBody

KM_TAG_ALLOW_WHILE_ON_BODY Keymaster 标记对应,其使用的标记 ID 值为 506。

如果用户身上仍佩戴着设备,允许在密钥身份验证超时后使用密钥。请注意,安全的体感传感器可以确定设备在用户的身上是否出现磨损。

AuthorizationList 对象与密钥认证关联时,此值始终为 true。

allApplications

KM_TAG_ALL_APPLICATIONS Keymaster 标记对应,其使用的标记 ID 值为 600。

指示设备上的所有应用是否都可以访问密钥对。

AuthorizationList 对象与密钥认证关联时,此值始终为 true。

applicationId
KM_TAG_APPLICATION_ID Keymaster 标记对应,其使用的标记 ID 值为 601。
creationDateTime
KM_TAG_CREATION_DATETIME Keymaster 标记对应,其使用的标记 ID 值为 701。
origin

KM_TAG_ORIGIN Keymaster 标记对应,其使用的标记 ID 值为 702。

AuthorizationList 对象与密钥认证关联时,此值通常设为 KM_ORIGIN_GENERATED。不过,如果认证使用 Keymaster 版本 0.2 或 0.3,则原点可能会被设为 KM_ORIGIN_UNKNOWN

rollbackResistant
KM_TAG_ROLLBACK_RESISTANT Keymaster 标记对应,其使用的标记 ID 值为 703。
rootOfTrust

KM_TAG_ROOT_OF_TRUST Keymaster 标记对应,其使用的标记 ID 值为 704。

如需了解更多详情,请参阅介绍 RootOfTrust 数据结构的部分。

osVersion

KM_TAG_OS_VERSION Keymaster 标记对应,其使用的标记 ID 值为 705。

与 Keymaster 关联的 Android 操作系统的版本,使用一个六位整数表示。例如,版本 6.0.1 表示为 060001。

只有 Keymaster 版本 1.0 或更高版本在授权列表中包含此值。

osPatchLevel

KM_TAG_PATCHLEVEL Keymaster 标记对应,其使用的标记 ID 值为 706。

与在 Keymaster 中使用的安全补丁程序关联的月份和年度,使用一个六位整数表示。例如,2016 年 6 月的补丁程序表示为 201606。

只有 Keymaster 版本 1.0 或更高版本在授权列表中包含此值。

attestationChallenge

KM_TAG_ATTESTATION_CHALLENGE Keymaster 标记对应,其使用的标记 ID 值为 708。

与 Keymaster 中定义的密钥对关联的质询字符串。

attestationApplicationId

KM_TAG_ATTESTATION_APPLICATION_ID Keymaster 标记对应,其使用的标记 ID 值为 709。

签署 Keymaster 中密钥对的认证证书的唯一 ID。

RootOfTrust

这个值集合可以定义与设备状态有关的密钥信息。

以下列表中的每个字段都是必选字段:

verifiedBootKey

验证系统映像的密钥的安全哈希值。建议您针对此哈希值使用 SHA-256 算法。

deviceLocked
在设备的引导装载程序被锁定时为 true,这将启用验证启动检查并防止未签署的设备映像被刷入设备。如需了解有关此功能的详细信息,请参阅验证启动文档。
verifiedBootState
设备启动状态(按照验证启动功能)。
osVersion
设备上的 Android 操作系统的当前版本,使用一个六位整数表示。例如,版本 6.0.1 表示为 060001。
patchMonthYear
与设备上当前安装的安全补丁程序关联的月份和年度,使用一个六位整数表示。例如,2016 年 8 月的补丁程序表示为 201608。

VerifiedBootState

此数据结构可以提供设备的当前启动状态,表示在设备完成启动后为用户和应用提供的保护级别。如需了解有关此功能的详细信息,请参阅“验证启动”文档中的启动状态部分。

此数据结构是一个枚举,它可以准确获取以下某个值:

Verified

指示完整的信任链,其包含引导装载程序、启动分区,以及所有已验证分区。

当设备处于此启动状态时,verifiedBootKey 是嵌入式设备证书的哈希值,设备制造商已在出厂时将其添加到设备的 ROM 中。

SelfSigned

指示嵌入式设备证书已验证设备的启动分区及签名有效。

当设备处于此启动状态时,verifiedBootKey 是用户安装的证书的哈希值,它将签署一个启动分区,用户可以将其添加到设备中代替制造商提供的原始启动分区。

Unverified
指示用户可以随意修改设备。因此,用户应负责验证设备的完整性。
Failed
指示设备验证失败。认证证书决不能使用这个值作为 VerifiedBootState