【问题标题】:Save and Retrieve KeyPair in AndroidKeystore在 AndroidKeystore 中保存和检索 KeyPair
【发布时间】:2017-02-08 10:08:34
【问题描述】:

我需要生成一个 RSA 2048 密钥对,然后保存它,如果存在则恢复它。

此刻,我有这个:

SecureRandom random = new SecureRandom();
RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(keySize, RSAKeyGenParameterSpec.F4);
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "SC");
generator.initialize(spec, random);
return generator.generateKeyPair();

这很完美,但现在我尝试从 Android Keystore 保存并获取它,但我没有实现。我试过了:

String alias = "TESTINGKEY";
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
if (!keyStore.containsAlias(alias)) {
    SecureRandom random = new SecureRandom();
    RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(keySize, RSAKeyGenParameterSpec.F4);
    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "SC");
    generator.initialize(spec, random);
    return generator.generateKeyPair();
} else {
    Key key = keyStore.getKey(alias, null);
    if (key instanceof PrivateKey) {
        Certificate cert = keyStore.getCertificate(alias);
        return new KeyPair(cert.getPublicKey(), (PrivateKey) key);
    } else {
        return null;
    }
}

但无法正常工作,因为在应用程序的第二次运行时,密钥库不包含密钥对。

https://developer.android.com/training/articles/keystore.html?hl=es 中,我看到KeyGenParameterSpec 构建器有一个“别名”值,但RSAKeyGenParameterSpec 没有。

如何保存?

【问题讨论】:

    标签: android rsa android-keystore


    【解决方案1】:

    AndroidKeyStore 需要使用KeyGenParameterSpec.Builder 来生成密钥。也使用AndroidKeyStore 而不是SC。您可以使用以下代码

    生成密钥 (Android>=23)

    KeyPairGenerator kpg = KeyPairGenerator.getInstance(
                    KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
    
    kpg.initialize(new KeyGenParameterSpec.Builder(
                    alias,
                    KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
                    .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                    .setKeySize(keySize)
                    .build());
    
    KeyPair keyPair = kpg.generateKeyPair();
    

    加载密钥

    KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
    keyStore.load(null);
    KeyStore.Entry entry = keyStore.getEntry(alias, null);
    PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
    PublicKey publicKey = keyStore.getCertificate(alias).getPublicKey();
    

    【讨论】:

    • 我试过你发布的@pedrofb 但是,现在,当我尝试使用 keypair.getPrivateKey().getEncoded() 时,启动一个 nullPointerException,因为这个 getEnconded() 里面没有“任何东西”。
    • 无法访问存储在 Android Keystore 中的密钥的密钥材料。您可以使用密钥,但不能提取它们。这是一个安全限制
    • @Shudy 我的回答清楚吗?如果您需要提取私钥的内容您不能使用AndroidKeyStore,但您可以完美地使用它,并且是推荐的方式来保证它的安全。提取私钥以存储在文件中意味着您需要额外的安全措施
    • 是的,是的。但是我知道的问题是我需要将我的公钥(以字符串格式)发送到服务器,所以当我尝试获取公共的编码以转换为字符串时,它是空的。
    • 我指的是私钥。可以使用byte publickey[] = keyStore.getCertificate(alias).getPublicKey().getEncoded(); 访问公钥原始数据。您需要将其转换为 base64 以将其作为字符串发送到服务器
    【解决方案2】:

    另外回答 pedrofb 对于 SDK 您可以使用 KeyPairGeneratorSpec 而不是 KeyGenParameterSpec

    信息: https://developer.android.com/reference/android/security/KeyPairGeneratorSpec.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-24
      • 2021-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-07
      • 2011-03-22
      相关资源
      最近更新 更多