android 自定义库,Android 密钥库系统

利用 Android 密钥库系统,您可以在容器中存储加密密钥,从而提高从设备中提取密钥的难度。在密钥进入密钥库后,可以将它们用于加密操作,而密钥材料仍不可导出。此外,它提供了密钥使用的时间和方式限制措施,例如要求进行用户身份验证才能使用密钥,或者限制为只能在某些加密模式中使用。如需了解详情,请参阅安全功能部分。

密钥库系统由 Android 4.0(API 级别 14)中引入的 Security 库使用。本文介绍何时以及如何使用 Android 密钥库提供程序。

安全功能

Android 密钥库系统可以保护密钥材料免遭未经授权的使用。首先,Android 密钥库可以防止从应用进程和 Android 设备中整体提取密钥材料,从而避免了在 Android 设备之外以未经授权的方式使用密钥材料。其次,Android 密钥库可以让应用指定密钥的授权使用方式,并在应用进程之外强制实施这些限制,从而避免了在 Android 设备上以未经授权的方式使用密钥材料。

提取防范

Android 密钥库密钥使用两项安全措施来避免密钥材料被提取:密钥材料永不进入应用进程。通过 Android 密钥库密钥执行加密操作时,应用会在后台将待签署或验证的明文、密文和消息馈送到执行加密操作的系统进程。如果应用进程受到攻击,攻击者也许能使用应用密钥,但无法提取密钥材料(例如,在 Android 设备以外使用)。

您可以将密钥材料绑定至 Android 设备的安全硬件,例如可信执行环境 (TEE) 和安全元件 (SE)。为密钥启用此功能时,其密钥材料永远不会暴露于安全硬件之外。如果 Android 操作系统受到攻击或者攻击者可以读取设备内部存储空间,攻击者也许能在 Android 设备上使用任意应用的 Android 密钥库,但无法从设备上提取这些数据。只有设备的安全硬件支持密钥算法、分块模式、填充方案和密钥有权配合使用的摘要的特定组合时,才可启用此功能。要检查是否为密钥启用了此功能,请获取密钥的

硬件安全模块

运行 Android 9(API 级别 28)或更高版本的受支持设备可拥有 StrongBox Keymaster,它是位于硬件安全模块中的 Keymaster HAL 的一种实现。该模块包含以下组成部分:

自己的 CPU。

安全存储空间。

真实随机数生成器。

可抵御软件包篡改和未经授权旁加载应用的附加机制。

检查存储在 StrongBox Keymaster 中的密钥时,系统会通过可信执行环境 (TEE) 证实密钥的完整性。

为支持低能耗的 StrongBox 实现,为一部分算法和密钥大小提供了支持:

RSA 2048

AES 128 和 256

ECDSA P-256

HMAC-SHA256(支持 8-64 字节密钥大小,含首末值)

Triple DES 168

使用 KeyStore 类生成或导入密钥时,您需要通过将 true 传递给 setIsStrongBoxBacked() 方法,指示在 StrongBox Keymaster 中存储密钥的偏好。

注意:如果 StrongBox Keymaster 不适用于密钥的给定算法和关联的密钥大小,框架会抛出 StrongBoxUnavailableException。

密钥使用授权

为了避免在 Android 设备上以未经授权的方式使用密钥,在生成或导入密钥时,Android 密钥库会让应用指定密钥的授权使用方式。一旦生成或导入密钥,其授权将无法更改。然后,每次使用密钥时,都会由 Android 密钥库强制执行授权。这是一项高级安全功能,通常仅用于有以下要求的情形:在生成/导入密钥后(而不是之前或当中),应用进程受到攻击不会导致密钥以未经授权的方式使用。

支持的密钥使用授权分为以下几类:加密:授权密钥算法、运算或目的(加密、解密、签署、验证)、填充方案、分块模式以及可与密钥搭配使用的摘要;

时间有效性间隔:密钥获得使用授权的时间间隔;

