1
votes

I need to implement a free of charge scheme (no SSL certificate) which can meet the requirements on the sensitive data transmission, protection and storage, assuming mutually trusted third party is not available, that is, we cannot use SSL, TLS etc. But this doesn't means I will implement SSL by myself, I still would like to outsourcing encryption and decryption parts to existing codes.

I have drafted below scheme as my account and password protection solution:

Assumptions on our attackers:

  1. have complete knowledge of the protocol.

  2. have access to a large dictionary of commonly used passwords.

  3. can eavesdrop on all communications between client and server.

  4. can intercept, modify, and forge arbitrary messages between client and server.

  5. can access the source codes (including encryption code) on the client-side.

Solutions:

  • RSA (encryption & decryption on client and server sites respectively, public key is safe for transmission, there are not risk if the key is obtained by a hacker.)

  • SHA256/SHA512/Twice MD5 (Encryption with User ID binding Salt, both stored in database on the server site. I use binding salt here to avoid common password and prevent rainbow table.)

Registering a New User:

  1. First Generate RSA keys on server end ( Stored in session);

  2. Send public key to client;

  3. Store public keys in javascript variable;

  4. In All subsequent requests use this key to encrypt data and send to server;

  5. Use private keys stored in session to decrypt user account and password on server side;

  6. Encrypt the passwords with one-way encryption algorithm with a random salt (like the common opinion: SHA-256 is stronger than MD5);

  7. Store the user id , the hash password and the random salt (user id binding) into database ( avoid common password and building specific rainbow table).

Existing User Login:

  1. First Generate RSA keys on server end (stored in session);

  2. Send public key to client;

  3. Store public keys in javascript variable;

  4. In All subsequent requests use this key to encrypt data and send to server;

  5. Use private keys stored in session to decrypt user account and password on server side;

  6. Fetch the hash password and the salt from database by using the user account;

  7. Encrypt the passwords with one-way encryption algorithm with the obtained random salt;

  8. Compare the encrypted password with the hash password obtained from the database;

  9. Determine login success or failure.

I am new in this parts and I do need some professional suggestions from you? Is the scheme secure enough? Many thanks.

3
You really should be posting this on security.stackexchange.comfbernardo
steps 1-3 aren't secure on both endspyCthon
How are your users accessing your service? Can you use a self-signed certificate? How about something like OpenVPN to create an encrypted transport?Adam Liss
i was really wondering why people tend to "fetch" a password from the database and compare it to the values sent over. taking out the password (be it hashed or not) from the database is some risky move. why not just compare to the database, and return a count. (like 0 = non-existent, 1 = exising, > 1 = some error) that way, no values from the database is every pulled out.Joseph
@AdamLiss i wan't talking about the storing procedure. what i meant was people tend to program this "user check" by fetching a row in the database and compare in PHP rather make the necessary hashing in PHP then check if the username and hashed password exists in the database and just return a count.Joseph

3 Answers

6
votes

The main problem here is that you're doing a whole lot of work and you're not getting any better security than a self-signed SSL certificate, and you set yourself up as being the responsible party to close any possible holes and maintain the security of your system (hint: this is a Big Deal).

So, if you're talking about a generally available web application that you want your users to be able to just use, and use with confidence of security, then paying for a signed SSL certificate is really your only option. That said, a couple notes:

  1. The hashes you've mentioned are OK, but if you want real security use something like pbkdf2 (google this and your eyes will be opened to the depth and difficulty of real security)
  2. Without verifying the identity of the server (the purpose of signing in a signed SSL certificate) you open yourself up to man-in-the-middle attacks. If someone else can impersonate you, and has the full ability to "intercept, modify, and forge arbitrary messages between client and server", then it's simple for them to phish whatever info they want from your users. So, that's a problem you'll need to address if you intend for this to be a complete solution.

Edit: After reading and thinking more about what you're looking for, I think I may have a solution for you.

There's really two things that you could want to secure: your content, and your users credentials. You've determined that your content isn't worth spending $35 a year to secure, which is fair enough and perfectly reasonable. You still want to provide as much security as possible for your user's credentials, because that information is valuable to them and to those who would exploit it.

Even though you don't want to spend the money to secure your content, you still want it only accessible to credentialed users. So, instead of making users create a username/password, which would be worth protecting, just have them log in with their email address.

Your content and the email address are accessible to third parties of sufficient skill and motivation, but from what you've said, your content probably isn't worth that amount of effort, and their email address isn't that sensitive. But you still get to have a login gateway between the world and your content, and you can utilize a double opt-in to limit spam, etc. You can easily expand such a system to include a username/password and use SSL if your content grows to require it.

2
votes

If the attackers "can intercept, modify, and forge arbitrary messages between client and server", they can alter the JavaScript code the clients will get. From this point onwards, your entire mechanism collapses, since the attacker could replace any cryptographic operations you intended to perform with their own.

JavaScript cryptography isn't good enough anyway (see this article).

Using SSL/TLS with a self-signed certificate would at least give you the opportunity to give that certificate manually to your clients, or to let them remember the first certificate they've seen (in a similar way to what most people do when they connect over SSH: they don't necessarily verify the key the first time, but look for changes in subsequent connections).

0
votes

Using public keys to encrypt all of the data is going to kill you performance-wise. Asymmetric keys are only intended to encrypt small amounts of data (such as a symmetric session key).

Have you considered using a mechanism like Kerberos? It's intended for authentication over non-secure networks. It's drastically different from what you're doing-- take a look and maybe it will give you some ideas.