我正在尝试使用Android 4.3中提供的Android密钥存储区提供程序来安全地保存私钥,然后使用此私钥来加密和解码数据。
我认为到目前为止我已经实现了正确的方法和代码,但我目前面临一个我无法弄清楚的奇怪问题。
我有一个名为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”的别名,并尝试基于此创建和存储私钥。因此,您可以看到我尝试基于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”。
我找不到任何理由,在网上进行的研究证明是没有用的,所以我想知道是否有人知道可能会出现什么问题?
答案 0 :(得分:1)
为什么它是blueBirdKeyStore:
blueBirdKeyStorage.loadKeyStore();
不应该是:
keyStorage.loadKeyStore();
另外,你还没有使用别名&#39;在你的loadPrivateKey()中:
KeyStore.Entry entry = keyStore.getEntry(EnhancedCredentialStore.KEY_ALIAS, null);
现在,我不确定,但是你不应该使用&#39;别名&#39;在这?
答案 1 :(得分:1)
检查密钥是否存在的方法存在缺陷:
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.
答案 2 :(得分:0)
loadPrivateKey in your class does not use the "alias" to retrieve the key. It's using another class's constant so I'm not sure what's you're expecting here.