用户身份验证:密钥只能在用户最近进行身份验证时使用。请参阅要求进行用户身份验证才能使用密钥。

作为一项额外的安全措施,对于密钥材料位于安全硬件内的密钥(请参阅

选择密钥链或 Android 密钥库提供程序

如果您需要系统全局凭据,请使用

使用 Android 密钥库提供程序让各个应用存储自己的凭据,并且只允许应用自身访问。通过这种方式,应用可以管理仅可供自身使用的凭据,同时所提供的安全优势还可媲美

使用 Android 密钥库提供程序

如需使用此功能,请使用标准的 AndroidKeyStore 提供程序。

生成新私钥

生成新的

Security 库为生成有效的对称密钥提供了默认实现,如以下代码段所示:

Kotlin

// Although you can define your own key generation parameter specification, it's

// recommended that you use the value specified here.

val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC

val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)Java

// Although you can define your own key generation parameter specification, it's

// recommended that you use the value specified here.

KeyGenParameterSpec keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC;

String masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec);

或者,您也可以稍后使用

Kotlin

/*

* Generate a new EC key pair entry in the Android Keystore by

* using the KeyPairGenerator API. The private key can only be

* used for signing or verification and only with SHA-256 or

* SHA-512 as the message digest.

*/

val kpg: KeyPairGenerator = KeyPairGenerator.getInstance(

KeyProperties.KEY_ALGORITHM_EC,

"AndroidKeyStore"

)

val parameterSpec: KeyGenParameterSpec = KeyGenParameterSpec.Builder(

alias,

KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY

).run {

setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)

build()

}

kpg.initialize(parameterSpec)

val kp = kpg.generateKeyPair()Java

/*

* Generate a new EC key pair entry in the Android Keystore by

* using the KeyPairGenerator API. The private key can only be

* used for signing or verification and only with SHA-256 or

* SHA-512 as the message digest.

*/

