Android KeyStore的使用

在我们App开发过程中,可能会涉及到一些敏感和安全数据需要加密的情况,比如登录token的存储。我们往往会使用一些加密算法将这些敏感数据加密之后再保存起来,需要取出来的时候再进行解密。

此时就会有一个问题:用于加解密的Key该如何存储?

  • 如果把Key和加密后的数据存到一起,那有一定的安全风险。
  • 对Key再进行一次加密,这就陷入了死循环。

为了保证安全性,Android提供了KeyStore系统来保存Key,本文就浅探一下KeyStore及其使用方法。

一、什么是KeyStore?如何保证安全性?

1、什么是KeyStore?

先来看看官方对他的定义:

This class represents a storage facility for cryptographic keys and certificates.

这个类代表加密密钥和证书的存储设施

定义其实很简单,他就是用来保存加解密的Key和证书的。

2、如何保证安全性?

安全性保护措施在官方文档里有写(Android 密钥库系统 | Android 开发者 | Android Developers (google.cn)), 我就按自己的理解总结一下:

  • Key是保存在手机系统里的,应用进程在获取Key的时候是通过系统进程获取到内存里的。也就是说只能在本应用进程里才能拿到Key,想要把Key提取出来是不可能的。
  • KeyStore还可以指定密钥的授权使用方式(比如用户安全锁验证),可保证必须在授权的情况下才能获取到Key。

总的来说就是使用者只能在应用程序运行时使用KeyStore里存放的Key,除非攻击者拿到源码打断点调试,否则无法知道Key到底是什么。这样就保证了存储Key的安全性。

二、KeyStore的使用

KeyStore支持的加密算法有很多,其中对部分算法有API Level的要求,具体可以查看Android 密钥库系统 | Android 开发者 | Android Developers (google.cn)

本文就以AES加密算法为例,简单说明一下KeyStore的使用方式。注意,本文涉及到的代码需要minSdk>=23.

先简单实现一下AES算法的加解密

1、数据加密

object AESUtil {
   

    private const val IV_BLOCK_SIZE = 16

    fun encryptAES(encryptBytes: ByteArray, encryptKey: SecretKey): ByteArray?{
   
        try {
   
            //创建密码器
            val cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING")
            //用密钥初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, encryptKey)
            val final = cipher.doFinal(encryptBytes)
            // iv占前16位,加密后的数据占后面
            return cipher.iv + final
        } catch (e: NoSuchPaddingException) {
   
            e.printStackTrace()
        } catch (e: NoSuchAlgorithmException) {
   
            e.printStackTrace()
        } catch (e: InvalidAlgorithmParameterException) {
   
            e.printStackTrace()
        } catch (e: InvalidKeyException) {
   
            e.printStackTrace()
        } catch (e: BadPaddingException) {
   
            e.printStackTrace()
        } catch (e: IllegalBlockSizeException) {
   
            e.printStackTrace()
        }
        return null
    }

    fun decryptAES(decryptBytes: ByteArray, decryptKey: SecretKey): ByteArray? {
   
        try {
   
            // 先取出IV
            val iv = decryptBytes.copyOfRange(0, IV_BLOCK_SIZE)
            // 取出加密后的数据
            val decryptData = decryptBytes.copyOfRange(IV_BLOCK_SIZE, decryptBytes.size)
            val cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING")
            cipher.init(Cipher.DECRYPT_MODE, decryptKey, IvParameterSpec(iv))
            return cipher.doFinal(decryptData)
        } catch (e: NoSuchPaddingException) {
   
            e.printStackTrace()
        } catch (e: NoSuchAlgorithmException) {
   
            e.printStackTrace()
        } catch (e: InvalidAlgorithmParameterException) {
   
            e.printStackTrace()
        } catch (e: InvalidKeyException) {
   
            e.printStackTrace()
        } catch (e: BadPaddingException) {
   
            e.printStackTrace()
        } catch (e: IllegalBlockSizeException) {
   
            e
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值