Android-KeyStore安全的存储系统

在 Android 中,AndroidKeyStore 是一个安全的存储系统,用于存储加密密钥。它提供了一种安全的方式来生成、存储和管理密钥,而无需将密钥暴露给应用程序本身。以下是如何使用 AndroidKeyStore 的基本步骤和示例代码。

检查 AndroidKeyStore 是否可用

cpp 复制代码
AndroidKeyStore 在 Android API 18(Android 4.3)及以上版本中可用。确保你的应用支持这些版本。

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
    // AndroidKeyStore 不可用
    return;
}

完整 Java 示例

java 复制代码
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;

import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.Cipher;

public class AndroidKeyStoreExample {

    // 密钥库类型
    private static final String PP_KEYSTORE_TYPE = "AndroidKeyStore";
    // 密钥库别名
    private static final String PP_KEYSTORE_ALIAS = "pp_keystore_alias";
    // 加密算法标准名称
    private static final String PP_TRANSFORMATION = "RSA/ECB/PKCS1Padding";

    public static void main(String[] args) {
        try {
            // 创建 RSA 密钥对
            createRsaKeyPair(PP_KEYSTORE_ALIAS);

            // 获取公钥和私钥
            PublicKey publicKey = getPublicKey(PP_KEYSTORE_ALIAS);
            PrivateKey privateKey = getPrivateKey(PP_KEYSTORE_ALIAS);

            // 原始数据
            String originalText = "Hello, AndroidKeyStore!";
            System.out.println("Original Text: " + originalText);

            // 使用公钥加密数据
            byte[] encryptedData = encryptData(publicKey, originalText.getBytes(StandardCharsets.UTF_8));
            System.out.println("Encrypted Data: " + new String(encryptedData, StandardCharsets.UTF_8));

            // 使用私钥解密数据
            byte[] decryptedData = decryptData(privateKey, encryptedData);
            System.out.println("Decrypted Data: " + new String(decryptedData, StandardCharsets.UTF_8));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建 RSA 密钥对
     */
    public static void createRsaKeyPair(String alias) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
            KeyProperties.KEY_ALGORITHM_RSA, PP_KEYSTORE_TYPE
        );

        KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(
            alias,
            KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT
        )
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
            .build();

        keyPairGenerator.initialize(spec);
        keyPairGenerator.generateKeyPair();
    }

    /**
     * 获取公钥
     */
    public static PublicKey getPublicKey(String alias) throws Exception {
        KeyStore keyStore = KeyStore.getInstance(PP_KEYSTORE_TYPE);
        keyStore.load(null); // 加载 AndroidKeyStore

        return keyStore.getCertificate(alias).getPublicKey();
    }

    /**
     * 获取私钥
     */
    public static PrivateKey getPrivateKey(String alias) throws Exception {
        KeyStore keyStore = KeyStore.getInstance(PP_KEYSTORE_TYPE);
        keyStore.load(null); // 加载 AndroidKeyStore

        return (PrivateKey) keyStore.getKey(alias, null);
    }

    /**
     * 使用公钥加密数据
     */
    public static byte[] encryptData(PublicKey publicKey, byte[] data) throws Exception {
        Cipher cipher = Cipher.getInstance(PP_TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 使用私钥解密数据
     */
    public static byte[] decryptData(PrivateKey privateKey, byte[] encryptedData) throws Exception {
        Cipher cipher = Cipher.getInstance(PP_TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(encryptedData);
    }
}

代码说明

1. 创建 RSA 密钥对
  • 使用 KeyPairGeneratorKeyGenParameterSpec 创建一个 RSA 密钥对。
  • KeyGenParameterSpec.Builder 用于指定密钥的用途(加密和解密)、填充方式等配置。
2. 获取公钥和私钥
  • 公钥通过 KeyStore.getCertificate(alias).getPublicKey() 获取。
  • 私钥通过 KeyStore.getKey(alias, null) 获取。
3. 加密数据
  • 使用公钥和指定的加密算法(RSA/ECB/PKCS1Padding)对数据进行加密。
4. 解密数据
  • 使用私钥和相同的加密算法对加密后的数据进行解密。

运行结果

假设原始数据是 "Hello, AndroidKeyStore!",运行程序后会输出:

复制代码
Original Text: Hello, AndroidKeyStore!
Encrypted Data: [加密后的二进制数据]
Decrypted Data: Hello, AndroidKeyStore!

注意事项

  1. API 版本要求

    • AndroidKeyStore 支持 API 18 及以上版本。
    • 如果需要在更低版本中实现类似功能,可以考虑使用其他加密库(如 Bouncy Castle)。
  2. 异常处理

    • 在实际开发中,务必捕获并处理可能抛出的异常,例如:
      • KeyStoreException
      • NoSuchAlgorithmException
      • InvalidKeyException
      • IllegalBlockSizeException
      • BadPaddingException
  3. 安全性

    • 使用 setUserAuthenticationRequired(true) 可以要求用户认证(如指纹或 PIN 码)才能访问密钥。
    • 避免将敏感数据存储在内存中太久,减少泄露风险。
  4. 填充方式

    • PKCS1Padding 是常用的填充方式,但如果你需要更高的安全性,可以考虑更现代的填充方式(如 OAEP)。

通过以上代码和解释,你应该能够理解如何在 Android 应用中使用 AndroidKeyStore 来安全地生成密钥、加密和解密数据。如果有进一步的问题,请随时提问!

相关推荐
橙子199110161 小时前
Kotlin 中的作用域函数
android·开发语言·kotlin
zimoyin1 小时前
Kotlin 懒初始化值
android·开发语言·kotlin
枣伊吕波2 小时前
第六节第二部分:抽象类的应用-模板方法设计模式
android·java·设计模式
萧然CS2 小时前
使用ADB命令操作Android的apk/aab包
android·adb
优质网络系统领域创作者2 小时前
思科(Cisco ASA/Firepower)、华三(H3C)、华为(Huawei USG)防火墙 的基础配置
安全
AORO_BEIDOU2 小时前
防爆手机与普通手机有什么区别
人工智能·5g·安全·智能手机·信息与通信
码农飞哥2 小时前
互联网大厂Java求职面试实战:Spring Boot与微服务场景深度解析
java·数据库·spring boot·安全·微服务·消息队列·互联网医疗
AORO_BEIDOU4 小时前
遨游5G-A防爆手机:赋能工业通信更快、更安全
5g·安全·智能手机
Waitccy4 小时前
Linux 系统安全基线检查:入侵防范测试标准与漏洞修复方法
linux·运维·网络·安全·系统安全·等保
鸿蒙布道师5 小时前
宇树科技安全漏洞揭示智能机器人行业隐忧
运维·网络·科技·安全·机器学习·计算机视觉·机器人