【问题标题】:KeyStore no key found for my aliasKeyStore 找不到我的别名的密钥
【发布时间】:2017-10-17 05:11:42
【问题描述】:

我正在尝试使用 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 相同的别名,对吗?

谢谢!

【问题讨论】:

  • 您是否尝试在命令行中列出密钥库别名?stackoverflow.com/a/12894334/1056359
  • 是的,别名没问题,我正在使用签名 apk 调试它
  • 异常发生在哪一行代码?确保您从运行应用程序的 jre 中使用正确的密钥库。使用的运行时 JRE 可能是不同的,包含不同的密钥库而没有您的别名。
  • 在这部分代码中:KeyStore.Entry entry = ks.getEntry(alias, null);
  • 我试图获取我的发行版 apk 并在我的设备上运行它,但 adb 工具却遇到了同样的错误

标签: android android-keystore


【解决方案1】:

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

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

不可否认,官方文档和Gist中的代码示例相当复杂,很容易出错。更好的选择可能是Scytale。它是 KeyStore 的包装器,可以正确处理 API

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.

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我不确定你的答案,我需要使用我的密钥库来加密数据,为什么我需要创建一个新的别名?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-03
    • 2017-02-26
    • 2022-01-24
    • 2015-05-11
    • 1970-01-01
    • 2014-06-17
    • 1970-01-01
    相关资源
    最近更新 更多