I should develop an phonegap application. I need to encrypt my requests to the server side and then decrypt.
HTTPS is not a solution, because I need to sign requests to be sure that the data is not fake. I can use any async cryptography (the app will generate private/public keys and will send public key to the server). But this way I need to keep my private key on the device.
The question is: how I can keep private key on the device securely?
I can use sqlclipher (to encrypt my local SQLite DB) and integrate it into my phonegap app. Great, but here I have to keep secret key for database :)
var db = window.sqlitePlugin.openDatabase({name: "DB", key: "secret1"});
Any one who have access to the phone can get this secret key. So here I have the same issue:)
Please, give me any suggestions.
Thanks!
p.s. app for iOS and Android
You have to differentiate between encryption and authentication.
First, I suggest to use https to encrypt your messages and transfer them securely.
Second, I suggest to use HMAC for authentication of your messages. It basically works like this:
Generate a secret string known to your app and the server at compile time. You store this secret directly in the source code of your app so it is never transmitted to or from the server. This might be the main difference to your private/public key approach: You compile the secret right into your app instead of writing it later in some user accessible storage. "Right into your app" means in the case of Phonegap NOT in your HTML/JS files but in the native source code! You have to bridge the accessor to javascript if necessary.
Set a user id (=key; long, random!) in your app when the user starts your app for the first time. If you want to authenticate your users, you probably have some kind of login/password mechanism. (Store the user id as well as an HMAC generated from the user id and the shared secret on the device. Every time you read the user id, check it against the hash to be sure that the user id was not spoofed.)
In your App
Include a user id in every message.
Include a timestamp in every message.
Calculate the HMAC hash from a string put together from the message, the server address, the request URI, and the shared secret.
Include the hash value in your request header.
On the server side
Check if the timestamp is valid, e. g. not older than 2 minutes or so. This prevents replay attacks (at least after 2 minutes).
Check in your database if the user id is valid.
Calculate the HMAC hash from a string put together from the message, the server address, the request URI, and the shared secret. Including the request URI prevents people to send the same valid request to another URI on your server; e. g. in REST environments it is a big difference if you send the same DELETE request to /comment/1 or /user/1.
Compare it to the hash value submitted in your header, they have to be equal.
If any check fails, send an error. Otherwise send the response.
There is a chance of getting the shared secret and information about the way how you calculate the HMAC hash by decompiling your source code. I see no way to avoid this risk. ...without diving deeper into native development:
iOS Keychain
https://developer.apple.com/library/ios/documentation/Security/Conceptual/keychainServConcepts/iPhoneTasks/iPhoneTasks.html
Android security features
http://developer.android.com/training/articles/security-tips.html
By default, PhoneGap does not provide the feature of encryption on its own. Devices based on iOs and Android(above Gingerbread version) support full-disk encryption. But this is not available to PhoneGap/Cordova developers.
From the wiki:
PhoneGap is generally limited to the security features of the platform
on which it is running.
Refer to https://github.com/phonegap/phonegap/wiki/Platform-Security
For some JS based solution, give a try at http://code.google.com/p/crypto-js/
Related
I am learning how to build android apps. I'm building my first app using PHP and Java, i'm passing the values from Java to PHP using parameters.
localhost/myfile.php?id=GET ID FROM JAVA EDITBOX&name=GET NAME FROM JAVA EDITBOX
I'm inserting and updating using this method.
But i'm afraid about my app security, how can i hide my links? I would like to insert some security technics to prevent a common user from having the access to my links, and insert random data into my database.
I'm sorry about that noob question, but i would like to read more about that.
how can i hide my links
No way because APK file can be de-compiled
I would like to insert some security technics to prevent a common user
from having the access to my links, and insert random data into my
database.
You are allowing Un-authenticated users to insert the records??? If you are doing this, you are doing it wrong (I think)
You should allow Authenticated Users to Insert/Delete/Update records and
Un-authenticated users can Load data only.
Some Security Practices:
Authentication (Login) / Authorization (Permission)
Don't trust any data sent from client --> Data Validation at Server side is required
Use Asymmetric encryption - Public/Private key
Encrypt your data at client side using Public key
Decrypt the data at Server side using Private key
Apply Digital Signature OR MAC (Message Authentication Code) to make sure your data is Integrity & Authentication
Https used
I am deciding the mechanism to protect Android App and data. I did some research, but don't know if below solutions are enough or not. See if any expert can provide me some advice:
For SQLite database-level protection: Use SQLCipher
For SQLite data-level protection: Use AES256 to encrypt and decrypt (But don't know where to store the secret key is better?)
For Android data to Web Service(PHP): Use SSL and Post method
For Web Service(PHP) Json to Android: Use SSL and Post method
To prevent Android APK to re-engineering: Use Proguard
To make Web Service(PHP) can only access by the Android app: Hard-code a secret key inside the app, send it in HEAD with SSL everytime to the server. Or use android application licensing?
Thanks!!!
For SQLite database-level protection: Use SQLCipher
Correct.
For SQLite data-level protection: Use AES256 to encrypt and decrypt (But don't know where to store the secret key is better?)
You could but it might not be that necessary since SQLCipher already do the job on data protection in database-level. But if you do want to do double encryption, AES256 could do the job for you. Store the key somewhere that is hard to decode: ndk or in Java code. But don't forget to encrypt secret key as well. Decrypt it when you want to use.
For Web Service(PHP) Json to Android: Use SSL and Post method
Not enough. It is still be able to do repeated request attacked. Add two more mechanics, nonce (number used once) and request signing to your API. It will be far more safe.
For Android data to Web Service(PHP): Use SSL and Post method
SSL + Post + nonce + Request Signing + Certificate Pinning (to prevent man-in-the-middle attack).
To prevent Android APK to re-engineering: Use Proguard
Correct.
To make Web Service(PHP) can only access by the Android app: Hard-code a secret key inside the app, send it in HEAD with SSL everytime to the server. Or use android application licensing?
Just attach some variable, that indicated that the transaction was sent from your android app, to the request.
I don't understand what the hacker can see and cannot see when he enters in a mobile app, for example android. He decompiles the .apk, then sees some .class files. If for example, I encrypt a key/value pair in a file, I still need to call this key from the code, and if the hacker can see the code, no matter if the key is encrypted, he will know which key I am calling?
My goal is to keep some encrypted string in my app, for example the twitter account Id of my app.
Some topics talk about " a private key to read, what was encrypted with a public key ", but if I use them, I still need to store them somewhere in my app...
Don't completely understand your requirement but the rule-of-thumb is always assume that client is not to be trusted.
You have to ensure that
All decryption should be done in your server (which you trust).
The client should never be able to access the decrypted data (unless you want it to). Hence whatever part of your code that needs to directly access the decrypted data should be in the server.
The client should have only the encrypted data (if it must store data).
The client should not be able to access the private key you used to encrypt the data.
If in your case your client must be able to access the critical data directly, then your only resort is to use obfuscation techniques (Basically hiding your data/code, to make it hard to find/understand). Of course all obfuscation techniques can be defeated eventually by a determined hacker. You have to decide how valuable your data is, what are the probabilities a hacker will try and access your data.
To take an extreme example : storing your twitter account and password using obfusucation is very bad. Storing a twitter-url- might not be so bad.
you can get your keys from server while launching app. and also dont manage in app purchase detail in sharedPrefrence or Sqlite. because in rooted device user can see that data file from root browser or sqlite editor application so user be able to change value.
A very determined person can crack it, but it's a major pain to crack encrypted strings and will stop most hackers. Especially if you obfuscate your code with something like ProGuard.
Answer to a similar question for details on how to encrypt
I am creating an app that requires the user to register with a remote server, but I want to hash their password before sending it off to be stored in my database.
I tried using the jBCrypt library, but it created a long hang time while hashing. Are there any other alternatives? What would be the best (and safest) way to hash the passwords without creating a noticeable hang?
Your approach seems to be wrong. Unless you have some special requirements, the usual way to do this is the following (not Android-specific, for any web application):
When the users register, take their password, hash it (using a random salt is also recommended), and save it in the DB. That is done so you don't save the actual password in your DB.
When the user needs to login, you send the actual password to your webapp (use SSL to avoid sending it in the clear), not the hash. On the server, you apply the same hashing algorithm as in step 1, and compare the result to what is in your DB. If they are the same, the user has provided the correct password.
In short, you should do your hashing on the server, not on the Android device.
Avoid saving 3rd party passwords at all cost. Saving them is considered a form of phishing. Try to save an authentication token instead of a raw password that you can get using a method like OAuth.
If you do need to send a password to a database on a webserver, just use HTTPS. This will ensure safe encryption over the wire. Then you can encrypt the password as necessary in the database. This method also ensures that your encryption mechanism is not on the device itself which can be more easily compromised.
I've got an app that can save stuff you like to Google Storage for Developers. Assuming, of course, that you have an account and associated access keys. Their web based key management tool allows you to create keys and associated secrets. My question is regarding how a user can most easily install these in their copy of my app, allowing them to use the cloud storage.
A key is a 20 character alphanumeric string, and an associated secret is a 40 character Base-64 encoded string. It is clearly impractical for the user to enter these manually. Cut and paste across activities seems way awkward to me. How do you suggest getting two strings from a web page to two activity EditText fields - or to a tmp file I can read and then dispose - or ??
thanks.
The best way to go about it would be the API from Google
If you have access to a web page, there are these values are residing, you can download it, parse, and get these values.
Since it doesn't look like Google provides an API specifically for getting keys, your best bet would probably be to use an HTTP GET to pull the web page containing the keys and secret keys.
If you need to be authenticated with Google to do this (presumably you'd have to be), you could use SignPost to handle OAuth and make secure HTTP requests. After you pull the page, parse through the HttpResponse content and store the keys in a text file or a SharedPreferences file.