Android密钥库可以';t从共享首选项中解密字符串

Android密钥库可以';t从共享首选项中解密字符串,android,cryptography,android-keystore,Android,Cryptography,Android Keystore,我正在尝试使用密钥库对字符串进行加密,并将该字符串保存到共享首选项,然后在随后的应用程序启动时解密该字符串。然而,我相信我错过了重点 我主要基于以下链接: 我用另一篇文章写了这个包装器 然而,我找到的所有示例代码都在同一个应用程序运行期间进行加密和解密。这是没有用的。我需要加密我的字符串,保存在某个地方,然后在以后解密它。因此,此包装器尝试初始化密钥库,如下所示: @TargetApi(Build.VERSION_CODES.M) public KeyStoreHelper(boolean

我正在尝试使用密钥库对字符串进行加密,并将该字符串保存到共享首选项,然后在随后的应用程序启动时解密该字符串。然而,我相信我错过了重点

我主要基于以下链接:

我用另一篇文章写了这个包装器

然而,我找到的所有示例代码都在同一个应用程序运行期间进行加密和解密。这是没有用的。我需要加密我的字符串,保存在某个地方,然后在以后解密它。因此,此包装器尝试初始化密钥库,如下所示:

@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;
}
最后,我用以下方法运行一次:

testKeystoreHelper(true);
我退出应用程序,并使用以下命令再次运行:

testKeystoreHelper(true);
testkeystrehelper(false)

但这根本不起作用,让我:

E/Error: java.io.IOException: Error while finalizing cipher at
javax.crypto.CipherInputStream.fillBuffer(CipherInputStream.java:104)
因为每次应用程序启动时,尽管键名相同,但这些对总是不同的:

KeyPair keyPair = keyPairGenerator.generateKeyPair();
因为我每次都在初始化密钥。但是,我怎样才能在不初始化密钥对的情况下获取密钥对呢

所以我错过了要点,长话短说,有人能告诉我下面的基本算法吗

  • 初始化密钥库
  • 买双
  • 对字符串加密并保存到首选项
  • 退出应用程序
  • Init密钥库获取用于解密的正确密钥对
  • 从首选项获取加密字符串
  • 将其解密到内存中
  • 我不知道如何使用两个不同的应用程序发布来实现这一点。我总是在同一个应用程序中找到加密和解密代码


    谢谢大家!

    正如您在问题中指出的,您需要从密钥库恢复密钥,而不是每次都初始化密钥

    使用此代码加载
    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();