IT评测·应用市场-qidao123.com技术社区

标题: Android密钥库(AndroidKeyStore)使用 [打印本页]

作者: 没腿的鸟    时间: 2024-6-11 22:55
标题: Android密钥库(AndroidKeyStore)使用
一、KeyStore形貌

在 Android 开发中,KeyStore 是一个用于存储密钥和证书的安全容器。它提供了一种安全的方式来存储敏感信息,如密钥对、数字证书等,以防止它们被未授权的应用或攻击者访问。
KeyStore 通常用于加密数据、数字签名、TLS/SSL 连接等场景。

Android 开发中使用 KeyStore 的常见场景:
在 Android 中,KeyStore 是通过 java.security.KeyStore 类来实现的。可以使用该类来创建、加载、存储和检索密钥和证书。Android 提供了特定于 Android 平台的 KeyStore 实现,称为 AndroidKeyStore,它提供了更高级的安全功能,如硬件支持、密钥链随机生成等。
二、KeyStore使用

  1. // 密钥库类型
  2. private const val PP_KEYSTORE_TYPE = "AndroidKeyStore"
  3. // 密钥库别名
  4. private const val PP_KEYSTORE_ALIAS = "pp_keystore_alias"
  5. // 加密算法标准算法名称
  6. private const val PP_TRANSFORMATION = "RSA/ECB/PKCS1Padding"
复制代码
1. 生成公私钥密钥对

  1.     /**
  2.      * 触发生成密钥对.
  3.      *
  4.      * 生成RSA 密钥对,包括公钥和私钥
  5.      *
  6.      * @return KeyPair 密钥对,包含公钥和私钥
  7.      */
  8.     private fun generateKey(): KeyPair {
  9.         // 创建密钥生成器
  10.         val keyPairGenerator = KeyPairGenerator.getInstance(
  11.             KeyProperties.KEY_ALGORITHM_RSA,
  12.             PP_KEYSTORE_TYPE
  13.         )
  14.         // 配置密钥生成器参数
  15.         KeyGenParameterSpec.Builder(
  16.             PP_KEYSTORE_ALIAS,
  17.             KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
  18.         )
  19.             .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
  20.             .setDigests(KeyProperties.DIGEST_SHA256)
  21.             .build().run {
  22.                 keyPairGenerator.initialize(this)
  23.             }
  24.         // 生成密钥对
  25.         return keyPairGenerator.generateKeyPair()
  26.     }
复制代码
通过上述代码使用“AndroidKeyStore”范例的密钥库,生成 RSA 密钥对,包括公钥和私钥。
后续针对数据的加密息争密就必要使用此时密钥库中生成的 公钥和私钥。
2. AndroidKeyStore 密钥库得到密钥对

2.1 公钥

  1.     /**
  2.      * 获取公钥.
  3.      *
  4.      * @return 公钥
  5.      */
  6.     private fun getPublicKey(): PublicKey? {
  7.         val keyStore = KeyStore.getInstance(PP_KEYSTORE_TYPE).apply {
  8.             load(null)
  9.         }
  10.         // 判断密钥是否存在
  11.         if (!keyStore.containsAlias(PP_KEYSTORE_ALIAS)) {
  12.             return generateKey().public
  13.         }
  14.         val entry = keyStore.getEntry(PP_KEYSTORE_ALIAS, null)
  15.         if (entry !is KeyStore.PrivateKeyEntry) {
  16.             return null
  17.         }
  18.         return entry.certificate.publicKey
  19.     }
复制代码
2.2 私钥

  1.     /**
  2.      * 获取私钥.
  3.      *
  4.      * @return 密钥
  5.      */
  6.     private fun getPrivateKey(): PrivateKey? {
  7.         val keyStore = KeyStore.getInstance(PP_KEYSTORE_TYPE).apply {
  8.             load(null)
  9.         }
  10.         // 判断密钥是否存在
  11.         if (!keyStore.containsAlias(PP_KEYSTORE_ALIAS)) {
  12.             return generateKey().private
  13.         }
  14.         val entry = keyStore.getEntry(PP_KEYSTORE_ALIAS, null)
  15.         if (entry !is KeyStore.PrivateKeyEntry) {
  16.             return null
  17.         }
  18.         return entry.privateKey
  19.     }
复制代码
3. 加密、解密

