我正在尝试使用密钥库来加密字符串,并将此字符串保存到共享首选项,然后在后续的子应用程序启动时解密字符串。然而,我相信我错过了密钥库的主要观点。
大多数情况下,我基于以下链接:
我使用另一个我从其他问题
发布的帖子编写了这个包装器java.lang.IllegalArgumentException: bad base-64 when decrypting string
然而,我在同一个App运行期间找到,加密和解密的所有示例代码。这永远不会有用。我需要加密我的字符串,保存在某处并在以后解密。所以这个包装器尝试初始化KeyStore:
@TargetApi(Build.VERSION_CODES.M)
public KeyStoreHelper(boolean encrypt) {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
if (encrypt) {
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(
MY_KEY_NAME_INSIDE_KEYSTORE,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.build());
} else {
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(
MY_KEY_NAME_INSIDE_KEYSTORE,
KeyProperties.PURPOSE_DECRYPT)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.build());
}
KeyPair keyPair = keyPairGenerator.generateKeyPair();
String provider = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? "AndroidOpenSSL" : "AndroidKeyStoreBCWorkaround";
if (encrypt) {
PublicKey publicKey = keyPair.getPublic();
mInCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
mInCipher.init(Cipher.ENCRYPT_MODE, publicKey);
} else {
PrivateKey privateKey = keyPair.getPrivate();
mOutCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
mOutCipher.init(Cipher.DECRYPT_MODE, privateKey);
}
} catch (Exception e) {
Log.e(ERROR_TAG, Log.getStackTraceString(e));
}
}
public static KeyStoreHelper getInstance(boolean encrypt) {
if (mKeyStoreHelperInstance == null) {
mKeyStoreHelperInstance = new KeyStoreHelper(encrypt);
}
return mKeyStoreHelperInstance;
}
然后我尝试加密一些字符串保存到首选项,如下所示
private SharedPreferences mSharedPreferences;
private void testKeystoreHelper(boolean encrypt) {
KeyStoreHelper keyStoreHelper;
initSharedPreferences();
final String sharedPreferencesAlias = "mysecret";
String plainText;
String secretString;
if (encrypt) {
plainText = "my secret string";
keyStoreHelper = KeyStoreHelper.getInstance(true);
secretString = keyStoreHelper.encrypt(plainText);
Log.v(TAG, "Encrypted = " + secretString);
mSharedPreferences.edit().putString(sharedPreferencesAlias, secretString).apply();
} else {
keyStoreHelper = KeyStoreHelper.getInstance(false);
secretString = mSharedPreferences.getString(sharedPreferencesAlias, null);
plainText = keyStoreHelper.decrypt(secretString);
Log.v(TAG, "Decrypted" + plainText);
}
}
最后我做了一次运行:
testKeystoreHelper(true);
我退出应用程序并再次运行:
testKeystoreHelper(假);
但这对我来说无效:
E/Error: java.io.IOException: Error while finalizing cipher at
javax.crypto.CipherInputStream.fillBuffer(CipherInputStream.java:104)
因为每次应用程序启动时虽然键名相同,但这些对总是不同的:
KeyPair keyPair = keyPairGenerator.generateKeyPair();
因为我每次都在初始化密钥。但是如果不初始化KeyPair,我怎么能得到KeyPair呢?
所以我错过了主要观点,长话短说,有人会引导我使用以下基本算法吗?
我不知道如何使用两个不同的应用程序启动来完成此操作。我总是在相同的应用程序运行中找到加密和解密的代码。
谢谢你!答案 0 :(得分:0)
正如您在问题中指出的那样,您需要从密钥库中恢复密钥,而不是每次都初始化密钥。
使用此代码加载AndroidKeyStore
并获取私钥
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.Entry entry = keyStore.getEntry(MY_KEY_NAME_INSIDE_KEYSTORE, null);
PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
如果已创建密钥,请勿生成密钥。检查是否存在
keyStore.containsAlias(MY_KEY_NAME_INSIDE_KEYSTORE);
使用
恢复公钥PublicKey publicKey = keyStore.getCertificate(MY_KEY_NAME_INSIDE_KEYSTORE).getPublicKey();