Probably you should change your server approach to public key exchange and generate key separately on android device. This way would be much secure.
You must store private keys with a certificate in KeyStore
. Here are steps how you can achieve this:
Step 1. Decode the Base64 PKCS#8 to get an instance of PrivateKey:
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privateKey = kf.generatePrivate(ks);
Step 2. The case might be that your server sends a certificate with private key or PKCS#8 blob also contains the public key.
Step 3. If server does not send certificate, you'll need to generate certificate for private key. Here is example using BouncyCastle.
Step 4. Store key on KeyStore:
X509Certificate certificate = ... // get certificate for private key or generate
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
keystore.setKeyEntry("MyAlias", privateKey, null, new Certificate[] { certificate });
If you really have to transmit private key to device from server, more secure case might be following:
- Generate AES key on device.
- Get server's public key first.
- Wrap generated AES key using that public key.
- Transmit encrypted AES key to server.
- Decrypt encrypted AES key on server side using private key.
- Encrypt private key using AES key, and transfer it to device.
The question was updated, so updated answer:
If you have to keep public private keypair in the app, I'd recommend keeping bytes of key using Android NDK, and strongly obfuscating it.
However, if I were you, as obfuscation tools are expensive for strong Android C++ code encryption, I'd keep those static key on server side, not hardcoded inside app. Then I'd send static key to device using the steps I mentioned before using symmetric encryption.
But if you choose using NDK option, it's better than storing key on file or on Java code also, but not fully bulletproof. Once user opens the app, you can store the key retrieved from C++ code in KeyStore, so, you make sure it's safe.
So, if you want to go with fastest option for keeping private key secure inside app binary, go for NDK option, and in future you can obfuscate it. If you have time to do some server side arrangements for transmitting private key, then storing on keystore, then go for steps I wrote.
Here are few resources might help you for NDK:
https://androidsecurity.info/2016/12/15/storing-your-secure-information-in-the-ndk/
https://medium.com/@abhi007tyagi/storing-api-keys-using-android-ndk-6abb0adcadad/