添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Android的KeyStore保护数据

Android的KeyStore保护数据

有知友问我keystore的知识,我们先看谷歌文档对安卓中keystore的解释:

Android Keystore系统可让您将加密密钥存储在容器中,以使其更难从设备中提取。一旦密钥进入密钥库,就可以将其用于加密操作,而密钥材料仍不可导出。而且,它提供了限制何时和如何使用密钥的功能,例如要求用户进行身份验证才能使用密钥,或者限制仅在某些加密模式下使用密钥。

让我们先清除一些有关Android Keystore系统的知识。密钥库不一定只用于密码,它可以用于任何敏感数据,这样做的方式使攻击者或恶意/未经授权的软件很难从我们这里获取此信息。

简单来说:应用程序只能编辑,保存和检索 自己的 密钥。

这个概念很简单,但功能强大。该应用将生成或接收私钥-公钥对,然后将其存储在Android Keystore系统中。

然后,在将公用密钥存储在特定于应用程序的文件夹中之前,可以使用公用密钥对应用程序秘密进行加密,并在需要时使用专用密钥对相同信息进行解密。

同样是这样几个步骤:

  • 创建秘钥
  • 加密数据
  • 解密数据

1、创建秘钥:

在开始加密过程之前,我们需要为要用来加密/解密数据的别名提供一个名称。可以是任何字符串。只要不是一个空的。别名是生成的密钥将出现在Android KeyStore中的条目的名称。

final KeyGenerator keyGenerator = KeyGenerator
        .getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

此密钥生成器的算法将是AES,并且我们要将密钥/数据保存在 AndroidKeyStore中。

那么这个KeyGenParameterSpec到底是什么?

您可以将KeyGenParameterSpec视为我们将要生成的键的属性。例如,假设我们希望密钥在一定时间后过期,这就是我们要指定的地方。

他是我们的KeyGenParameterSpec。

final KeyGenerator keyGenerator = KeyGenerator
        .getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(alias,
        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
       .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
        .build();

第一件事是我们传入我们要使用的别名。接下来,我们指定目的,即 加密 解密 数据。

由于我们使用的是 “ AES / GCM / NoPadding” 转换算法,因此我们还告诉KeyGenParameterSpec应该使用的填充类型。

2、加密数据

final KeyGenerator keyGenerator = KeyGenerator
        .getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(alias,
        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
       .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
        .build();
keyGenerator.init(keyGenParameterSpec);
final SecretKey secretKey = keyGenerator.generateKey();
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);

现在我们有了密钥,我们将使用它来初始化我们的cipher对象,这将负责实际的加密。我们告诉Cipher我们将要使用的加密转换的类型,我们指定我们现在要进行加密,然后传入secretKey进行加密。

final KeyGenerator keyGenerator = KeyGenerator
        .getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(alias,
        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
        .build();
keyGenerator.init(keyGenParameterSpec);
final SecretKey secretKey = keyGenerator.generateKey();
final Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
iv = cipher.getIV();
encryption = cipher.doFinal(textToEncrypt.getBytes("UTF-8"));

接下来,我们获取解密所需的密码 初始化向量(IV) 的引用,并使用 doFinal(textToEncrypt) 完成加密。doFinal方法返回一个字节数组,它是实际的加密文本。

3、解密数据

先获取keystore实例:

keyStore =getInstance(“ AndroidKeyStore ”); 
keyStore.loadnull;

获取secretKey。

keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore
        .getEntry(alias, null);
final SecretKey secretKey = secretKeyEntry.getSecretKey();

我们需要一个GCMParameterSpec指定身份验证标签的长度,并传入我们在加密过程中较早时获取的IV来解密。

keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore