How can I obfuscate a static password in objective c? - objective-c

I need to hide a password to connect with a server. The problem is that the password is given by the service providers, so it is static.
I already thought of using the keychain, but the problem is that even if I use this I need to hard code the password to insert it in the keychain somewhere in the code.
So, is there a way to hide a static password to be available for my app, avoiding to write it in my code?

I would think about setting up a middle layer server - kind of a proxy - between users of your app and the service provider. It will allow you to:
set different password for each user
optionally give users a chance to change a password
have more control over who uses the service and what data is transmitted
be more independent of your service provider (e.g. change it anytime)
It will require more effort but may be it is more advantageous in long run.

This is not a solvable problem, and has been discussed at length around SO. For one "hub" question that includes links to several others, see Secure https encryption for iPhone app to webpage.
Using obscurity is not a horrible thing. But keep it simple. XOR the value with some random key. Done. Putting more and more layers buy you nothing, and cost you complexity (which means time and bugs, which are the enemies of both profit and security). If someone puts a debugger on your code, they're just going to log all the data you send to the server, so all the hoops you jump through to hide how you compute the password won't matter, because eventually you have to send it to the server. So keep it simple to stop people from just using "strings" to pull it out, and recognize that you cannot stop a debugger.
The only way to secure the service-provider's key is to put that key on your server, and then proxy for the service after authenticating the user. If you put it in the code, then it is discoverable, period. If this were a solvable problem, there would be no unlicensed copies of software, no unlicensed copies of music, no jailbreaks for iPhones, etc etc etc. If Apple can't stop reverse engineering when controlling every piece of the system from the hardware to the OS, you're not going to fix it inside of an app.
What you should be thinking about is how to recover if and when the key is lost. How do you discover that it's happened? How do you expire that key and create a new one? If you're shipping the key in the code, you must assume that it eventually will be discovered, and you should have a plan for dealing with it.
As a side note, one technique I've used in the past is to download the key from our server on-demand rather than encoding it anywhere in the app. We use authenticated HTTPS and check our certificates. Of course it is still possible to fool this system (it's always possible to fool a system that gives a client information they're only supposed to use a certain way), but the thinking is at least we can change the key more easily this way to stem the tide briefly if the key leaks.

This is the key and the box problem, you can keep putting your key in a new box every time and hide this key in a new box and you can keep on doing this.... but in the end you always have the last key... and nowhere to hide it.
Personally i would obfuscate the key to the keychain, and hide the real key in the keychain.
If it is a realy important secret you can use AES to encrypt your key, but then again your stuck with your encryption key, here you can use something that is device specific instead of a hardcoded value and generate your key out of that property.
For sure not perfect but will do the job in most cases.

Related

Where to put Google API key

I made a styled map in Google Maps and I needed an API key to make it work. I did it, and it workes fine if the API key is not restricted. If I restrict it on a particular IP or domain, it doesn't work, but this is not the problem I want to discuss here. I was wondering, why not leaving my key unrestricted? So i searched online and they said that a key shouldn't be unrestricted for security reasons, so they suggest to
store them in environment variables or in files outside of your application's source tree
I asked myself then, even if I put my API key in an external file, get it with php or whatever, wouldn't it be shown in the html's source code anyway? I mean, in the how-to page they say to write this code
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
that's fine, but whatever is my way to set the YOUR_API_KEY, whether getting it from an external file or not, it will be shown on my html's source code anyway.
So,
does anyone know what they mean when they say to put the API key on an external file?
If i find a way to put it on an external file, can I leave it unrestricted? If so, what could happen (speeching from a security point of view)?
Leaving an API completely unrestricted is awful practice and should be avoided in almost every situation. All someone with malicious intent needs to do is find your API key and suddenly they have access to almost everything function that the API key gives you access to. Always restrict keys to the bare minimum.
Since you're going to be embedding the map into an iframe, that script is going to be run client side meaning there isn't much when it comes to hiding the API key but if you restrict a key to simply view maps (and any other functions that will be needed on the users side) there won't be any need to hide it and you can leave it in there as the docs show you.
The document you read on best practices for security with API's applies more to applications of the Google API where it is handling sensitive data or the key has access to functions that could seriously compromise the security of your application if accessed. This doesn't apply in the scenario you described with maps.

Nginx basic auth and number of authenticated locations