KeyPairGenerator kpg = KeyPairGenerator.getInstance(

KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");

kpg.initialize(new KeyGenParameterSpec.Builder(

alias,

KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)

.setDigests(KeyProperties.DIGEST_SHA256,

KeyProperties.DIGEST_SHA512)

.build());

KeyPair kp = kpg.generateKeyPair();

生成新密钥

如需生成密钥,请按照与生成新私钥相同的流程进行操作。在每种情况下,您都需要使用 Security 库。

更安全地导入加密密钥

借助 Android 9(API 级别 28)及更高版本,您能够利用 ASN.1 编码密钥格式将已加密密钥安全导入密钥库。Keymaster 随后会在密钥库中将密钥解密,因此密钥的内容永远不会以明文形式出现在设备的主机内存中。此过程提高了密钥解密的安全性。

注意:只有搭载 Keymaster 4 或更高版本的设备才支持该功能。

如需支持以安全方式将已加密密钥导入密钥库,请完成以下步骤:

生成目的为 PURPOSE_WRAP_KEY 的密钥对。建议也为该密钥对添加认证。

在您信任的服务器或机器上,生成 SecureKeyWrapper 应包含的 ASN.1 消息。

该封装容器包含以下架构:

KeyDescription ::= SEQUENCE {

keyFormat INTEGER,

authorizationList AuthorizationList

}

SecureKeyWrapper ::= SEQUENCE {

wrapperFormatVersion INTEGER,

encryptedTransportKey OCTET_STRING,

initializationVector OCTET_STRING,

keyDescription KeyDescription,

secureKey OCTET_STRING,

tag OCTET_STRING

}

创建 WrappedKeyEntry 对象,传入字节数组形式的 ASN.1 消息。

将该 WrappedKeyEntry 对象传入接受 Keystore.Entry 对象的 setEntry() 的重载。

使用密钥库条目

AndroidKeyStore 提供程序的使用通过所有标准

列出条目

通过调用

Kotlin

/*

* Load the Android KeyStore instance using the

* "AndroidKeyStore" provider to list out what entries are

* currently stored.

*/

val ks: KeyStore = KeyStore.getInstance("AndroidKeyStore").apply {

load(null)

}

val aliases: Enumeration = ks.aliases()Java

/*

* Load the Android KeyStore instance using the

* "AndroidKeyStore" provider to list out what entries are

* currently stored.

*/

KeyStore ks = KeyStore.getInstance("AndroidKeyStore");

ks.load(null);

Enumeration aliases = ks.aliases();

对数据进行签名和验证

Kotlin

/*

* Use a PrivateKey in the KeyStore to create a signature over

* some data.

*/

val ks: KeyStore = KeyStore.getInstance("AndroidKeyStore").apply {

load(null)

}

val entry: KeyStore.Entry = ks.getEntry(alias, null)

if (entry !is KeyStore.PrivateKeyEntry) {

Log.w(TAG, "Not an instance of a PrivateKeyEntry")

return null

}

val signature: ByteArray = Signature.getInstance("SHA256withECDSA").run {

initSign(entry.privateKey)

update(data)

sign()

}Java

/*

* Use a PrivateKey in the KeyStore to create a signature over

* some data.

*/

KeyStore ks = KeyStore.getInstance("AndroidKeyStore");

ks.load(null);

KeyStore.Entry entry = ks.getEntry(alias, null);

if (!(entry instanceof PrivateKeyEntry)) {

Log.w(TAG, "Not an instance of a PrivateKeyEntry");

return null;

}

Signature s = Signature.getInstance("SHA256withECDSA");

s.initSign(((PrivateKeyEntry) entry).getPrivateKey());

s.update(data);

byte[] signature = s.sign();

类似地,请使用

Kotlin

/*

* Verify a signature previously made by a PrivateKey in our

* KeyStore. This uses the X.509 certificate attached to our

* private key in the KeyStore to validate a previously

* generated signature.

*/

val ks = KeyStore.getInstance("AndroidKeyStore").apply {

load(null)

}

val entry = ks.getEntry(alias, null) as? KeyStore.PrivateKeyEntry

if (entry == null) {

Log.w(TAG, "Not an instance of a PrivateKeyEntry")

return false

}

val valid: Boolean = Signature.getInstance("SHA256withECDSA").run {

initVerify(entry.certificate)

update(data)

verify(signature)

}Java

/*

* Verify a signature previously made by a PrivateKey in our

* KeyStore. This uses the X.509 certificate attached to our

* private key in the KeyStore to validate a previously

* generated signature.

*/

KeyStore ks = KeyStore.getInstance("AndroidKeyStore");

ks.load(null);

KeyStore.Entry entry = ks.getEntry(alias, null);

if (!(entry instanceof PrivateKeyEntry)) {

Log.w(TAG, "Not an instance of a PrivateKeyEntry");

return false;

}

Signature s = Signature.getInstance("SHA256withECDSA");

s.initVerify(((PrivateKeyEntry) entry).getCertificate());

s.update(data);

boolean valid = s.verify(signature);

要求进行用户身份验证才能使用密钥

生成密钥或将密钥导入到 AndroidKeyStore 时,您可以指定仅授权经过身份验证的用户使用密钥。用户使用安全锁定屏幕凭据(图案/PIN 码/密码、指纹)的子集进行身份验证。

这是一项高级安全功能,通常仅用于有以下要求的情形:在生成/导入密钥后(而不是之前或当中),应用进程受到攻击不会导致密钥被未经身份验证的用户使用。

如果仅授权经过身份验证的用户使用密钥,可将密钥配置为以下列两种模式之一运行:经过身份验证的用户可以在一段时间内使用密钥。在用户解锁安全锁定屏幕或使用 setUserAuthenticationValidityDurationSeconds 在密钥生成或导入时指定。此类密钥只有在启用了安全锁定屏幕的情况下才能生成或导入(请参阅

用户身份验证会授权与某一密钥关联的特定加密操作。在此模式中,涉及此类密钥的每个操作都必须由用户单独授权。目前,此类授权的唯一方式是指纹身份验证:

支持的算法

Cipher

算法

提供支持的 API 级别

备注

AES/CBC/NoPadding

23+

AES/CBC/PKCS7Padding

23+

AES/CTR/NoPadding

23+

AES/ECB/NoPadding

23+

AES/ECB/PKCS7Padding

23+

AES/GCM/NoPadding

23+

仅支持 12 字节长的 IV。

RSA/ECB/NoPadding

18+

RSA/ECB/PKCS1Padding

18+

RSA/ECB/OAEPWithSHA-1AndMGF1Padding

23+

RSA/ECB/OAEPWithSHA-224AndMGF1Padding

23+

RSA/ECB/OAEPWithSHA-256AndMGF1Padding

23+

RSA/ECB/OAEPWithSHA-384AndMGF1Padding

23+

RSA/ECB/OAEPWithSHA-512AndMGF1Padding

23+

RSA/ECB/OAEPPadding

23+

KeyGenerator

算法

提供支持的 API 级别

备注

AES

23+

支持的大小:128、192、256

HmacSHA1

23+

支持的大小:8-1024(含),必须是 8 的倍数

默认大小:160

HmacSHA224

23+

支持的大小:8-1024(含),必须是 8 的倍数

默认大小:224

HmacSHA256

23+

支持的大小:8-1024(含),必须是 8 的倍数

默认大小:256

HmacSHA384

23+

支持的大小:8-1024(含),必须是 8 的倍数

默认大小:384

HmacSHA512

23+

支持的大小:8-1024(含),必须是 8 的倍数

默认大小:512

KeyFactory

KeyStoreKeyStore 支持的密钥类型与 KeyPairGenerator 和 KeyGenerator 支持的相同。

KeyPairGenerator

算法

提供支持的 API 级别

备注

DSA

19-22

EC

23+

支持的大小:224、256、384、521

支持的命名曲线:P-224 (secp224r1)、P-256(又称为 secp256r1 和 prime256v1)、P-384(又称为 secp384r1)、P-521(又称为 secp521r1)

在 API 级别 23 前,EC 密钥可使用经“RSA”算法初始化的

RSA

18+

支持的大小:512、768、1024、2048、3072、4096

支持的公开指数:3、65537

默认公开指数:65537

Mac

算法

提供支持的 API 级别

备注

HmacSHA1

23+

HmacSHA224

23+

HmacSHA256

23+

HmacSHA384

23+

HmacSHA512

23+

Signature

算法

提供支持的 API 级别

备注

MD5withRSA

18+

NONEwithECDSA

23+

NONEwithRSA

18+

SHA1withDSA

19-22

SHA1withECDSA

19+

SHA1withRSA

18+

SHA1withRSA/PSS

23+

SHA224withDSA

20-22

SHA224withECDSA

20+

SHA224withRSA

20+

SHA224withRSA/PSS

23+

SHA256withDSA

19-22

SHA256withECDSA

19+

SHA256withRSA

18+

SHA256withRSA/PSS

23+

SHA384withDSA

19-22

SHA384withECDSA

19+

SHA384withRSA

18+

SHA384withRSA/PSS

23+

SHA512withDSA

19-22

SHA512withECDSA

19+

SHA512withRSA

18+

SHA512withRSA/PSS

23+

SecretKeyFactory

算法

提供支持的 API 级别

备注

AES

23+

支持的密钥规范:

HmacSHA1

23+

支持的密钥规范:

HmacSHA224

23+

支持的密钥规范:

HmacSHA256

23+

支持的密钥规范:

HmacSHA384

23+

支持的密钥规范:

HmacSHA512

23+

支持的密钥规范:

博客文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值