Alternative to SSL - “Manual” Encryption?

2020-02-01 07:56发布

问题:

I would like to encrypt data that travels back and forth between the server and client in my Web application. I would use SSL but that requires a certificate along with a dedicated IP address. I have no problem getting a certificate but the dedicated IP requires me to upgrade to a business hosting plan which is $20 a month on my Web host. I have no plans on doing that as I'm sticking with my $20/year shared hosting plan.

So, I would like to implement an alternative to SSL. It does more than SSL does, though. Along with encrypting the data sent back and forth, it also encrypts the rows in the database. I was thinking of doing something like this:

JavaScript Code:

var transfer_key = 'whatever'; 
function encrypt(data, key) {...}
function decrypt(data, key) {...}

function send_data_to_server(url, data)
{
    $.post(url, {'data' : encrypt(data, transfer_key) }, function(response) {
        var decrypted_response = JSON.parse(decrypt(response));
    });
}

PHP Code:

$data = $_POST['data']; 
$transfer_key = 'whatever'; 
$storage_key = 'whatever2'; 

function encrypt($data, $key) {...}
function decrypt($data, $key) {...}

databaseQuery('INSERT INTO table VALUES (?)', encrypt($data, $storage_key)); 

$decrypted_data = decrypt($data, $transfer_key); 
$response = processData($decrypted_data); 

echo encrypt($transfer_key, $response); 

As you can see, the data the client sends to the server is encrypted, and vice versa. And the data in the database is encrypted as well. Now of course, I would never implement the keys like that. I would probably have a second or third key that's randomly generated for each user. So transfer_key could be equal to a constant_key concatenated with a random key, and same goes for storage_key.

Would this be a good alternative to SSL? How can I implement this type of encryption in such a way that it is harder to defeat? Are there any particular weaknesses to this approach?

I'm probably going to find a JS library that takes care of the encryption and use PHP's mcrypt extension for the server-side. I was thinking of Blowfish, maybe AES256, but I'm not sure which one gives me the best ratio of encryption strength to memory consumption.

Advice?

回答1:

Uh, oh. Good luck with that. Have you had a look at the TLS specification? Do you think you can come up with something adequate that will be tested by millions of people?

No, really, TLS has been tested and improved over the years by so many people, cryptographers who do nothing else than breaking such protocols, it would be a hard task coming up with something adequate.

SSL has been developed by experts in the field and they most certainly thought at first, too, that their protocol was absolutely unbreakable. But then there was version 2, then 3, then TLS v.1, v1.1 and now 1.2.

If you don't have any prior experience in designing secure protocols you should stick with the mainstream and use TLS/SSL.

Security is one of the rare fields where it makes sense and is actually cool to go with the mainstream, so I'd say the added money would be well spent.

Edit:

Maybe I was a bit harsh, and I lacked some explanation as to why your approach cannot compete with a somewhat complex protocol such as TLS, so let's analyze it:

1) How would you do the key exchange? For AES to work on both ends, you need to do a Key Exchange, for symmetric encryption, both parties need to possess the same key. As you said, you would like to generate it randomly on the client - so far so good. First problem - you need to generate a secure random number - otherwise, e.g. by using the built-in Javascript random number generator - attackers would be able to predict your random numbers after some time.

2) Let's say you got that mastered. Then the next problem arises, how would you send this key to the server in a secure manner, i.e. perform the key exchange? There you will need some form of authentication on the server side, otherwise just about anyone could impose as your server and do this:

  • trick people into sending their keys to their rogue server first
  • then forward the key to your server
  • your server would dutifully send the data encrypted with the established key
  • the attackers would intercept that data and happily read your secrets by decrypting with the key they just stole

3) So you need server authentication, at least, if not client authentication, too. This will imply that you need some form of asymmetric/public key cryptography to encrypt/wrap the key with the server's public key so that just the server is able to decrypt it.

4) Once you mastered that, you are still susceptible to more involved forms of attacks such as replay attacks, man-in-the-middle-attacks, reflection attacks, ...

5) Maybe you also want Perfect Forward Secrecy so that once a key does get compromised the attacker would not be capable of decrypting any past data. You will need Diffie-Hellman (preferably in its Elliptic Curve Cryptography form) to achieve this.

6) Last but not least, a session mechanism would probably also be nice so that you can pick up previous sessions with already established symmetric keys, so that you can reduce the load on the server by not having to re-establish it again using the somewhat resource-intensive public key algorithms.

-> Add a couple more features, such as securely negotiating an algorithm suite that both client and server acknowledge to support and you will have reimplemented the TLS protocol.

Sorry if this sounds a bit sarcastic, but I know it seems tempting to roll your own crypto schemes (it's fun, too), but in the end you should stick with TLS: it's (relatively) easy to use, it runs on the transport layer (so you can code your applications as if there were no encryption at all) and best of all, it's secure.

EDIT: Well, there have been some attacks recently, but almost all attacks exploited the "human factor" in these protocols by attacking the public key certificates that back the protocol (Comodo, DigiNotar etc. are prominent examples) or more arcane features of the protocol like algorithm negotiation etc., but the BEAST has been the first time that TLS has been successfully attacked on the cryptography level, which is interesting and scary at the same time, because the basics of that attack have been known for some years now.

Still, with recent fixes for BEAST in place by now, I would bet that TLS is still the best option you have for secure communication on the web, especially when compared to hand-crafted solutions.



回答2:

Ryan: I'm saying this in what I hope is the best possible way: memory consumption is the absolute least of your problems.

There is nothing secure about this. Nothing. N.o.t.h.i.n.g.

It's dead from the very first sending of that javascript... I don't care how long your keys are or how random the salt is.

What you have won't stop someone sitting in a coffee shop with their laptop open grabbing packets from intercepting the keys and being able to easily decrypt everything else you pass back and forth. Heck, just seeing the words "encrypt", "decrypt", and "key" in the stream would be enough to pique someones interest to dive further for fun (or profit..). Never mind watching an open connection suddenly start transferring parts of the packets encrypted and other parts in the clear.

If what you have is worth encrypting then it's worth the additional $240/year to do it right. Please, step back from the ledge and just do it right.



回答3:

Everyone is being so negative, and while I share the sentiment that you personally should probably not be doing this, let me make some general remarks:

For a secure channel you need three things:

  • line encryption
  • key exchange
  • authentication

For encryption, you need to implement a cipher. That's doable.

Key exchange is the crucial point: Both peers need to know that they know a common key without anyone else being able to know the common key. There exist protocols for that, and it should be possible to implement that. SSL is doing that, for example. The fact that you can sniff an SSL connection and not learn anything shows that it can be done.

Authentication is necessary to stop man-in-the-middle attacks, and this requires some sort of out-of-band information exchange (like a phone call or PKI infrastructure). Whether any of this really works practically is highly debatable, even for SSL.

So basically if you can implement all those components over HTTP, then in principle it should be possible to run secure communication over HTTP. After all, SSL is doing the same thing, it's running a secure channel over an insecure medium. Basically what you want is to implement SSL in JavaScript. Check out aSSL, they've tried something like that.



回答4:

My advice is to stick with SSL/TLS. I think this will make your life easier and also give your solution industry recognized credibility.

Instead of the static IP address, could you use DynDNS (or similar service) with a self-signed certificate?