当前位置: 首页 > 编程笔记 >

Android使用KeyStore对数据进行加密的示例代码

裴英锐
2023-03-14
本文向大家介绍Android使用KeyStore对数据进行加密的示例代码,包括了Android使用KeyStore对数据进行加密的示例代码的使用技巧和注意事项,需要的朋友参考一下

谈到 Android 安全性话题,Android Developers 官方网站给出了许多很好的建议和讲解,涵盖了存储数据、权限、网络、处理凭据、输入验证、处理用户数据、加密等方方面面

密钥的保护以及网络传输安全 应该是移动应用安全最关键的内容。Android 提供大量用来保护数据的加密算法,例如 Cipher 类中提供了 AES 和 RSA 算法,再例如安全随机数生成器 SecureRandom 给 KeyGenerator 提供了更加可靠的初始化参数,避免离线攻击等等。

而如果需要存储密钥以供重复使用,Android 提供了 KeyStore 等可以长期存储和检索加密密钥的机制,Android KeyStore 系统特别适合于存储加密密钥。”AndroidKeyStore” 是 KeyStore 的一个子集,存进 AndroidKeyStore 的 key 将受到签名保护,并且这些 key 是存在系统里的,而不是在 App 的 data 目录下,依托于硬件的 KeyChain 存储,可以做到 private key 一旦存入就无法取出,总之,每个 App 自己创建的 key,别的应用是访问不到的。

KeyStore 提供了两个能力:

有了这两个能力,我们的密钥保护就变得很容易了,你只需要:

在应用安装后第一次运行时,生成一个随机密钥,并存入 KeyStore

当你想存储一个数据,便从 KeyStore 中取出之前生成的随机密钥,对你的数据进行加密,加密完成后,已完成加密的数据可以随意存储在任意地方,比如 SharePreferences,此时即使它被他人读取到,也无法解密出你的原数据,因为他人取不到你的密钥

当你需要拿到你的原数据,只需要从 SharePreferences 中读取你加密后的数据,并从 KeyStore 取出加密密钥,使用加密密钥对 “加密后的数据” 进行解密即可

其中加密算法可以使用 Cipher AES 来保证安全性,不要使用自己创造的加密算法。

这就是使用 KeyStore 的一整套流程,另外 KeyStore 还可以用来做数据签名和签名验证,就像一个黑匣子一样,具体可以自行搜索了解。

KeyStore 适于存储运行时生产获取到的数据,比如运行时,用户输入的密码,或者服务端传下来的 token,但无法用于存储我们需要预设在 App 内的 API key / secret,对于这类需要预设的固定密钥,我将介绍一种十分安全、难破解的保护方式。

加密:

public String encryptString(String needEncryptWord, String alias) {
    if(!"".equals(alias)&&!"".equals(needEncryptWord)){
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
        initKeyStore(alias);
      }
      String encryptStr="";
      byte [] vals=null;
      try {
        KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
//      RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();
        if(needEncryptWord.isEmpty()) {
//        Toast.makeText(this, "Enter text in the 'Initial Text' widget", Toast.LENGTH_LONG).show();
          return encryptStr;
        }

//      Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
        Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//      inCipher.init(Cipher.ENCRYPT_MODE, publicKey);
        inCipher.init(Cipher.ENCRYPT_MODE, privateKeyEntry.getCertificate().getPublicKey());

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        CipherOutputStream cipherOutputStream = new CipherOutputStream(
            outputStream, inCipher);
        cipherOutputStream.write(needEncryptWord.getBytes("UTF-8"));
        cipherOutputStream.close();

        vals = outputStream.toByteArray();
      } catch (Exception e) {
        e.printStackTrace();
      }
      return Base64.encodeToString(vals, Base64.DEFAULT);
    }
    return "";
  }

解密:

public String decryptString(String needDecryptWord, String alias) {
    if(!"".equals(alias)&&!"".equals(needDecryptWord)){
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
        initKeyStore(alias);
      }
      String decryptStr="";
      try {
        KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
//      RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey();

//      Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
        Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//      output.init(Cipher.DECRYPT_MODE, privateKey);
        output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
        CipherInputStream cipherInputStream = new CipherInputStream(
            new ByteArrayInputStream(Base64.decode(needDecryptWord, Base64.DEFAULT)), output);
        ArrayList<Byte> values = new ArrayList<>();
        int nextByte;
        while ((nextByte = cipherInputStream.read()) != -1) {
          values.add((byte)nextByte);
        }

        byte[] bytes = new byte[values.size()];
        for(int i = 0; i < bytes.length; i++) {
          bytes[i] = values.get(i).byteValue();
        }

        decryptStr = new String(bytes, 0, bytes.length, "UTF-8");
      } catch (Exception e) {
        e.printStackTrace();
      }
      return decryptStr;
    }
    return "";
  }

源码下载地址,我已经将加密解密封装进了工具类,并对Android 7.0的兼容也处理了

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。

 类似资料:
  • 本文向大家介绍Android数据传输中的参数加密代码示例,包括了Android数据传输中的参数加密代码示例的使用技巧和注意事项,需要的朋友参考一下 Android开发中,难免会遇到需要加解密一些数据内容存到本地文件、或者通过网络传输到其他服务器和设备的问题,但并不是使用了加密就绝对安全了,如果加密函数使用不正确,加密数据很容易受到逆向破解攻击。还有很多开发者没有意识到的加密算法的问题。 1、数据传

  • 本文向大家介绍Android 使用密码以安全方式对数据进行AES加密,包括了Android 使用密码以安全方式对数据进行AES加密的使用技巧和注意事项,需要的朋友参考一下 示例 以下示例使用AES加密给定的数据块。加密密钥以安全的方式派生(随机盐,1000轮SHA-256)。加密使用具有随机IV的CBC模式下的AES。 请注意,存储在类数据EncryptedData(salt,iv,和encryp

  • 本文向大家介绍Yii 实现数据加密和解密的示例代码,包括了Yii 实现数据加密和解密的示例代码的使用技巧和注意事项,需要的朋友参考一下 在Yii中又很多的数据我们不能够以明文进行存储和展示,例如密码和一些比较重要的文件信息,这时候我们都需要我们对这些信息进行加密 一:对密码进行加密和验证客户端传输的密码是否正确 1:对密码进行加密 2:对客户端传递的密码进行验证,判断是否正确 二:生成一个伪随机数

  • 本文向大家介绍Python使用MD5加密算法对字符串进行加密操作示例,包括了Python使用MD5加密算法对字符串进行加密操作示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Python使用MD5加密算法对字符串进行加密操作。分享给大家供大家参考,具体如下: 输出结果: gxbdb684f1b8cfdf046744ea96d9fce48469fbac305dc6aa0d6operato

  • 问题内容: 有没有一个很好的示例,说明如何在Android上使用AES 加密和解密图像及其他文件? 问题答案: 并像这样调用它们: 这应该可行,我现在在项目中使用类似的代码。

  • 本文向大家介绍C#对文件进行加密解密代码,包括了C#对文件进行加密解密代码的使用技巧和注意事项,需要的朋友参考一下 加密代码 解密代码如下 以上所述就是本文的全部内容了,希望大家能够喜欢。