I have a webapp with some functionality that I'd like to be made accessible via an API or webservice.  My problem is that I want to control where my API can be accessed from, that is, I only want the apps that I create or approve to have access to my API.  The API would be a web-based REST service.  My users do not login, so there is no authentication of the user.  The most likely use case, and the one to work with now, is that the app will be an iOS app.  The API will be coded with django/python.
Given that it is not possible to view the source-code of an iOS app (I think, correct me if I'm wrong), my initial thinking is that I could just have some secret key that is passed in as a parameter to the API.  However, anyone listening in on the connection would be able to see this key and just use it from anywhere else in the world.
My next though is that I could add a prior step.  Before the app gets to use API it must pass a challenge.  On first request, my API will create a random phrase and encrypt it with some secret key (RSA?).  The original, unencrypted phrase will be sent to the app, which must also encrypt the phrase with the same secret key and send back the encrypted text with their request.  If the encryptions match up, the app gets access but if not they don't.
My question is: Does this sound like a good methodology and, if so, are there any existing libraries out there that can do these types of things?  I'll be working in python server-side and objective-c client side for now.
The easiest solution would be IP whitelisting if you expect the API consumer to be requesting from the same IP all the time. 
If you want to support the ability to 'authenticate' from anywhere, then you're on the right track; it would be a lot easier to share an encryption method and then requesting users send a request with an encrypted api consumer handle / password / request date. Your server decodes the encrypted value, checks the handle / password against a whitelist you control, and then verifies that the request date is within some timeframe that is valid; aka, if the request date wasnt within 1 minute ago, deny the request (that way, someone intercepts the encrypted value, it's only valid for 1 minute). The encrypted value keeps changing because the request time is changing, so the key for authentication keeps changing. 
That's my take anyways.
Security measures for controlling access to web-services/API