KeyStore没有为我的别名找到密钥

时间:2017-05-17 16:09:37

标签: android android-keystore

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

谢谢!

2 个答案:

答案 0 :(得分:2)

来自Sonic的答案是正确的,因为您用于对应用进行签名的Java Key Store与您在应用中使用的KeyStore不同。前者是您的开发机器(您的笔记本电脑)上的文件,而后者仅在您安装应用程序的手机上(Android手机或模拟器)。对您的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.

答案 1 :(得分:1)

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