如何使用Android密钥存储提供程序存储密钥
我想使用Android 4.3中可用的Android密钥存储提供程序来安全地保存私钥,然后使用此私钥来加密和解码数据。如何使用Android密钥存储提供程序存储密钥
我想我已经实现了正确的方法和代码,但目前我面临着一个奇怪的问题,我无法弄清楚。
我有一个叫KeyStorage类,我用它来创建密钥对,加载密钥库和检索私钥,这个类的代码如下:
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”的别名,并尝试在此基础上创建和存储私钥。正如你所看到的,我尝试基于Alias加载密钥库来创建新的密钥对,然后最终检索私钥。但它不起作用。
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”。
我找不到任何理由和网上研究已证明无果,所以我想知道如果有人有任何想法可能会出错?
为什么blueBirdKeyStore在:
blueBirdKeyStorage.loadKeyStore();
它不应该是:
keyStorage.loadKeyStore();
此外,你还没有使用的 '别名' 在你loadPrivateKey():
KeyStore.Entry entry = keyStore.getEntry(EnhancedCredentialStore.KEY_ALIAS, null);
现在,我不确定,但是不应该在此使用'别名'吗?
你的类中的loadPrivateKey不使用“别名”来检索密钥。它使用了另一个课程的常量,所以我不确定你在这里期待什么。
不,它使用正确的别名。 – for3st 2016-09-22 08:08:01
你的方法来检查,如果你的键值存在是有缺陷的:
if (keyStore.isKeyEntry(alias)) {
Log.e("E", "Could not find key alias: " + alias);
return null;
}
根据javadoc的.isKeyEntry()
有以下行为
返回true,如果给定别名标识的条目是通过创建 调用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.
1.您生成KeyPair并且不使用它。您的generateNewKeyPair方法不会返回任何内容。 2.您不会将任何内容保存到KeyStore以稍后加载它。请参考KeyStore使用示例。它可以帮助你http://developer.android.com/samples/BasicAndroidKeyStore/index.html – 2014-09-25 16:25:48
@AlexanderZhak尽管许多upvotes,你的评论是错误的:检查官方文档:https://developer.android.com/ training/articles/keystore.html#UserAuthentication这就是您如何使用Android Keystore--如果您将KeyFactory与Android Keystore实例一起使用,则不需要明确地放置该密钥。 – for3st 2016-09-21 11:51:22