Android 密钥库系统 (一)

目录

一、Android 密钥库系统

二、密钥使用授权

三、生成新私钥


一、Android 密钥库系统

利用 Android 密钥库系统,您可以在容器中存储加密密钥,从而提高从设备中提取密
钥的难度。在密钥进入密钥库后,可以将它们用于加密操作,而密钥材料仍不可导出。此外,
它提供了密钥使用的时间和方式限制措施,例如要求进行用户身份验证才能使用密钥,或者
限制为只能在某些加密模式中使用。如需了解详细信息,请参阅 安全功能 部分。
密钥库系统由 KeyChain API 以及在 Android 4.3 API 级别 18 )中引入的 Android 密钥
库提供程序功能使用。本文说明了何时以及如何使用 Android 密钥库提供程序。
安全功能
Android 密钥库系统可以保护密钥材料免遭未经授权的使用。首先, Android 密钥库可以
防止从应用进程和 Android 设备中整体提取密钥材料,从而避免了在 Android 设备之外以
未经授权的方式使用密钥材料。其次, Android 密钥库可以让应用指定密钥的授权使用方式,
并在应用进程之外强制实施这些限制,从而避免了在 Android 设备上以未经授权的方式使
用密钥材料。
提取防范
Android 密钥库密钥使用两项安全措施来避免密钥材料被提取:
密钥材料永不进入应用进程。通过 Android 密钥库密钥执行加密操作时,应用会将待签
署或验证的明文、密文和消息馈送到执行加密操作的系统进程。如果应用进程受攻击,攻击
者也许能使用应用密钥,但无法提取密钥材料(例如,在 Android 设备以外使用)。
您可以将 密钥材料绑定至 Android 设备的安全硬件 ,例如可信执行环境 (TEE) 和安全
元素 (SE) 。为密钥启用此功能时,其密钥材料永远不会暴露于安全硬件之外。如果 Android
操作系统受到攻击或者攻击者可以读取设备内部存储空间,攻击者也许能在 Android 设备
上使用应用的 Android 密钥库,但无法从设备上提取这些数据。只有设备的安全硬件支持
密钥算法、区块模式、填充方案和密钥有权使用的摘要的特定组合时,才可启用此功能。要
检 查 是 否 为 密 钥 启 用 了 此 功 能 , 请 获 取 密 钥 的
KeyInfo 并 检
KeyInfo.isInsideSecurityHardware() 的返回值。

二、密钥使用授权

为了避免在 Android 设备上以未经授权的方式使用密钥材料,在生成或导入密钥时
Android 密钥库会让应用指定密钥的授权使用方式。一旦生成或导入密钥,其授权将无法更
改。然后,每次使用密钥时,都会由 Android 密钥库强制执行授权。这是一项高级安全功
能,通常仅用于有以下要求的情形:在 生成 / 导入密钥后 (而不是之前或当中),应用进程受
到攻击不会导致密钥以未经授权的方式使用。
支持的密钥使用授权可归为以下几个类别:
加密:授权密钥算法、运算或目的( 加密、解密、签署、验证 )、填充方案、区块模式以
及可与密钥搭配使用的摘要;
时间有效性间隔:密钥获得使用授权的时间间隔;
用户身份验证:密钥只能在用户最近进行身份验证时使用。请参阅 要求进行用户身份验
证才能使用密钥
作 为 一 项 额 外 的 安 全 措 施 , 对 于 密 钥 材 料 位 于 安 全 硬 件 内 部 的 密 钥 ( 请 参
KeyInfo.isInsideSecurityHardware() ),某些密钥使用授权可能由安全硬件实施,具体取决于
Android 设备。加密和用户身份验证授权可能由安全硬件实施。由于安全硬件一般不具备独
立的安全实时时钟,时间有效性间隔授权不可能由其实施。
您可以使用 KeyInfo.isUserAuthenticationRequirementEnforcedBySecureHardware() 查询密钥的
用户身份验证授权是否由安全硬件实施。
选择密钥链或 Android 密钥库提供程序
在需要系统级凭据时请使用 KeyChain API 。在应用通过 KeyChain API 请求使用任何凭据时,
用户需要通过系统提供的 UI 选择应用可以访问已安装的哪些凭据。因此,在用户同意的情
况下多个应用可以使用同一套凭据。
使用 Android 密钥库提供程序让各个应用存储自己的凭据,并且只允许应用自身访问。这
样,应用可以管理仅能由自己使用的凭据,同时又可以提供等同于 KeyChain API 为系统级凭
据提供的安全优势。这一方法不需要用户选择凭据。
使用 Android 密钥库提供程序
要使用此功能,请使用标准的 KeyStore KeyPairGenerator KeyGenerator 类,以及在
Android 4.3 API 级别 18 )中引入的 AndroidKeyStore 提供程序。
AndroidKeyStore 注 册 为 KeyStore 类 型 以 用 于 KeyStore.getInstance(type) 方 法 , 而 在 用
KeyPairGenerator.getInstance(algorithm, provider) KeyGenerator.getInstance(algorithm,
provider) 方法时注册为提供程序。

三、生成新私钥

生成新的 PrivateKey 要求您同时指定自签署证书具备的初始 X.509 属性。之后,您可以使
KeyStore.setKeyEntry 将证书替换为由证书颁发机构 (CA) 签署的证书。
要生成密钥,请使用 KeyPairGenerator KeyPairGeneratorSpec
/*
* 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();
生成新密钥
要生成密钥,请使用 KeyGenerator KeyGenParameterSpec
使用密钥库条目
AndroidKeyStore 提供程序的使用通过所有的标准 KeyStore API 加以实现。
列出条目
通过调用 aliases() 方法列出密钥库中的条目:
/*
* Load the Android KeyStore instance using the the
* "AndroidKeyStore" provider to list out what entries are
* currently stored.
*/
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
Enumeration<String> aliases = ks.aliases();
签署和验证数据
通过从密钥库提取 KeyStore.Entry 并使用 Signature API (例如 sign() )签署数据:
/*
* 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();
类似地,请使用 verify(byte[]) 方法验证数据:
/*
* 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);
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值