2. 密码学基础
在 Android Keystore 与密钥服务开发中,密码学原语并不是抽象的理论,而是直接决定密钥如何生成、如何存储、如何调用以及如何失效的工程基础。理解对称加密、非对称加密、哈希、消息认证码、数字签名与密钥派生之间的分工,才能在后续使用 KeyStore、KeyGenerator、KeyPairGenerator、Cipher、Mac、Signature 等 API 时做出正确选择。
一、核心原理:六类密码学原语的分工
密码学原语可以按“是否可逆”“是否使用密钥”“密钥是否成对”三个维度来区分。对称加密使用同一把密钥完成加密和解密,速度快,适合保护大量数据;非对称加密使用公钥和私钥成对工作,公钥可公开,私钥必须保密,适合密钥交换和身份验证;哈希函数把任意长度输入压缩成固定长度摘要,不可逆,用于完整性校验;消息认证码在哈希基础上加入共享密钥,既校验完整性又验证来源;数字签名用私钥签名、公钥验签,提供不可否认性;密钥派生则从一个主密钥或口令派生出多个用途不同的子密钥,避免密钥复用。
二、方法流程:在 Android 中如何选择与调用
在 Android 开发中,选择密码学原语应遵循“先明确安全目标,再匹配原语”的顺序。若目标是保护本地文件或网络报文,优先使用 AES-GCM 这类带认证的对称加密;若需要安全交换密钥或验证身份,使用 ECDH 或 ECDSA;若只需校验数据是否被篡改,使用 SHA-256;若需要同时验证来源和完整性,使用 HMAC;若需要向第三方证明某条数据由特定私钥持有者签发,使用数字签名;若需要从用户口令或主密钥生成多个子密钥,使用 PBKDF2 或 HKDF。
以下代码展示了在 Android 中生成 AES 密钥并使用 GCM 模式加密的典型流程:
// 1. 在 Android Keystore 中生成 AES 密钥
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(new KeyGenParameterSpec.Builder(
"my_aes_key",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setKeySize(256)
.build());
SecretKey secretKey = keyGenerator.generateKey();
// 2. 使用 Cipher 加密
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] iv = cipher.getIV();
byte[] cipherText = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
对于消息认证码,Android 提供 Mac 类,常用算法为 HmacSHA256。数字签名则通过 Signature 类完成,例如 SHA256withECDSA。密钥派生可使用 SecretKeyFactory 配合 PBKDF2WithHmacSHA256,或使用 Android 提供的 HKDF 实现。
三、案例场景:一次安全通信的完整链路
假设一个 Android 应用需要向服务端上传敏感数据。完整链路如下:客户端首先生成临时 ECDH 密钥对,与服务端公钥协商出共享密钥;然后使用 HKDF 从共享密钥派生出 AES 加密密钥和 HMAC 密钥;接着用 AES-GCM 加密数据,GCM 本身已提供完整性保护;若协议要求额外来源认证,再对密文计算 HMAC;服务端收到后先验 HMAC,再解密,最后用客户端公钥验证数字签名。这个链路中,非对称加密解决密钥交换,对称加密解决数据保密,KDF 解决密钥隔离,MAC 和签名解决认证与不可否认。
四、误区与复盘:常见错误与纠正
- 误区一:用哈希代替加密。哈希不可逆,不能用于需要还原明文的场景;若需保密,必须使用加密。
- 误区二:用对称加密代替 MAC。对称加密只保证机密性,不保证完整性;应使用 AES-GCM 或 Encrypt-then-MAC。
- 误区三:密钥复用。同一把密钥既用于加密又用于签名,会扩大攻击面;应通过 KDF 派生不同用途的子密钥。
- 误区四:忽略 IV 和盐值。GCM 的 IV 必须唯一,PBKDF2 的盐值必须随机且足够长,否则会削弱安全性。
- 误区五:在应用层保存原始密钥。应优先使用 Android Keystore 生成和持有密钥,避免密钥泄露。
| 原语 | 典型算法 | 密钥类型 | 主要安全目标 | Android API |
|---|---|---|---|---|
| 对称加密 | AES-GCM | 单密钥 | 机密性 + 完整性 | KeyGenerator、Cipher |
| 非对称加密 | RSA-OAEP、ECDH | 公钥/私钥对 | 密钥交换、机密性 | KeyPairGenerator、Cipher |
| 哈希 | SHA-256 | 无密钥 | 完整性 | MessageDigest |
| 消息认证码 | HMAC-SHA256 | 共享密钥 | 完整性 + 来源认证 | Mac |
| 数字签名 | SHA256withECDSA | 私钥签名/公钥验签 | 不可否认性 | Signature |
| 密钥派生 | PBKDF2、HKDF | 主密钥/口令 | 密钥隔离与扩展 | SecretKeyFactory |