How to sign data properly in Ruby (HMAC?) - ruby

I have a server (RoR app) sending information to a client (a Ruby Sinatra app) and I need a way for the client to be certain the data has come from my server, rather than an evil third party.
The client has to login to the server before anything will be sent back the other way so the server could reply to the login with a shared key used to sign all further responses, but then the 3rd party could capture that response and be evil.
I'd like to find some way (in Ruby, with a view to cross-platform applicability) to sign the server's response so that it can be verified without inspection of the client's code leading to forgeries. Any ideas?
UPDATE: Lets see if I can explain this better!
(I've added code to github since I wrote this question, so you can (if you like!) have a poke around : The 'client' The 'server')
The process is this: Joe Bloggs uses a bookmarklet on his mobile device. This posts the currently visited URL to sitesender.heroku.com. When sitesender.heroku.com receives that request it checks its DB to see if anyone has logged into the same account using the Target application. If they have, their IP address will have been noted and sitesender.heroku.com will make a GET request of the target app (a webserver) at that IP asking the target to lanch the bookmarked URL in the default browser.
The basic idea being that you can send a site to your main computer from your iPhone for later viewing when you find the iPhone can't cope with the page (eg. flash, screen size).
Obviously the major issue is that with an open server anyone could send a request to open 'seriouslyevilwebsite.com' to a broad range of IPs and I've unleashed a plague on the digital world. Seeing as I'm using heroku.com as a server (its an incredibly good but cloud based RoR host) I can't just test the originating IP.
As far as I understand HTTPS, for this setting I'd have to sort out certificates for every target application? I agree that I need some form of asymmetric crypto, sign the outgoing requests from sitesender.heroku.com with a private key (never distributed) and get the target to perform the same operation using the public key and test for similarity - but you've guessed correctly, I'm still slightly clueless as to how HMAC works! How is it asymmetric? Is it formulated so that performing the same HMAC operation with the private key and public key will generate the same signature? In which case - HMAC is a winner!
Thanks for your patience!

I'm not sure exactly what you mean by "freely examined, but not replicated".
In general, if you need a secure communications channel, https is your friend.
Failing that (or if it's insufficient due to some architectural issue), HMAC and asymmetric crypto is the way to go.
UPDATE: I'm not sure I understand the problem, so I will try to describe the problem I think you're trying to solve: You have clients that need to be confident that the response they are seeing is actually coming from your server.
Assuming that I'm correct and this is really the problem you're trying to solve, HTTPS solves it nicely. You install a cert on your server—you can sign it yourself, but clients won't trust it by default; for that, you need to buy one from one of the standard certificate authorities (CAs)—and then the client makes an HTTPS request to your server. HTTPS handles verifying that the provided certificate was issued for the server it's talking to. You're done.
Finally, I think there's a misunderstanding with how an HMAC works. The key principle of asymmetric crypto is to NEVER distribute your private key. With asymmetric crypto, you encrypt messages with the recipient's public key and he/she decrypts it with his/her private key. You sign messages with your private key, and he/she verifies it using your public key.

Related

Xamarin forms app: how to digitally sign using private key from keystore

I want to use asymmetric key pairs to sign/verify data sent from an Xamarin forms smartphone app to a web service.
I have an Xamarin forms smartphone app targeted at Android and iOS devices. The client on the device connects through a web service to a database and, on successful login, retrieves and sends data. Currently the user logs in, providing username and password. The password is hashed and the database user table is searched for the combination of the username and password hash. If this combination is found then the user is deemed to be legitimate and information can be retrieved and sent.
I now want to introduce another layer of security, so that each device that installs the app would need, additionally, a private key. This key would be used to produce a digital signature or hash of data sent up to the web service. When the web service receives the request, it will use the corresponding public key of the key pair to verify the signature, and only allow the request through if the signature is verified. From time to time, I may want to eliminate the user base and start afresh and I was thinking that I could do this easily by creating a new asymmetric key pair and sending the new private key out to each user whom I wanted to be able to use the system while also changing the corresponding public key on the web service to the new one. This way anyone still using the old private key would not gain access. The difficulty I have found with this approach is that I don’t know how to get a new key on to the user's device and, having done that, I don’t know how to get access to this key in the app’s code in order to create the digital hash. I have tried experimentally to look at the key store, but I don’t seem to be able to do that on an iPhone the way I can on the PC, so my question, at its simplest is, how do I get a private key onto an iPhone or an Android phone and, having got it on there, how do I get access to it in code in order to use it to generate a digital hash. Of course, I could just use symmetric encryption, and pass a password to the user base which could then be used in code to encrypt some mutually agreed piece of text and the web service, on receiving it, would use the same password to decrypt it. I just thought that the asymmetric key pair approach was a more elegant, and, in the end, more robust solution. The other point is that I want to use the .Net System.Security.Cryptography classes only, ie no third party code if possible.

Secure WebAPI using HMAC. How to store passwords?

I'm new to WebAPI and before I dive too deep, I would like to first secure the Web API application first. After days of research, I just found one approach that's straight forward.
Looking over this post How to secure an ASP.NET Web API, I understand overall how it works and it's great there is a github source for it too. (Most answers I found just describe the generic concept with no code to back it up)
My question is, how do you store this "Shared Secret Key" on the server which typically is user's password? I'm doing a ASP.NET MVC 4 app with provided membership provider and it stores the user passwords with salt.
Obviously, the salt value is randomly generated per user and it's not likely the end user knows what their salt value is.
So then, what do you do?
PS: Am I missing some well known frameworks that handle this? I know Microsoft encourages mobile app developments and want developers to create new apps, but how am I suppose to do this when I can't even build authentication for Web API easily? Sorry, just a bit frustrated.
HMAC is not typically used for authenticating users to an API. It's typically used to authenticate "trusted" systems to an API. Example: Company A wants to access Company B's protected API, but doesn't need to authenticate at the user level.
When doing HMAC, you need to have the shared secret available in clear text on both the client and server so that both systems can create the exact same request signature hash. Although you may want to store the shared secret in an encrypted format, it must be a two-way (reversible) encryption.

Is there a standard way to handle cross-framework authentication?

I have some Ruby web apps that use OpenID for authentication and store the session in a cookie. There are a few API- and AJAX- related things that my Ruby frameworks aren't a good fit for, so I've got some node.js services. The problem is that if someone knew the URLs of my AJAX services, they'd basically be open to the public as things stand. At the moment those services do a simple check of the Origin header, but obviously that's very easy to forge.
So I want to be able to restrict access to the services running on Node (or Python, or in a non-Rack based Ruby service, or anything else) to users who are logged into the 'main' service that's run through a Rack-based web application. Are there any conventions for how this sort of thing is done? I've seen heaps of websites that will serve content and pages through example.com, and then the AJAX calls get made through api.example.com, so I'm surprised this is something I' haven't read about.
I do have an idea for how to do this, and I'd love some feedback on whether I'm missing something blindingly obvious that makes this insecure:
My Ruby web app uses OpenID for authentication and stores the session in a session cookie using Rack::Session. From looking at the Rack::Session source, my framework seems to go through this process:
generate a Marshal dump of my User object
generate a SHA1 hash of the Marshal based on a secret key
store a hex digest of the SHA1 hash in a cookie
So theoretically I could have a pre-arranged key or system for generating the key, or some message passing between frameworks through a secure channel to share the key. Then I could reverse the encryption process in any other framework that wanted to be able to verify session data. I'd have to get rid of the first step and only store JSON data or something instead of a Ruby object for cross-language compatibility, of course.
Is this considered a secure way to do things, assuming the protocols for sharing the key are appropriately secure?
What you're describing is a Message Authentication Code (MAC); in this case, it's a Hash-based MAC or HMAC. Basically, take a representation of the data you want to authenticate (make sure is coming from a certain source), append a secret key to it, and hash the whole thing. Then attach that computed hash to the message (what you just hashed minus the secret key). When the receiving party receives the message, it would take the data, append the same shared secret to it, and hash it. If that computed value is the same as the one received as part of the message, it is authentic and should be processed; if the hashes do not match, it is not from the party it should be from and should be discarded.
You may want to look at the RFC specifying the HMAC construct (just don't use the sample code as it still uses MD5; use something like SHA-256 or SHA-512 to implement your HMAC):
http://www.ietf.org/rfc/rfc2104.txt

Client PC authentication in ASP.NET MVC (Advice needed)

I've have some authentication scenario that I'm not sure how to approach. I'll appreciate any advice on the subject.
Requirement:
Website will contain one section
that will be only available to
specific computers.
Website needs to be aware which PC is currently making request (I need to be able to tie this PC to other tables in Database)
We have full access to PCs that will be accessing website
Website cannot require login, user should be just presented with content pages without need for logging in.
Solution needs to be secure since, it will have to pass security audit
Assume that every PC is on different network.
My ideas so far:
use client certificates but I'm
not sure whether you can issue
different certificate per client? If
the answer is 'you don't know who is
making the request' than it's failing
requirement number 2 and therefore is
not an option.
Windows
Authentication with impersonation so
I can have different users logged in
on PC (I'm in control what will be
the user name/account logged in on
the machine)
Basic Authentication and set PC to remember username/password first time. I'm a bit afraid that this "remember me" can expire which would cause big chaos since someone would have to setup this PC(s) again...
Windows Identity
Foundation - never tried but if I can
implement this scenario here in some
nice way I appreciate if you can
point me in the right direction.
Thanks in advance for your help.
EDIT:
I would prefer not to use SSL if possible... (performance consideration)
EDIT2:
Currently I think that the best option would be to check whether PC is authenticated (whether it contains Forms Authentication cookie) and if it is not then redirect him to some https:// page that will check client certificate, set cookie if cert exists and redirect back to target page.
This shouldn't be slow since SSL will be used only in rare cases when cookie expires.
Please let me know if you see any flaws in this solution. If you know how to create server certificate and later generate different client certificates from it I would be grateful for guidelines.

Protecting Javascript Code in a FF extension

I am looking to protect the code of my Firefox extension because it has server calls in it that no would be a security risk if someone could make them outside of the extension. Any suggestions on how to encrypt it?
This is basically impossible. You want to give executable code to an untrusted client that has "secret" calls in it, yet not let the client know the secrets? How, then, is it going to execute the code?
At some point, it must be decrypted. Which means the client has everything it needs to perform the decryption, which means a user can do it, and build a malicious version of your extension.
The only choice you have is to redesign such that vulnerable services are not publically exposed.
If it's going to be executed on the client side, with no reliable secret, then basically you've definitely got a security vulnerability.
It's hard to suggest ways round this without knowing a bit more about your extension. An obvious suggestion would be to request a username/password, authenticate (over HTTPS) with the server and receive a time-limited token, and then present that token with the "dodgy" request. That won't stop anyone with the right username and password though...
You could use xauth, which is a variant of OAuth designed to solve this type of problem. Twitter uses xauth: http://dev.twitter.com/pages/xauth
Additionally, you could obfuscate your Javascript code, or even write it in C (as a NPAPI plugin).

Resources