KeyStore 找不到我的别名的密钥

KeyStore no key found for my alias

我正在尝试使用 this gist 加密我应用中的一些数据。

我已经用别名“Pablo”签署了我的 apk。 问题是尝试 运行 此代码:

public static String encrypt(String alias, String plaintext) {
    try {
        PublicKey publicKey = getPrivateKeyEntry(alias).getCertificate().getPublicKey();
        Cipher cipher = getCipher();
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return Base64.encodeToString(cipher.doFinal(plaintext.getBytes()), Base64.NO_WRAP);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

private static KeyStore.PrivateKeyEntry getPrivateKeyEntry(String alias) {
    try {
        KeyStore ks = KeyStore
                .getInstance("AndroidKeyStore");
        ks.load(null);
        KeyStore.Entry entry = ks.getEntry(alias, null);

        if (entry == null) {
            Log.w(TAG, "No key found under alias: " + alias);
            Log.w(TAG, "Exiting signData()...");
            return null;
        }

        if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
            Log.w(TAG, "Not an instance of a PrivateKeyEntry");
            Log.w(TAG, "Exiting signData()...");
            return null;
        }
        return (KeyStore.PrivateKeyEntry) entry;
    } catch (Exception e) {
        Log.e(TAG, e.getMessage(), e);
        return null;
    }
}

但我遇到异常:“在别名下找不到密钥”

有什么想法吗?我必须输入与我的 jks 相同的别名吗?

谢谢!

您在应用程序中请求的密钥库与用于签署应用程序的本地密钥库不同:您可以通过调用 ks.containsAlias(alias) 来检查。您必须在运行时密钥库中提供别名。您必须为您的别名创建一个条目:setEntry(String alias, KeyStore.Entry entry, KeyStore.ProtectionParameter protParam) (Saves a keystore Entry under the specified alias.)

来自 Sonic is correct in that the Java Key Store 的您用于签署应用程序的答案与您在应用程序中使用的 KeyStore 不同。前者是您的开发机器(您的笔记本电脑)上的文件,而后者仅在您安装应用程序的手机上(Android phone 或模拟器)。签署您的 apk 以便它可以在 Play 商店上发布和加密用户数据上的私人数据是不同的过程。

在不清楚的情况下,您应该尝试参考规范来源,而不是质量参差不齐的任意要点和教程。在这种情况下,official Android documentation for KeyStore 有一个完整的存储密钥的例子。请注意,Gist 中引用的 Android KeyStore 仅适用于 API 18+。

诚然,官方文档和Gist中的代码示例相当复杂,很容易出错。更好的选择可能是像 Scytale 这样的东西。它是 KeyStore 的包装器,可以正确处理 API < 18 的情况。下面是一个代码片段来演示:

Store store = new Store(getApplicationContext());
if (!store.hasKey("test")) {
   SecretKey key = store.generateSymmetricKey("test", null);
}
...

// Get key
SecretKey key = store.getSymmetricKey("test", null);

// Encrypt/Decrypt data
Crypto crypto = new Crypto(Options.TRANSFORMATION_SYMMETRIC);
String text = "Sample text";

String encryptedData = crypto.encrypt(text, key);
Log.i("Scytale", "Encrypted data: " + encryptedData);

String decryptedData = crypto.decrypt(encryptedData, key);
Log.i("Scytale", "Decrypted data: " + decryptedData);

请注意,无论主机上的 .jks 状态如何,您仍然需要创建密钥来加密数据。示例中的代码是正确的:

if there is no key in the keystore with that alias
    make a new key with that alias
use the key to encrypt and decrypt data.