Im using basic auth in nginx, no issue there, but i would like to limit the number of distinct locations a user is authenticated,
The end goal is to prevent user sharing access data to website, since the website does real time "monitoring" of some data, i wan't that if the same user/pass combination is used from another ip, that or either both users stop getting data,
or one of them stops getting data.
I don't think that is a good idea, because a user may log in via pc and mobile phone at the same time and has two different ip addresses that way. Also http-auth isn't designed to do what you want it to. It would have to remember the ip-address and make it expire somehow, when the user leaves without logging out. Altogether would it be difficult to guess for how long the session is valid. Another problem is, that most users don't have static IPs and get disconnected by their providers every 24 hours. What happens if that occurs after a valid login?
The most popular method to deal with this kind of problems are session-cookies. These can be described as a one time password and you can use that for as long as you want or until it expires. SessionIDs are usually saved in some kind of database and making those sessions unique would not be a big deal and may therefor be what you want. Luckily the
ngx_http_auth_request_module would allow you to only implement this missing part and would bring you as close as you can get without developing your own nginx-module (see https://www.nginx.com/resources/wiki/modules/ for available modules).
On the other hand: Don't do that. Seriously. If you care for security, do not try to reinvent the wheel and use something, that has already proven. E.g. ngx_http_auth_jwt_module allows you the use of OpenID, which also sets you free from saving sensible user data on your server (because nobody wants to save passwords unless it is absolutely necessary).
Both of these methods require nginx-modules, which may not be installed on your server. If you don't have the permissions to build them, I would suggest to add that to your question, so that others can suggest solutions for non root servers.
If you want to keep it simpler you should also consider to generate download links each and every time and save ip-address and download link address in a database. Delete entries when a user downloads that file and you are done. For that to work you can use the
Content-Disposition: attachment; filename=FILENAME-HTTP-Header, so that your download.php doesn't save a file that called alike.
May be you can also find some kind of javascript to replace ngx_http_auth_jwt_module and use OpenID with http-auth. That can work, because it is possible to do the authentication with ajax as well.
Last but not least: If you still want to do http-auth, also use HTTPS, because your passwords won't be encrypted by this auth-method by default.
What you want to do is unusual so you will need to write a lot of the logic to handle the process.
Your code will need to store a User ID and IP Address pair for each loged in user and validate each attempted log in against this. As the previous answer pointed out, you will need to expire logins etc. Basically, you need to roll a session handler.
This is not impossible or particularly difficult but you need to write it yourself in one of the scripting languages available to Nginx which are either Perl, which is not recommended due to limited ecosystem in Nginx, or Lua, which is highly recommended due to the massive Nginx lua ecosystem (used by Cloudflare for instance).
You will need to compile in the 3rd party Nginx Lua Module and associated modules or just uninstall Nginx and use the Openresty Bundle which already has everything you will need included instead ... including Redis for storage if you need to scale up.
Here are some tools you can use as your building blocks
Openresty Session Library
Openresty Redis Session Library
Openresty Encrypted Session Module
Note that you can implement Openresty stuff directly in Nginx if you wish without having to run Openresty as it is just a convenient bundle of Nginx and useful module.

Ways to protect my framework in Xcode?

We intend to sell our framework on the net ,and it needs to be protected in a matter than if someone buying it, he can't put it on the net, or give it to other developers .
We dont want to find it all over the net after a few months.
I had a few ways in mind but each had its catch .
Give a unique ID to every developer, and program that id to the framework, so he must enter that to use it. problem is ,that he can give the framework with the id to anyone .
Ask for the device number and enable only that device in my framework for each developer. problem here is that when he put it on store, all users cant use that since they have others device id.
Use the net to check some how(??) which i preferred not to limit the users to that need.
I can program each framework with a code, that only me can extract, so when i find it on the net i can be sure what dev put it in there (it doesn't help-i cant sue everyone)
Is there any other way to make the framework per developer but also let it work on all other users at the appstore when its there ?
Thanks .
#diederikh makes very good points, and NicolasMiari also provides good insight. The best answer IMO is a combination of these two. (While keeping in mind diederikh's excellent advice that your goal is to come up with something simple that will make things hard on legitimate customers.)
Rather than recompiling your entire framework for every customer, you make your license key depend on their bundle identifier. They send you their bundle ID. You use your private key and sign their bundle id. This provides you a hash that you send to them. Now, at runtime, your framework uses the public key (which is not sensitive; you could publish it anywhere) to verify your signature. See SecKeyRawVerify() for doing that on iOS.
You can use this approach to create time-limited keys. Just include time stamps in the signed data.
Using this approach, you could, if you wanted, let customers test your framework indefinitely by using your bundle identifier. You would make a signed hash of that identifier available to trial customers. But as soon as they want to upload to AppStore, they would have to change the identifier and pay you for a new signed key.
There certainly is a way to get around this. Attackers could modify your framework to ignore the signature verification. But that's always true, and preventing that is better done with lawyers after the fact than with DRM that will only likely cause trouble for paying customers.
Look at how PSPDFKit does it. If you want to use it out of demo mode you'll have to call a method with an unique ID. This ID will enable functionality which is not available in demo mode.
You can also sign (with the codesign tool) the framework with an unique certificate for each customer.
I would not worry too much; if will always find a way around your locks.

Solutions to protecting game high-scores

My friend proved it to me by taking the WP7 papertoss games and getting the .xap from it and then posting his own high scores.
Is there any fool proof way to stop this ? (I think xbox live integration makes hacking the high scores impossible but that is for special people )
It depends first of all how the high-scores are sent. I can only assume that what your friend did was take the XAP and modify some internal file or track the HTTP web requests that are used to send the scores to the centralized locations. I have two recommendations for you.
Encrypt. Don't keep scores in plaintext. There are plenty of strong encryption methods that you can take advantage of that will render the scoreboard useless unless the person who tries to read it has the key.
If you send the scores to a web service, never send it in plaintext (once again). From my own experience I can say that web requests can be easily altered and sniffed. So if I see that the app sends http://yourservice/sendscore?user=Den&score=500, I might as well invoke http://yourservice/sendscore?user=Den&score=99999999. Same applies if you plan on using headers.
Be aware, that using the Xbox Live services is only possible if you are a registered Xbox developer, and this is not easy to get.
First of all - is a high score list really that critical that you're worried about an edge case (the common person isn't going to have a dev unlocked phone with ability to modify the *.xap file)?
Second of all, no. There's no fool-proof way to protect your high score list if it is being stored locally on the device. The only way to protect the high score list would be to store it in the cloud via a web service or some other mechanism.
It is tricky to have a secure high score system since users can always modify information on the client side. It's impossible to prevent a determined hacker from looking at your code, but you can make it more difficult by obfuscating your code. PreEmptive's Dotfuscator is currently free for Windows Phone 7 developers and also has analytics built in if you want to use it. This will obfuscate your code and make it harder to read your code. Although it's not fool proof, it's an extra hurdle for hackers to overcome.
The obfuscation would make it harder to find the encryption key you're using to authenticate the high score.

Avoid running of software after copying to next machine?

I have developed a small software. I want to provide and run it commercially only. I want it to be run in the machines who have purchased it from me.
If someone copies it from my clients computer and runs it in next computer, I would like to stop functioning/running the software.
What can be the ways to prevent the piracy of my software?
Adaption of one of my previous answers:
There are a few ways to "activate" copied software to try to stop casual copying of the application.
In the most simplistic case, a registration code ("CD key") purchased from you, possibly via your website, and it is sent to the user who enters it into the program or installer. The whole process can basically be done offline; the program itself locally determines that the code is valid or invalid.
This is nice and easy, but it extremely vulnerable to key sharing - since there's no "phoning home" then the application cannot know that thousands of different people are all using the same key that they got off the internet or a serial library or their friend. It's also reasonably easy to make "keygens" which generate valid-seeming keys that were never actually issued by the developers.
Then we get into online registration. You still have some kind of code, but the program will phone home back to the server to determine whether the code is valid and usually unique. This stops basic key sharing, because the company knows if too many people from all over the world are all using the same key. Perhaps there is some kind of identification involved using MAC address, too, with infinite registrations allowed on the same hardware but maybe a limited number on what appears to be a different computer.
This is still pretty easy and stops simple key sharing. People will actually have to get into cracking the software or faking the server response to get past it.
Sometimes the program itself is partially/mostly encrypted and is only decrypted by the online registration step. Depending on how well this is obfuscated then it can be pretty difficult and time consuming to crack. Bioshock was a high-profile example of this - debuting with a brand new encryption/copy protection scheme that took around two weeks from release to be broken.
Finally, a particularly guarded application might stay in constant contact with the server, refusing to work at all if the connection is severed.
If you know for sure that all your users will all have reliable internet connections then it can be considered quite a strong way to protect the app, at the cost of privacy and some user distrust of the spyware.
In this case to get around the activation they would need to fake the server itself. Steam emulators and private WoW servers are an example of this.
And in the end, nothing is uncrackable.
In a nutshell: you can't.
Even very sofisticated systems (e.g. dongle keys) can be circumvented.
I guess your best call is to give a code to your customers and have an online check for that code, so that it cannot be used twice.
Of course, that can be circumvented too but...
As nico said you really can't.
A simple solution might be to generate (registration/activation) codes that are based on hardware or software installed on the particular computer - eg video card serial id or c:/windows creation time.
I have one idea may be it works.
What we can do, we will make an encorrupted database field and that field will be empty for the first time as soon as i install my software to some machine it will read the Mac Address + Mother Board Serial + Processor ID and make an encorrupted value with the combination of these three and write in to that field which i left empty for the first time use.
After that every time my application will read these three values and recreate the encrupptted value in the same manner and compare with the value of that database field. If the value of the database field and the value of the regenerated encrroupted field is equal, that means the computer is same other wise it is installed on some other machine in this case you delete all the code and can make the system unstable to punish the person also :) ...
Please let me know about your opinion about this idea.
The best way is to use some sort of hardware-locking in which your license code contains encrypted info about the machine on which it will run. Your software will then check for this info and match it with the current computer and if the match is successful, the license is deemed valid.
Sure, any scheme can be cracked by someone on the face of the planet, but that does not mean you shouldn't use a protection scheme.
If you are looking for a ready-made scheme for this, have a look at CryptoLicensing.
Companies such as ours (Wibu-Systems), Safe-Net, and Flexera (expensive) offer dongle-free solutions as well as ones based on hardware. But _simon was right in that a dongle is the only iron-clad protection. All software-based systems can be cracked; it's just that some are more difficult than others. Really good hardware-based solutions are effectively uncrackable. No one has yet cracked the CodeMeter stick unless the implementation was flawed.