3.1 加密

  1.     /**
  2.      * 数据加密.
  3.      *
  4.      * @param data 原始数据,字符串
  5.      * @return 加密数据,字节数组
  6.      */
  7.     fun encryptData(data: String): ByteArray {
  8.         return encryptDataInternal(data.toByteArray())
  9.     }
  10.     /**
  11.      * 数据加密.
  12.      *
  13.      * @param bytes 原始数据
  14.      * @return 加密数据
  15.      */
  16.     private fun encryptDataInternal(bytes: ByteArray): ByteArray {
  17.         return getPublicKey()?.run {
  18.             val cipher = Cipher.getInstance(PP_TRANSFORMATION)
  19.             cipher.init(Cipher.ENCRYPT_MODE, this)
  20.             cipher.doFinal(bytes)
  21.         } ?: byteArrayOf()
  22.     }
复制代码
3.2 解密

  1.     /**
  2.      * 数据解密.
  3.      *
  4.      * @param bytes 加密数据
  5.      * @return 原始数据,字符串
  6.      */
  7.     fun decryptData(bytes: ByteArray): String {
  8.         return String(decryptDataInternal(bytes))
  9.     }
  10.     /**
  11.      * 数据解密.
  12.      *
  13.      * @param bytes 加密数据
  14.      * @return 原始数据
  15.      */
  16.     private fun decryptDataInternal(bytes: ByteArray): ByteArray {
  17.         return getPrivateKey()?.run {
  18.             val cipher = Cipher.getInstance(PP_TRANSFORMATION)
  19.             cipher.init(Cipher.DECRYPT_MODE, this)
  20.             cipher.doFinal(bytes)
  21.         } ?: byteArrayOf()
  22.     }
复制代码
形貌下Cipher对象参数:
Cipher.getInstance(String transformation) 是用于获取 Cipher 对象的静态方法。它担当一个字符串参数 transformation,该参数指定了要使用的加密算法、模式和添补方式

3.3 加解密对象Clpher参数transformation介绍

transformation 参数的格式通常为 "algorithm/mode/padding",此中:

例如我们当前工具类,要使用 RSA 算法、ECB 模式和 PKCS5Padding 添补方式进行加密,你可以使用如下的 transformation 参数:
  1. private const val PP_TRANSFORMATION = "RSA/ECB/PKCS1Padding"
复制代码
然后调用 Cipher.getInstance(transformation) 方法来获取对应的 Cipher 对象,用于实行加密息争密操作。
在 Android 中,常见的加密算法和模式包括:


3.3.1 Android支持的transformation范例,参考Cipher文档:


Cipher  |  Android Developers

3.3.2 注意:padding使用OAEP添补方式

  1. private const val PP_TRANSFORMATION = "RSA/ECB/OAEPwithSHA-512andMGF1Padding"
复制代码
如果添补模式为OAEP,必要修改的代码如下
1. 密钥对生成必要修改代码

  1. // padding: 主要是生成KeySotre密钥对,填充模式:ENCRYPTION_PADDING_RSA_OAEP
  2. .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
  3. // mode: ECB
  4. .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
  5. // 消息摘要只支持512和256,OAEPwithSHA-512andMGF1Padding
  6. .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
复制代码
2. 加密必要修改代码

  1. /**
  2.      * 数据加密.
  3.      *
  4.      * @param bytes 原始数据
  5.      * @return 加密数据
  6.      */
  7.     private fun encryptDataInternal(bytes: ByteArray): ByteArray {
  8.         return getPublicKey()?.run {
  9.             val cipher = Cipher.getInstance(TRANSLATOR_TRANSFORMATION)
  10.             cipher.init(
  11.                 Cipher.ENCRYPT_MODE, this,
  12.                 OAEPParameterSpec(
  13.                     "SHA-512",
  14.                     "MGF1",
  15.                     MGF1ParameterSpec.SHA1,
  16.                     PSource.PSpecified.DEFAULT
  17.                 )
  18.             )
  19.             cipher.doFinal(bytes)
  20.         } ?: byteArrayOf()
  21.     }
复制代码
注意


Android平台在使用RSA/ECB/OAEPWithSHA-256AndMGF1Padding加密模式时,对MGF1摘要算法的支持存在一些限制。

