2. 密码学基础

在 Android Keystore 与密钥服务开发中,密码学原语并不是抽象的理论,而是直接决定密钥如何生成、如何存储、如何调用以及如何失效的工程基础。理解对称加密、非对称加密、哈希、消息认证码、数字签名与密钥派生之间的分工,才能在后续使用 KeyStore、KeyGenerator、KeyPairGenerator、Cipher、Mac、Signature 等 API 时做出正确选择。

一、核心原理:六类密码学原语的分工

密码学原语可以按“是否可逆”“是否使用密钥”“密钥是否成对”三个维度来区分。对称加密使用同一把密钥完成加密和解密,速度快,适合保护大量数据;非对称加密使用公钥和私钥成对工作,公钥可公开,私钥必须保密,适合密钥交换和身份验证;哈希函数把任意长度输入压缩成固定长度摘要,不可逆,用于完整性校验;消息认证码在哈希基础上加入共享密钥,既校验完整性又验证来源;数字签名用私钥签名、公钥验签,提供不可否认性;密钥派生则从一个主密钥或口令派生出多个用途不同的子密钥,避免密钥复用。

密码学原语:密钥、方向与用途 对称加密 AES / ChaCha20 同一密钥加解密 速度快,适合大数据 KeyGenerator + Cipher 非对称加密 RSA / ECC 公钥加密,私钥解密 速度慢,适合小数据 KeyPairGenerator + Cipher 哈希函数 SHA-256 / SHA-3 单向不可逆 固定长度摘要 MessageDigest 消息认证码 HMAC-SHA256 共享密钥 + 哈希 完整性 + 来源验证 Mac 数字签名 SHA256withECDSA 私钥签名,公钥验签 不可否认性 Signature 密钥派生 HKDF / PBKDF2 主密钥 → 子密钥 用途隔离,避免复用 SecretKeyFactory / HKDF 对称/非对称负责“保密”,哈希/MAC/签名负责“完整与认证”,KDF 负责“密钥管理”

二、方法流程:在 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 和签名解决认证与不可否认。

工程建议:在 Android Keystore 中,密钥本身不出安全硬件,应用只能通过句柄调用。因此,密钥派生和签名操作应尽量在 Keystore 内部完成,避免将原始密钥导出到应用内存。

四、误区与复盘:常见错误与纠正

  • 误区一:用哈希代替加密。哈希不可逆,不能用于需要还原明文的场景;若需保密,必须使用加密。
  • 误区二:用对称加密代替 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
复盘要点:密码学原语没有“万能算法”,只有“匹配场景的组合”。在 Android Keystore 开发中,先确定安全目标,再选择原语,最后通过 Keystore 约束密钥用途和生命周期,才能构建可审计、可维护的密钥服务体系。