Working on remote logging system for android, I faced up with Google require not to send user information to remote system, as this violates section 4.3 of the Developer Distribution Agreement.
To solve this we need to send the data to our server encrypted.
It’s nice to encrypt it so even if someone sniff the traffic they will not be able to decrypt contents.
To provide such encryption we can use asymmetric algorithm like RSA, public key is stored inside the android application and used to encrypt the data sent to remote server, private key is stored on servicer side and used to decrypt the data.
But the problem with asymmetric algorithm is that generaly they can encrypt data length up to key size, so for RSA its 4096 bits, which is not good in our case, as our logs can be much longer.
Symmetric algorithms, like AES can encrypt practically unlimited ammount of data, but as the same key is used to encrypt and decrypt information, it’s easy to stole data while transmissing to server if one has access to app code, which is true for Android applications.
The often used solution is:
On Client Side:
Generate random AES key ( e.g 256 bits long)
Encrypt body with AES using generated key
Encrypt key with RSA using stored public key
Send encrypted key along with encrypted body
On Server Side
Decrypt key with RSA private key to get plain AES key
Decrypt body with plain AES key
Handle the request
Lets start from the client side:
Generate random AES key
Encrypt data with AES
Encrypt key using RSA
To generate RSA key-pair we can simply use great online service: Generate Key Online
We can store public key either in assets/resources/plain string
To unify reading key we can use InputStream as source, so it can be FileInputStream, ByteArrayInputStream or any other source:
Using public key, we can encrypt data
Now we have everything encrypted and we can send data to our API. Body will be send as base64 request body, encrypted key - as request header.