Java Android安全地将字符串存储到密钥库中

Java Android安全地将字符串存储到密钥库中,java,android,cryptography,rsa,Java,Android,Cryptography,Rsa,我知道将字符串存储到密钥库是不安全的,但此时我需要它。我对密码学特别是非对称密码学非常陌生。 我尝试使用RSA算法在密钥库中存储字符串(和私钥)。这就是我到目前为止所做的,而且很有效,但这是最简单的方法吗 注意1:我只支持API 21及更新版本,所以我应该使用密钥库或密钥链吗? 注2:它在API 23 M上不起作用,它在将私钥强制转换为RSAPrivateKey时出错 public static final String TAG = KeyStoreManager.class.getName()

我知道将字符串存储到密钥库是不安全的,但此时我需要它。我对密码学特别是非对称密码学非常陌生。 我尝试使用RSA算法在密钥库中存储字符串(和私钥)。这就是我到目前为止所做的,而且很有效,但这是最简单的方法吗

注意1:我只支持API 21及更新版本,所以我应该使用密钥库或密钥链吗?

注2:它在API 23 M上不起作用,它在将私钥强制转换为RSAPrivateKey时出错

public static final String TAG = KeyStoreManager.class.getName();

static final String CIPHER_TYPE = "RSA/ECB/PKCS1Padding";
static final String CIPHER_PROVIDER = "AndroidOpenSSL";
public static final String PHRASE_ALIAS = "phrase";
public static final String ANDROID_KEY_STORE = "AndroidKeyStore";
public static final String MIHAIL_GUTAN_X500 = "CN=some name";


public static boolean setKeyStoreString(String fileName, String strToStore, String alias, Context context) {

    try {
        KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
        keyStore.load(null);

        int nBefore = keyStore.size();

        // Create the keys if necessary
        if (!keyStore.containsAlias(alias)) {

            Calendar notBefore = Calendar.getInstance();
            Calendar notAfter = Calendar.getInstance();
            notAfter.add(Calendar.YEAR, 1);

            KeyPairGenerator generator = KeyPairGenerator.getInstance(
                    KeyProperties.KEY_ALGORITHM_RSA, ANDROID_KEY_STORE);

            KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
                        .setAlias(alias)
                        .setKeyType(KeyProperties.KEY_ALGORITHM_RSA)
                        .setKeySize(2048)
                        .setSubject(new X500Principal(MIHAIL_GUTAN_X500))
                        .setSerialNumber(BigInteger.ONE)
                        .setStartDate(notBefore.getTime())
                        .setEndDate(notAfter.getTime())
                        .build();

            generator.initialize(spec);


            KeyPair keyPair = generator.generateKeyPair(); // needs to be here
            Log.v(TAG, "The keypair" + keyPair.toString());
        }
        int nAfter = keyStore.size();
        Log.v(TAG, "Before = " + nBefore + " After = " + nAfter);

        // Retrieve the keys
        KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, null);
        RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey();
        RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();

        Log.v(TAG, "private key = " + privateKey.toString());
        Log.v(TAG, "public key = " + publicKey.toString());

        // Encrypt the text
        String dataDirectory = context.getApplicationInfo().dataDir;
        String filesDirectory = context.getFilesDir().getAbsolutePath();
        String encryptedDataFilePath = filesDirectory + File.separator + fileName;

        Log.v(TAG, "strPhrase = " + strToStore);
        Log.v(TAG, "dataDirectory = " + dataDirectory);
        Log.v(TAG, "filesDirectory = " + filesDirectory);
        Log.v(TAG, "encryptedDataFilePath = " + encryptedDataFilePath);

        Cipher inCipher = Cipher.getInstance(CIPHER_TYPE, CIPHER_PROVIDER);
        inCipher.init(Cipher.ENCRYPT_MODE, publicKey);

        CipherOutputStream cipherOutputStream =
                new CipherOutputStream(
                        new FileOutputStream(encryptedDataFilePath), inCipher);
        cipherOutputStream.write(strToStore.getBytes("UTF-8"));
        cipherOutputStream.close();
        return true;
    } catch (NoSuchAlgorithmException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (NoSuchProviderException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (InvalidAlgorithmParameterException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (KeyStoreException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (CertificateException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (IOException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (UnrecoverableEntryException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (NoSuchPaddingException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (InvalidKeyException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    } catch (UnsupportedOperationException e) {
        Log.e(TAG, Log.getStackTraceString(e));
    }
    return false;
}
然后我检索字符串:

public static String getKeyStoreString(String fileName, String alias, Context context) {
    KeyStore keyStore;
    String recoveredSecret = "";
    String filesDirectory = context.getFilesDir().getAbsolutePath();
    String encryptedDataFilePath = filesDirectory + File.separator + fileName;
    try {
        keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
        keyStore.load(null);

        // Retrieve the keys
        KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)
                keyStore.getEntry(alias, null);
        RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey();

        Cipher outCipher = Cipher.getInstance(CIPHER_TYPE, CIPHER_PROVIDER);
        outCipher.init(Cipher.DECRYPT_MODE, privateKey);

        CipherInputStream cipherInputStream = new CipherInputStream(
                new FileInputStream(encryptedDataFilePath), outCipher);
        byte[] roundTrippedBytes = new byte[1000]; 
        int index = 0;
        int nextByte;
        while ((nextByte = cipherInputStream.read()) != -1) {
            roundTrippedBytes[index] = (byte) nextByte;
            index++;
        }
        recoveredSecret = new String(roundTrippedBytes, 0, index, "UTF-8");
        Log.e(TAG, "round tripped string = " + recoveredSecret);
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (UnrecoverableEntryException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (NoSuchProviderException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (NullPointerException e) {
        e.printStackTrace();
    }

    Log.e(TAG, "recovered: " + recoveredSecret);
    return recoveredSecret;
}

你凭什么认为它不安全?是什么让你认为你需要自己加密它?它是不安全的,因为它可以被提取出来,我不想这样,关于加密,我只是不知道密钥库是如何工作的,所以我自己这么做,有没有办法让密钥库这样做?据我所知,没有我的意思是有钥匙链,我不知道很多,但我知道这不是一个好的选择,如果你有一个秘密,你想为你的应用程序保密,只有它可以提取,但只有密码。它和密码一样安全。它已经加密了。您可以在密钥存储库中的密钥条目上输入第二个密码。好的,很高兴知道,谢谢。什么使您认为它不安全?是什么让你认为你需要自己加密它?它是不安全的,因为它可以被提取出来,我不想这样,关于加密,我只是不知道密钥库是如何工作的,所以我自己这么做,有没有办法让密钥库这样做?据我所知,没有我的意思是有钥匙链,我不知道很多,但我知道这不是一个好的选择,如果你有一个秘密,你想为你的应用程序保密,只有它可以提取,但只有密码。它和密码一样安全。它已经加密了。您可以在密钥库中的密钥条目上输入第二个密码。好的,很高兴知道,谢谢。