【问题标题】:How to store key using Android Key Store Provider如何使用 Android Key Store Provider 存储密钥
【发布时间】:2014-11-20 10:51:39
【问题描述】:

我正在尝试使用 Android 4.3 中提供的 Android Key Store Provider 来安全地保存私钥,然后使用此私钥加密和解码数据。

到目前为止,我认为我已经为此实施了正确的方法和代码,但是我目前面临一个我无法弄清楚的奇怪问题。

我有一个名为 KeyStorage 的类,用于创建密钥对、加载 KeyStore 并检索私钥,该类的代码如下:

public class KeyStorage {

public static final String ANDROID_KEYSTORE = "AndroidKeyStore";
private KeyStore keyStore;

public void loadKeyStore() {
    try {
        keyStore = KeyStore.getInstance(ANDROID_KEYSTORE);
        keyStore.load(null);
        Enumeration<String> aliases = keyStore.aliases();
        while(aliases.hasMoreElements())
            Log.e("E", "Aliases = " + aliases.nextElement());
    } catch (Exception e) {
        // TODO: Handle this appropriately in your app
        e.printStackTrace();
    }
}

public void generateNewKeyPair(String alias, Context context)
        throws Exception {

    Calendar start = Calendar.getInstance();
    Calendar end = Calendar.getInstance();
    // expires 1 year from today
    end.add(1, Calendar.YEAR);

    KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
            .setAlias(alias)
            .setSubject(new X500Principal("CN=" + alias))
            .setSerialNumber(BigInteger.TEN)
            .setStartDate(start.getTime())
            .setEndDate(end.getTime())
            .build();

    // use the Android keystore
    KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA", ANDROID_KEYSTORE);
    gen.initialize(spec);

    // generates the keypair
    gen.generateKeyPair();
}

public PrivateKey loadPrivteKey(String alias) throws Exception {

    if (keyStore.isKeyEntry(alias)) {
        Log.e("E", "Could not find key alias: " + alias);
        return null;
    }

    KeyStore.Entry entry = keyStore.getEntry(EnhancedCredentialStore.KEY_ALIAS, null);

    if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
        Log.e("E", " alias: " + alias + " is not a PrivateKey");
        return null;
    }

    return ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
}

然后我有一个名为 CredentialStore 的类,我尝试在其中使用它。我创建了一个名为“MySecureKey”的别名,并尝试基于此创建和存储私钥。如您所见,我尝试根据别名创建新的密钥对,加载密钥库,然后最终检索私钥。但是它不起作用。

public class CredentialStore {

public static final String KEY_ALIAS  = "MySecureKey";

private KeyStorage KeyStorage;

public CredentialStore(Activity context){

    keyStorage = new KeyStorage();
    try {
        keyStorage.generateNewKeyPair(KEY_ALIAS, context);
    } catch (Exception e) {
        e.printStackTrace();
    }
    blueBirdKeyStorage.loadKeyStore();

    try {
        keyStorage.loadPrivteKey(KEY_ALIAS);
    } catch (Exception e) {
        e.printStackTrace();
    }

}

我得到的日志如下:

Aliases = MySecureKey
Could not find key alias: MySecureKey

因此,当我检查 loadKeyStore 方法中的别名时,它看起来就在那里,因为它正在返回日志中。但是,当我尝试使用 loadKeyStore 方法调用它时,我得到日志说它找不到密钥“MySecureKey”。

我找不到任何原因,并且在线研究被证明是徒劳的,所以我想知道是否有人知道可能出了什么问题?

【问题讨论】:

  • 1.您生成 KeyPair 并且不使用它。您的 generateNewKeyPair 方法不返回任何内容。 2. 您不会将任何内容保存到 KeyStore 以便稍后加载。请参阅有关 KeyStore 使用的示例。它可能会帮助你developer.android.com/samples/BasicAndroidKeyStore/index.html
  • @AlexanderZhak 尽管有很多支持,但您的评论是错误的:查看官方文档:developer.android.com/training/articles/… 这就是您使用 Android 密钥库的方式 - 如果您使用,则无需明确放置密钥带有 Android Keystore 实例的 KeyFactory。

标签: android encryption private-key android-keystore


【解决方案1】:

为什么是blueBirdKeyStore在:

blueBirdKeyStorage.loadKeyStore();

不应该是:

keyStorage.loadKeyStore();

另外,您还没有在 loadPrivateKey() 中使用“别名”:

KeyStore.Entry entry = keyStore.getEntry(EnhancedCredentialStore.KEY_ALIAS, null);

现在,我不确定,但您不应该在其中使用“别名”吗?

【讨论】:

    【解决方案2】:

    您的类中的loadPrivateKey 不使用“别名”来检索密钥。它正在使用另一个类的常量,所以我不确定你在这里期待什么。

    【讨论】:

      【解决方案3】:

      您检查密钥是否存在的方法有缺陷:

      if (keyStore.isKeyEntry(alias)) {
          Log.e("E", "Could not find key alias: " + alias);
          return null;
      }
      

      根据 javadoc .isKeyEntry() 具有以下行为

      如果给定别名标识的条目是由 调用 setKeyEntry,或通过调用 setEntry 创建 PrivateKeyEntry 或 SecretKeyEntry。

      但您的密钥不是通过setEntry() 创建的。我想如果你只是用

      加载密钥
      KeyStore.Entry entry = ks.getEntry(alias, null);
      

      它不会为空。

      Here is a full example with simple methods on how to use the Android Keystore with pre-M and M Apis.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-09
        • 2021-03-16
        • 2013-02-05
        • 2019-12-24
        • 2020-02-01
        • 1970-01-01
        • 2023-01-26
        • 1970-01-01
        相关资源
        最近更新 更多