1

I am developing an android app, in which I have to use payload encryption. For this backend giving me a pre generated key pair (RSA Public and Private key) for encryption and decryption.

As of now I am keeping these 2 keys (RSA public and private) in string hardcoded, but everyone knows that it's not a secure way to do this.

So in this process, client will send the request encrypted using server's public key, and server will decrypt it using their own private key. And the response can be decrypted only by client's private key because it was encrypted by client's public key.

Note - RSA public & private key will be static for my app, and I want to manage it put in a secure place.

So the main problem is where should I keep that private key in my app. Key is static in my app because server people distribute it to mobile team. And we can not use our self generated private key.

So what can be the best way to secure this first time givin private key at client side.

I tired this link & this, but none suitable for me.

Happy coding :-)

Bajrang Hudda
  • 3,028
  • 1
  • 36
  • 63

2 Answers2

3

The app should generate its own key and then transmit the public key to the backend. Then the backend can encrypt data to send to the app. If encryption is needed in the other direction, the backend can also generate a key and transmit its public key to the app for encryption.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
2

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:

  1. Generate AES key on device.
  2. Get server's public key first.
  3. Wrap generated AES key using that public key.
  4. Transmit encrypted AES key to server.
  5. Decrypt encrypted AES key on server side using private key.
  6. 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/

Natig Babayev
  • 3,128
  • 15
  • 23
  • 1
    How I will get privateKeyBytes?? Again I have to keep hardcoded in my code. And transmitting the privateKeyBytes ofcourse not a good solution though. – Bajrang Hudda Feb 16 '18 at 06:38
  • 1
    @BajrangHudda if you're going to transmit Base64 encoded private key from server, you can decode that in your application. So, you get private key bytes. – Natig Babayev Feb 16 '18 at 06:50
  • 1
    Also, you've noted that the key pair will be given by backend in a separate file and I have to use these keys only in my app but at a secure place. So, you can get your private key bytes from that file which has been transmitted. – Natig Babayev Feb 16 '18 at 06:53
  • 1
    More secure case might be, you generate AES (or any symmetric) key on mobile device, then you get server's public key. After that you can wrap your AES key using server's public key. Then when you post encrypted AES key to server, you can encrypt private key using that AES key, and decrypt it on device. – Natig Babayev Feb 16 '18 at 06:55
  • 1
    I've updated my answer which has steps how you can achieve transferring private key using AES key. – Natig Babayev Feb 16 '18 at 07:00
  • @BajrangHudda and again, you don't have to keep private key bytes hardcoded in your code. – Natig Babayev Feb 16 '18 at 07:03
  • Thanks for explaining, but my concern is I am alrady having the private kyes given by backend (no transmission at all), and the problem is where to kept this private key? – Bajrang Hudda Feb 16 '18 at 09:52
  • @BajrangHudda, it depends... Can you tell me what is your intention with that keys on backend? What will they be used for? Because description of question is little bit different than actual question. I need to clarify use case of private key, so, I can say some practical answer for it. – Natig Babayev Feb 16 '18 at 10:06
  • Please read my updated question. – Bajrang Hudda Feb 16 '18 at 10:16
  • @BajrangHudda, so, RSA public & private key will be static for your app always? In that case 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. – Natig Babayev Feb 16 '18 at 10:35
  • But if you choose using NDK option, it's good choice 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. – Natig Babayev Feb 16 '18 at 10:36
  • 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 – Natig Babayev Feb 16 '18 at 10:39
  • Thanks for explaing so much dear, Let me do a bit reserch on it, or do you have any links that might help me to complete this. – Bajrang Hudda Feb 16 '18 at 10:48
  • @BajrangHudda I've updated answer with few links for NDK option. It should be pretty easy and fast, and as you should store bytes of public private keypair. – Natig Babayev Feb 16 '18 at 10:57
  • @BajrangHudda if my answer helps, I guess you can mark this as correct answer :) – Natig Babayev Feb 16 '18 at 10:59
  • I done with https://medium.com/@abhi007tyagi/storing-api-keys-using-android-ndk-6abb0adcadad/ this one, Is it secure enough to put our RSA Private key? – Bajrang Hudda Feb 19 '18 at 09:38
  • @BajrangHudda as I mentioned last time, the server approach should change to make it more and more secure. However, practically, NDK approach is much safer than keeping your RSA private key in Java code. So, yes, it's much more secure than storing private key in static java code. Also, to make this approach more secure, you can implement encrypt and decrypt methods inside c++ code, so, you never expose your private key out (unless you have different approach from server side). – Natig Babayev Feb 19 '18 at 09:43
  • What you say about android key store? May it be useful for this scenario? – Bajrang Hudda Feb 19 '18 at 09:45
  • Of course, it's useful. You can transfer your private key directly to key store either from C code, or through Java code, and safely use it. – Natig Babayev Feb 19 '18 at 09:46
  • One issue with KeyStore is that, it doesn't have direct NDK implementation, so, you have to anyway do it through reflection – Natig Babayev Feb 19 '18 at 09:47
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/165398/discussion-between-bajrang-hudda-and-natig-babayev). – Bajrang Hudda Feb 19 '18 at 09:47
  • So, basically you can transfer key to keystore from you c code, or just implement encrypt-decrypt methods in your c code – Natig Babayev Feb 19 '18 at 09:48