在AndroidKeystore中保存和检索KeyPair

8
我需要生成一个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的构建器具有“alias”值,但在RSAKeyGenParameterSpec中没有。

我该如何保存它?

2个回答

14

在使用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();

是的,没错。但我现在遇到的问题是,我需要将我的公钥(以字符串格式)发送到服务器,所以当我尝试获取公钥的编码并转换为字符串时,它为空。 - Shudy
1
我指的是私钥。公钥原始数据可以使用byte publickey[] = keyStore.getCertificate(alias).getPublicKey().getEncoded();访问。您需要将其转换为base64格式,以便将其作为字符串发送到服务器。 - pedrofb
Shudy,你能检查一下吗? - pedrofb
kpg.generateKeyPair() 方法是否也会将生成的密钥存储到 alias 名称下的 "AndroidKeyStore" 中,还是需要使用其他方法来存储密钥?如果需要,应该如何操作?请给予建议。 - Ωmega
@Ωmega,密钥是在“AndroidKeyStore”内部生成的(即使使用硬件支持),并且可以使用alias恢复(无法提取私钥)。 - pedrofb
显示剩余6条评论

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,