I'm trying to design a small api however I'm a bit stuck on how to secure the api. I have read some articles about how to do this one of them is: Login and retrieving an apikey and then hash some values with this apikey and send the hashed string back along with the request, so it can be done again on server level.
Is this a good way or is this dangerous to do?
If not miss understood, to avoid man in the middle I can add the request url to the variables that will be hashed, or isn't that the appropriate way
Also my brain is stuck on how to use a time stamp to avoid making lots of request to the same url with same data.
I'm sorry if my question have been asked a 1000 times. However I have read some articles now and it's still not clear to me what way to go for my small api.
From what I have read and understand from it this should be the way.
public key is stored in the application to let the user or application login.
server creates private key for this particular user when it's accessed. Or should this be always the same or a static value that has been created by a person?
user makes request sends along with the request a signature that's hash_hmac(some values+private key);
server checks if these value's are correct and does by creating the same hash from the value's that are send.
If server generates the same hash, the request is valid and can then be executed.
Is this they way to go or am I missing some mayor things here.
For hasing the data is the underneath way a good way to create a hash?
$l_sPrivateKey = 'something returned by database when user loged in';
$l_aData = array();
foreach($_POST as $key => $value){
if($key == 'signature') continue;
$l_aData[$key] = $value;
}
//This should then be the same as $_POST['signature'];
hash_hmac('sha256',serialize($l_aData),$l_sPrivateKey, false);
Your input would be appreciated.
Kind regards and thanks in advance
Secure Remote Password Protocol (SRP6a) With HMAC Fits Your Requirement
The following assumes that your API is browser-to-server so JavaScript-to-PHP not server-to-server using only PHP. SRP will work for both scenarios but the answer below discusses browser-to-server libraries.
Use the Secure Remote Password protocol to authenticate the user of the API which has the side effect of creating a strong session key. You can then use the shared strong session key to sign API requests and responses using HMAC.
RFC5054 uses SRP rather than public keys to create a shared session key to encrypt TLS traffic. There is an implementation in OpenSSL. This demonstrates that SRP authentication is a perfectly safe replacement to public keys to create a secure shared secret. IMHO using SRP is more convenient to solve your problem.
The Thinbus SRP library is a JavaScript SRP library which has a demo of authenticated to a PHP server. The PHP demo does not show using the shared session key but it is simply $srp->getSessionKey() on the server and client.getSessionKey() in the browser once the authentication protocol has finished. The default Thinbus configuration results in a 256bit shared key. You can use this with HMAC see the footnote 1 below about using signed JSON.
How It Works
The registration flow would be:
Client API registration form generates a random API password using JavaScript at the client which is not transmitted to the server. This is saved into the browser local storage and shown to the user asking them to print it off and keep a backup.
The password is given to the Thinbus SRP client JS library code which outputs a client salt and password verifier.
The salt and verifier are posted to the server and saved in the database for that client. Normally Thinbus recommends you keep the verifier hidden by using HTTPS to send the verifier to the server to prevent brute force attacks to recover the password. If you are using a random generated password as long as a typical software license key then you can transmit the verifier over HTTP. See footnote 2 below.
The API usage flow would start with an SRP authentication of the client that has the side effect of generating a session key. Note all this is in the Thinbus demo code as "standard usage" but is explained here to give a flavour of how STP authentication works. This authentication protocol is shown in sequence diagram of the thinbus page and is running in the online demos:
Client javascript loads the API password from browser local storage.
Client AJAX fetches from the server the client salt and a server random one-time number B.
Client javascript generates a one-time number A then uses the password, salt, and both one-time numbers to generate a session key K and hashes that with the both one-time numbers to create a password proof M that it posts to the server along with its random A.
Server uses the password verifier saved to the database at registration, the client salt, and the two random numbers to compute the session key K then confirms the client sent password proof M is good. If that is all good it sends its own proof M2back to the client. At this point the client has been authenticated using STP as a zero-knowledge proof of password.
Client checks M2 against its computation. If all is good both sides have a shared secret K which is a one time 256 bit session key derived from the random A and B that no man-in-the-middle can feasibly know.
All API requests and responses can be HMAC signed with the shared secret and verified on the other side.
All of the above is covered in the PHP demo of Thinbus minus actually calling $srp->getSessionKey() at the end to have a key that can be used to sign things with using HMAC.
Give that SRP replaces password authentication with a cryptographic zero-knowledge proof of password it is surprising that not all developers use it by default. The fact that it also generates a shared session key for API signing is simply an added bonus.
Footnote 1: Most APIs would prefer to post one JSON value with all the data in it. This is because JSON is simple yet more powerful with built in API in both PHP and JavaScript to turn objects into strings and back again. As #dbrumann pointed in a comment there is a standard for signing JSON which is JWT. Google suggest that here are libraries for this in both PHP and JavaScript. So if you upgrade to passing one JSON input value and returning one JSON output for every command in your API Ayou can use a JWT library to sign and validate the JSON inputs and outputs of the API. One of the JWS algorithms is "JWSAlgorithm.HS256 - HMAC with SHA-256, 256+ bit secret". The libraries will sort out the mechanics of actually signing and verifying so you don't have to write that code and worry about possible security bugs.
Footnote 2: The recommendation with Thinbus is to transmit the password verifier to the server over HTTPS to keep the verifier secret. This is to prevent interception then an offline dictionary attack against the password verifier to recover the password (i.e. the password is salted into the verifier so you would need to run the 16G crackstation password dictionary through the verifier generation code with the user salt to find a match). With API usage the browser window.crypto API can generate a truly random "API key". Typically windows keys were 16 upper case letters shown to the user formatted as XXXX-XXXX-XXXX-XXXX. Checking the GRC password search space page it says that a random 16 letter upper case password that size would take a government 14 years to exhaustively search. Given that estimation you can safely transmit a password verifier generated for such a long random password over plain HTTP without encryption as no-one will feasibly dedicate many years of computing power to run so many password guesses through the verifier generation algorithm (which uses the random client salt so cannot be pre-computed) to find a match to recover the client API password.
Related
My Requirement
I am making a website which will have mobile version as well. So, I am making it API centric. Now I want to make my API secure without the complexities of OAuth because the security I need is quite simple. I don't want anyone with access to the api links to be able to access my data.
So, I came across this article http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/ which is quite amazing and cleared most of my doubts.
Right now, I am trying to recreate whatever is there in the article. I am using Laravel 5 framework for PHP for development.
I want to make sure that the API is being used by the mobile app and the web version only and no one else.
I have seen api links like
example.com/fetchallinformation&publicKey=<something>&Hashkey?<some_hash_key>
Now, I understand that this key is generated by using hash_hmac() function in php.
My Approach
I have a table where I am storing the publicKey and privateKey for my api users
That HashKey in the URL is generated by hashing the privateKey and the publicKey in the client side and then sent to the server. So, i send the generated Hash along with the publicKey to the server.
In the server side, I take the publicKey and the Hash. I retrieve the private key from the table corresponding to the publicKey and has them and check if the resulting hash is same as the hash send by the client
If it is same, then I give permission to them, else, I don't.
My Confusion
I am not sure if this is the right way to do this.
Can we get the data that has been used to generate the hash using hash_hmac() by decrypting the hash?
That HashKey in the URL is generated by hashing the privateKey and the publicKey in the client side and then sent to the server. So, i send the generated Hash along with the publicKey to the server.
Close, but not quite. As you just described it, a user with a given public key would send the same hmac with every request. That's no better than "username and password."
Side note: if you aren't using https, you're already insecure and whatever else you do to secure the site is of relatively little value.
The point of generating an hmac signature is that it not only authenticates the user as being in possession of the secret key, it also authenticates the specific request as being made by that user and being made during a specific window of time. Two different requests back to back should have a different hmac. One request today and an identical request tomorrow should also have a different hmac. Otherwise, you're in for replay attacks. This means information about the current time or expiration time of the signature, and information about the request itself, must be included in the information that's passed through the hmac algorithm or you're not accomplishing much.
For any given request, by a specific user, at a specific time, there can only be one possible valid signature. HMAC is not reversible, so you can't take the signature apart at the server end and figure out the attributes of the request.
Of course, of you're thinking about embedding that secret key in your app, remember that such tactics can be relatively trivial to reverse-engineer.
Is it a viable authentication mechanism? Of course. As the article points out, Amazon Web Services uses hmac signatures on their APIs, and they have a massive potential attack surface... but does that mean you will implement it in a meaningfully secure fashion? Not necessarily. There is always someone more clever, devious, and determined than you can imagine.
Even Amazon apparently realizes that their Signature Version 2 is not as strong as it could be, so they now have Signature Version 4, which has a much more complex algorithm, including several rounds of hashing and generation of an intermediate "Signing Key" that is derived from your secret, the current date, the specific AWS service, AWS region, and other attributes. Regions where Amazon S3 was first deployed in 2014 or later don't have support for the original Sig V2 at all -- and it seems like it can only be security-consciousness that drove that decision, since the old algorithm is computationally less expensive, by far.
Use caution in rolling your own security mechanisms.
If you are primarily trying to avoid the learning curve with OAuth, which I agree is quite annoying at first, you could be on a fool's errand.
If this method works for you it should definitely be fine, and undoubtedly it is secure.
Regarding decryption - HMAC is not supposed to be decrypted due to its nature (hash). HMAC is considered to be very secure and you should have no problems with it. You can read a bit more about How and when do I use HMAC? [SE Security]
I want to make sure that the API is being used by the mobile app and the web version only and no one else.
This is a problem that neither OAuth nor AWS-style signature authentication really help with. Both are about authenticating users, not applications. You can certainly implement either approach if you have a bunch of time to sink into it, but in both cases you're going to need to embed a "secret" in your apps, and once you give that app to a user your secret's not really a secret any more...
There's no great way to do what you're looking for. If someone's going to take the time to reverse-engineer your app to learn about how to directly hit the underlying API, anything else you do client-side to "authenticate" the calling application can be reverse-engineered as well.
I'd recommend not even bothering, and spending the time you save polishing your app so no one wants to bypass it and hit your API directly. :)
I am currently working on a mobile app that has a accompanying web service being developed in PHP. The one thing that we want to make sure is that the users data is safe in every possible way.
After careful evaluation, we have decided to use RNCryptor for all things related to encryption. This is in addition to the HTTPS connection. The current process is like below (login example):
The RNCryptor library on iOS uses a key to encrypt password before sending it to the server.
The server then stores this encrypted password on the database.
While re-authneticating, the app sends the password (again encrypted with the static key) and the server decrypts it (means the server also has the encryption key), verifies the login and sends the login key (encrypted with the same static key) back to the client.
Every subsequent request relies on the encrypted loginKey and the username for authenticating the validity of the user and login session.
I believe the above system is flawed because of the STATIC encryption keys and since the key is available on both the server and the client.
What we would like is to make the encryption key dynamic by merging the raw password with the STATIC encryption key. This would make encryption key unique for each user but it also means the server will have no idea about the key. It is essential for the server to know the key since other user data also gets encrypted and decrypted based on this key.
Can somebody help me out with this? What steps do I need to take to make the system more secure? Any code snippet or reference link specific to server-mobile client would also do. I know there are a lot of tutorials out there but mostly all resume the client to web based and not mobile.
PS: Sorry for such a long post.
I would probably just use OATH2 tokens for authentication, but if you wanted to do it your own way...
For securing passwords a salted hash is used. As a basic example of hashing passwords with a salt consider the following, and keep in mind it's NOT cryptographically secure.
shaResult = SHA1(16 Byte Random Salt | "p#ssword")
Basics: The server stores the shaResult. Your app stores the salt value generated. When the user types in their password you append it to the stored salt, hash it, and send it to the server for verification. There's really no need to encrypt it to the server now. The HTTPS connection should handle that.
Good cryptographic password hashing is described in detail at Salted Password Hashing - Doing it Right To summarize they suggest using the following:
Salt should be generated using a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG). Suggested CSPRNGs is given in the link for multiple programming/scripting languages.
The salt needs to be unique per-user per-password. Every time a user creates an account or changes their password, the password should be hashed using a new random salt. Never reuse a salt. The salt also needs to be long, so that there are many possible salts. As a rule of thumb, make your salt is at least as long as the hash function's output. The salt should be stored in the user account table alongside the hash.
Use a well-tested cryptographic hash algorithm, such as SHA256, SHA512, RipeMD, WHIRLPOOL, SHA3, etc.
Use slow hashing functions that perform multiple iterations. Standard algorithms include PBKDF2 and bcrypt.
Use a keyed hashing algorithm, HMAC.
I'll reiterate that secure connections still need to be used in conjunction with the above.
If you want a method that does not use the same authentication value each time consider using the Challenge-Handshake Authentication Protocol which protects against replay attacks. See RFC1994 for more complete details.
At setup a shared key is established between the client and server. This must be done securely, possible with SSL or side-channed communications.
Authentication:
The server sends a random challenge to the client.
The client uses the challenge value to compute a hash with a function such as PBKDF2 and sends it to the server along with the user identifier.
The server performs the same computation and verifies the value from it's user identifier/shared key table.
There are slight variations but the concept is the same.
I would like to implement an API key system to secure API calls to my app.
The way I think will work is my having a private key/secret per account. Each request contains the time, account id and a hash(time+secret).
The server can then do the same thing with the users secret from the database and check that against the hash the client sent.
Is this a reasonable way to do it? It is open to a brute force attack, but I'm thinking that as long as the secret is long (ie uuid) it shouldn't be too much of a problem...
A Thought
Any one could submit another request with the same time and hash and have it accepted, after all its valid, right?
The problem being that the nonce + hash can be replayed. A real authentication protocol requires at least two messages:
Server Client
---->challenge --->
<----response------
For example, the challenge could be the nonce, supplied by the server, and the client's response would be the hash of password with the nonce.
Unfortunately, this requires state, and the whole problem with RESTful protocols is that they do not want the hassle of keeping state. And yet they want to authenticate...
So you really have three options:
Option 1: Pretend the problem does not exist, and use the stateless "authentication" protocol. This is no different from using a cookie. The nonce + password-hash is no more secure than a cookie. Cookies can be stolen, etc, and replayed. The entire web is now plagued by these replay attacks.
Option 2: Try to bolt an authentication protocol onto a stateless communication method. Here, you would have the client send you a UTC time-stamp instead of a nonce. The use of the time-stamp provides limited defense against replay. Obviously your clock is not going to be synched with that of the client, so your server will allow any timestamp within some error margin, and that error margin will be the replay margin of the authentication protocol. Note that this violates REST, because the authentication message is not idempotent. Idempotent implies "can be successfully replayed by an attacker".
Option 3: Do not try to bolt an authentication protocol onto a stateless protocol. Use SSL. Use client certificates. Instead of having the client download a string, let them generate a certificate, or you can supply them with a key-pair. They authenticate via SSL and do not authenticate in your REST layer. SSL has lots of "overhead". It is not lightweight, precisely because it does address these replay issues.
So at the end of the day, it depends on how much you value access to your APIs.
For APIs that only retrieve data (other than private data), rather than create, modify, or delete data,
option 1 in this answer
may be adequate. See, for example, the Bing Maps REST API and Google
Maps Premier web services (where here, Google Maps also hashes the URL with a digital signature
and a special key known only to the API user, which, while providing protection against modifying
the URL, apparently still doesn't provide replay attack protection).
In fact, some APIs that retrieve data do not use an API key, but rather limit access in other ways (for example, the YouTube API allows retrieving publicly available data on videos and users' channels without requiring authentication, but limits the number of recent requests).
Options 2 and/or 3 are required for APIs that do more than just retrieve publicly-available data, for instance, if it modifies user profiles, posts content, or accesses private information: see for example, the YouTube data API authentication page, where OAuth is mentioned as one possible authentication scheme.
Especially for option 1, the API key here is used in order to track access by users to your API, and most importantly, limit access by those users. Option 1 may not be appropriate for APIs that allow unlimited data access.
(This is an answer since it's too long to be a comment.)
Server contains:
username
password hash
Client sends:
username
random string
hash of (password hash + random string)
When clients calls server, server creates hash of password hash (which it knows itself) + random string (given in GET by calling client) eand evaluates if that matches the hash (given in GET by calling client)
Even better would be to create 1 function that generates a secret hash from (password hash + nonce) where "nonce" (something random) is also stored on server. Then make it possible to call the server once with username + password, which returns the secret hash; then have subsequent calls solely depend on username + random string + hash of (secret hash + random string) with the same methodology as described above, but secret being what was then password.
This way, even if your secret would be intercepted and reversed, your pass would still be safe.
And obviously, good hashing algorithms: no rot13 and even solely md5 is questionable.
We're building a game for Android, which needs access to web services - so we wrote a RESTful API in PHP that runs on our own server. What the API offers is: creating user, logging in, downloading games, retrieving game list, submitting score... etc. Now I'm thinking, if some experienced user gets the URL format of the API - s/he will be able to trash the system in many ways:
Create a script & run it to create automatic users - I think I can prevent it by CAPTCHA or someting like that. But again, captcha will annoy game players.
Malicious user logs in using his browser, downloads game & then submits score as he wish - all via calling the API by simply typing it from his browser. I assume malicious user somehow knows API urls to call - by sniffing when the application was making HTTP requests.
I need to ensure that requests are made only from Android device that installed the game. (The game will be free)
Now How do I prevent such abuses?
I think you will never be able to hide the urls being called by the application
(if I am running a root-ed android phone, I should be able to spy on all network traffic)
But your real problem is that you need to authenticate your api in some way.
One way would be to implement OAUTH, but maybe this'd be overkill.
If you want a simple mechanism, how about this;
create a secret key
build the api request (eg. https://my.example.com/users/23?fields=name,email)
hash this request path + plus your secret key (eg. md5(url+secret_key) == "a3c2fe167")
add this hash to your request (now it is https://.....?fields=name,email&hash=a3c2fe167)
on the api end, do the same conversion (remove the hash param)
check the md5 of the url and the secret key
As long as the secret remains secret, no one can forge your requests.
Example (in pseudo-code):
Android side:
SECRET_KEY = "abc123"
def call_api_with_secret(url, params)
# create the hash to sign the request
hash = MD5.hash(SECRET_KEY, url, params)
# call the api with the added hash
call_api(url+"&hash=#{hash}", params)
end
Server side:
SECRET_KEY = "abc123"
def receive_from_api(url, params)
# retrieve the hash
url_without_hash, received_hash = retrieve_and_remove_hash(url)
# check the hash
expected_hash = MD5.hash(SECRET_KEY, url_without_hash, params)
if (expected_hash != received_hash)
raise our exception!
end
# now do the usual stuff
end
Solutions that others have presented here are called security through obscurity. Basically they are trying to obscure the protocol and hide the implementation. This might work until someone capable enough disassembles the app and reverse-engineers the protocol. Hackers are very capable at that.
The question is if your app is worth cracking? Schemes like iTunes, DVD or Sony PS3 network were obviously worth the effort. The obscurity approach might work if no one capable of cracking cares. Just don't fool yourself that it is not doeable.
Since you can not trust the device or your app, you must trust the user. In order to trust the user, you need user identification and authorization system. Basically a login to your app. Instead rolling you own indentification system (login with confirmation emails, etc..), use a 3rd party system: OpenID (google accounts) or OAuth (facebook, twitter). In case of facebook use the server-side auth scheme.
What I'd do:
Allow users to freely play the game until they want to "save" the results on server.
Before saving their results have them login via above mentioned method.
Use HTTPS to send the data to your server. Buy a ssl certificate from trusted CA, so you don't have to deal with self-signed certs.
You mentioned users faking the high scores. This could still happen if your users are authenticated. When the game is uploading the high scores you may want to have it also upload a proof of the score. For example Score 20100 from 103 bugs squished, 1200 miles flown, level 3 reached, and 2 cherries were eaten. This is by no means perfect but would cover the low hanging fruit.
The first you should do is have authenticated users. Userid/password/session token etc., see if you can find some already existing frameworks. Once you have user authentication make sure you can do it securely with TLS or similar.
As far as I know there is no way your server can be certain that the request is coming from your application (it's all just bits in packets) but you can at least make it hard for someone to be malicious.
Build a secret into your application (as suggested by other responses, key, hash salt etc.)
Generate a unique ID on the first execution of the application after installation and track that along with the logged in user. Details on this and the device's unique ID (why not to use it) can be found on the android blog
Some ideas discussed in this post How to ensure/determine that a post is coming from an specific application running on an iPhone/iTouch?
Check User Agent
If you really want to secure the connection then you'll have to use public key cryptography, e.g. RSA. The device will encrypt the log in information using the public key and in the server end you will have to decrypt using the private key. After login the server will send a token/encryption key (the response will be an encrypted JSON or something) and the device will store that. From then as long as the session is not expired the device will send all the information encrypted using that token. For this requests you should not use RSA cause that will take more time. You can use AES256 (which is a popular private key encryption) with that encryption key received from server to encrypt your requests.
For sake of simplicity you can drop RSA altogether (If you are not sending payment information) and do everything using AES256 with a private key. The steps should be -
Encrypt every outgoing request with a private key.
Convert the encrypted string to a base 64 string.
URL encode the base 64 encoded string.
Send it over.
On the server end
Do base 64 decode
Decrypt using the private key.
Your request should carry a signature (e.g. the encryption key appended as a salt) so that it becomes possible to identify it after decrypting. If the signature is not present simply discard the request.
For sending responses do the same.
Android SDK should have methods for Encrypting with AES256 and Base 64 encoding.
Follow these guidelines from the Android team to secure your backend, by using Oauth tokens provided through Google's APIs.
I'm asked to write a Web API for an application (pc executable, not web-app) that will allow sending emails.
A user clicks something, the app communicates with the API which generates an email and sends it out.
I have to make sure noone unauthorised will have access to the API, so I need to make some kind of authentication and I haven't got an idea how to do it correctly.
There will be more applications accessing the API.
First thought was - send username and password, but this doesn't solve the problem really. Because if someone decompiles the application, they'll have the request url and variables including user/password or simply it can just be sniffed.
so... what options do I have?
I'm fairly sure secure connection (SSL) is not available to me at the moment, but still, this won't help me against the decompiling problem, will it?
EDIT
I haven't said that initially, but the user will not be asked for the username/password. It's the application(s) that will have to be authenticated, not users of the application(s).
The distribution of your software is really the crux of the problem. Hashing user names and passwords and storing them in the software isn't any more useful than storing un-hashed values, as either one would work to access the API server. If you're going to implement usernames and passwords for your users, I think you can use that as a pre-cursor to API control without storing the values in the software itself. Let me describe this in two parts.
Request Signatures
The most common method in use for API request verification is request signatures. Basically, before a request is sent to an API server, the parameters in the request are sorted, and a unique key is added to the mix. The whole lot is then used to produce a hash, which is appended to the request. For example:
public static function generateRequestString(array $params, $secretKey)
{
$params['signature'] = self::generateSignature($params, $secretKey);
return http_build_query($params,'','&');
}
public static function generateSignature($secretKey, array $params)
{
$reqString = $secretKey;
ksort($params);
foreach($params as $k => $v)
{
$reqString .= $k . $v;
}
return md5($reqString);
}
You could create an API request query string using the above code simply by calling the generateRequestString() method with an array of all the parameters you wanted to send. The secret key is something that is provided uniquely to each user of the API. Generally you pass in your user id to the API server along with the signature, and the API server uses your id to fetch your secret key from the local database and verify the request in the same way that you built it. Assuming that the key and user id are correct, that user should be the only one able to generate the correct signature. Note that the key is never passed in the API request.
Unfortunately, this requires every user to have a unique key, which is a problem for your desktop app. Which leads me to step two.
Temporal Keys
So you can't distribute keys with the application because it can be decompiled, and the keys would get out. To counter-act that, you could make very short-lived keys.
Assuming that you've implemented a part of the desktop app that asks users for their username and password, you can have the application perform an authentication request to your server. On a successful authentication, you could return a temporal key with the response, which the desktop app could then store for the lifetime of the authorized session, and use for API requests. Because you mentioned that you can't use SSL, this initial authentication is the most vulnerable part, and you have to live with some limitations.
The article Andy E suggested is a good approach (I voted it up). It's basically a handshake to establish a short-lived key that can be used to authenticate. The same key could be used for signature hashing. You could also take your chances and just send the username/password unencrypted and get a temporal key (it would only happen once), but you'd have to be aware that it could be sniffed.
Summary
If you can establish a temporal session key, you won't have to store anything in the client program that can be decompiled. A username/password sent once to your server should be enough to establish that. Once you have that key, you can use it to create requests in the desktop apps, and verify requests on the API server.
I would recommend you check out OAuth. it should definitely help you out in sorting out the security issues with authorizing tools to access your API.
http://oauth.net
Someone is always going to be able to decompile and hunt for the variables. An obfuscator might be able to hide them a little better. Sniffing is also easy without SSL unless you use a private and public keyset to encrypt the request data client side and decrypt server side (but obviously this key will be stored in the client application).
The best thing to do is provide as many layers of protection as you think you will need, creating a secure connection and obfuscating your code. You could look at the following article, which demonstrates a secure connection without using SSL:
http://www.codeproject.com/KB/security/SecureStream.aspx
As mattjames mentioned, you should never store passwords in plain text format. When the user enters their password into the application, store a hash of the password. The same hash should be stored on the server. That way, if the hash is seen by an interceptor they at least wouldn't see the user's original password.
You will need to use SSL if you need to prevent people from seeing the plain text password that is sent from the app over the network to the API.
For the decompilation issue, you would want to store the hash of the password in the API, not the original password. See explanation here: http://phpsec.org/articles/2005/password-hashing.html.