提示:正常我们必要对加密的数据进行本地存储,上述加密数据是ByteArray,字节数组不太适合本地存储,因此我们可以通过Base64将ByteArray数据转换为字符串进行生存,取出数据之时再做Base64解码。
  1. // ByteArray转Base64字符串
  2. Base64.encodeToString(encryptedBytes, Base64.DEFAULT)
  3. // Base64字符串转ByteArray
  4. Base64.decode(encryptedString, Base64.DEFAULT)
复制代码

到此为止,基本的使用和简朴的参数形貌已经完成。
4. 完备代码

  1. object KeyStoreHelper {    // 密钥库范例    private const val PP_KEYSTORE_TYPE = "AndroidKeyStore"    // 密钥库别名    private const val PP_KEYSTORE_ALIAS = "pp_keystore_alias"    // 加密算法标准算法名称    private const val PP_TRANSFORMATION = "RSA/ECB/PKCS1Padding"    /**     * 数据加密.     *     * @param data 原始数据,字符串     * @return 加密数据,字节数组     */    fun encryptData(data: String): ByteArray {        return encryptDataInternal(data.toByteArray())    }    /**     * 数据解密.     *     * @param bytes 加密数据     * @return 原始数据,字符串     */    fun decryptData(bytes: ByteArray): String {        return String(decryptDataInternal(bytes))    }    /**     * 数据加密.     *     * @param bytes 原始数据     * @return 加密数据     */    private fun encryptDataInternal(bytes: ByteArray): ByteArray {        return getPublicKey()?.run {            val cipher = Cipher.getInstance(PP_TRANSFORMATION)            cipher.init(Cipher.ENCRYPT_MODE, this)            cipher.doFinal(bytes)        } ?: byteArrayOf()    }    /**     * 数据解密.     *     * @param bytes 加密数据     * @return 原始数据     */    private fun decryptDataInternal(bytes: ByteArray): ByteArray {        return getPrivateKey()?.run {            val cipher = Cipher.getInstance(PP_TRANSFORMATION)            cipher.init(Cipher.DECRYPT_MODE, this)            cipher.doFinal(bytes)        } ?: byteArrayOf()    }    /**
  2.      * 获取公钥.
  3.      *
  4.      * @return 公钥
  5.      */
  6.     private fun getPublicKey(): PublicKey? {
  7.         val keyStore = KeyStore.getInstance(PP_KEYSTORE_TYPE).apply {
  8.             load(null)
  9.         }
  10.         // 判断密钥是否存在
  11.         if (!keyStore.containsAlias(PP_KEYSTORE_ALIAS)) {
  12.             return generateKey().public
  13.         }
  14.         val entry = keyStore.getEntry(PP_KEYSTORE_ALIAS, null)
  15.         if (entry !is KeyStore.PrivateKeyEntry) {
  16.             return null
  17.         }
  18.         return entry.certificate.publicKey
  19.     }    /**
  20.      * 获取私钥.
  21.      *
  22.      * @return 密钥
  23.      */
  24.     private fun getPrivateKey(): PrivateKey? {
  25.         val keyStore = KeyStore.getInstance(PP_KEYSTORE_TYPE).apply {
  26.             load(null)
  27.         }
  28.         // 判断密钥是否存在
  29.         if (!keyStore.containsAlias(PP_KEYSTORE_ALIAS)) {
  30.             return generateKey().private
  31.         }
  32.         val entry = keyStore.getEntry(PP_KEYSTORE_ALIAS, null)
  33.         if (entry !is KeyStore.PrivateKeyEntry) {
  34.             return null
  35.         }
  36.         return entry.privateKey
  37.     }    /**     * 触发生成密钥对.     *     * 生成RSA 密钥对,包括公钥和私钥     *     * @return KeyPair 密钥对,包罗公钥和私钥     */    private fun generateKey(): KeyPair {        // 创建密钥生成器        val keyPairGenerator = KeyPairGenerator.getInstance(            KeyProperties.KEY_ALGORITHM_RSA,            PP_KEYSTORE_TYPE        )        // 配置密钥生成器参数        KeyGenParameterSpec.Builder(            PP_KEYSTORE_ALIAS,            KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT        )            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)            .setDigests(KeyProperties.DIGEST_SHA256)            .build().run {                keyPairGenerator.initialize(this)            }        // 生成密钥对        return keyPairGenerator.generateKeyPair()    }}
复制代码



参考

1. Android 密钥库系统
2. Cipher API文档
3. AndroidKeyStoreRSACipherSpi源码
4. 加密参考官网地点




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4