Im trying to figure out what the best way to encrypt data sent between a webpage and the user(both ways) is, when hosted in an environment that doesn't support SSL. The purpose of encryption would be obscuring content for delivery through filters that aid in internet censorship. What ways would that be possible to acomplish for normal visitors without any effort on their part?

Any steering you guys could provide is greatly appreciated, Thanks!

  • 5
    $\begingroup$ What kind of "environment" is there which doesn't support SSL, but does support other kinds of encryption? Do you have filters which block SSL, or is your hardware not good enough to handle the crypto? $\endgroup$ – Paŭlo Ebermann Nov 9 '11 at 15:08
  • $\begingroup$ In the Internet layer model, TLS is usually located between TCP and the application. If the filter just checks for this specific structure, you can circumvent it, by placing some other frame around the actual TLS messages, e.g. making it look like HTTP requests and responses, where you embedd the actual TLS communication in something else (pictures, input fields of forms, etc.) $\endgroup$ – tylo Sep 29 '14 at 13:21
  • 1
    $\begingroup$ It would be in an environment that specifically blocks ssl traffic, e.g. from within parts of China. $\endgroup$ – Jayhal Oct 1 '15 at 16:24

There is no easy way to do this in a secure manner. Simply obscuring the content will give you no additional security. I'll give you an overview of the possible ways to realise such a system, and then I'll conclude by telling you why they don't work well enough, unfortunately.

Key-Exchange protocols and encryption

The basic idea of these protocols is to securely exchange a secret (the shared secret) and use it to encrypt communication.

First approach (flawed, as we'll see)

  • Have both parties participate in a Diffie-Hellman key exchange

    • Both agree on $G$ and $P$ (see RFC 3526)
    • Both generate a random value $X$.
    • Both exchange public value $Y = G^X \mod P$
    • With each other's $Y$, they generate secret key: $K = Y^X \mod P$
  • Now that both parties share a secret, use AES encryption (for instance) to encrypt the data being transmitted, using the shared secret to derive an AES encryption key.

This is easily implemented in JavaScript.

The great problem with this approach is that it's susceptible to a Man-in-the-middle attack. Unless you add some form of authentication, for instance using a pre-shared key, an attacker would simply intercept and relay the comunication: Alice ←→ Eve ←→ Bob. The Communication between Alice and Eve, and between Eve and Bob is now secure, the communication between Alice and Bob isn't.

Possible fix:

If there is a shared secret, one that is either transmitted securely through some other means or shared beforehand, you can authenticate messages using a Message authentication code.

This "solution" however isn't very good. It basically means:

In order to exchange a secret, first exchange a secret.

Which in practice means this approach will typically lead to an insecure crypto-system. This also happens to be the main problem with One-Time Pads.

You could use asymmetric keys for this, and build a Public Key Infrastructure to overcome this limitation, but then you'd basically implement almost all of SSL. It's worth mentioning again that 99% of security flaws are caused by mistakes in the implementation, rather than insecure protocols.

Second approach (totally doable, reasonably complicated)

We saw that the basic problems comes down to exchanging a secret. In order to authenticate both parties to each other (this is important, authenticating the client isn't enough!), we can use a password. This way, we can exchange a secret and know that we exchange it with the right person.

An example of a protocol designed for this purpose is the Secure Remote Password protocol (SRP). I'll not explain the protocol here, wikipedia does a far better job doing that.

Third approach, just implementing SSL

You could also basically implement SSL using your server-side language and JavaScript on the client. Now, SSL is quite complicated. The probability of a programming error leading to an insecure cryptosystem is very high.

It also requires you to have your own public key infrastructure. Meaning your clients have to get the right keys in order to communicate with your server.

In practice

This kind of thing is almost never done in practice. There are systems like Kerberos which, using a special key server, implement this kind of approach for client-server communication in closed networks, but I've never encountered anything like it on the world wide web.

  • If you just want to avoid being detected by Deep packet inspection, merely obfuscating the data will be enough. But you have to obfuscate at the TCP level, which normally means re-implementing whole protocols.

  • If you have to safeguard against decryption or de-obfuscation of your data after the fact, you need to use proper encryption that provides a few properties:

    • Authentication (you know exactly who you're talking to, both client and server)
    • Encryption (your communication is secret)
    • Perfect forward-secrecy (compromise of the long-term keys [like RSA keys] does not lead to a compromise of the short-lived encryption keys, i.e. does not compromise your past communications [this is the huge problem with PGP encrypted instant messaging])
    • Malleability (adversaries can easily fake the transcript of your messages after the fact, so that your scheme now provides deniability).

One protocol which provides all of these is Off-The-Record Messaging (OTR). This is a fantastic protocol, it's used for Instant Messaging however, not for web-pages.


I think I've taken more than enough of your time to demonstrate: there isn't an accepted or appropriate way to do it. But you can fiddle about until you find something that fits your (watered down) attack scenario. The Secure Remote Password protocol is the best way of doing this.

It will be much easier, and well worth your time and effort, to just change the rest of the system so that you can implement real SSL. That's the right way to do it.

  • 4
    $\begingroup$ Also, if the client JavaScript comes from the server over a non-authorized connection, there is no way to be sure that it hasn't been meddled with by the attacker, which makes all the secure protocols moot. See Javascript Cryptography Considered Harmful. $\endgroup$ – Paŭlo Ebermann Nov 9 '11 at 15:12

Actually, NoSSL has been created exactly for this purpose. It is open source and free.

You can download it here: http://www.nossl.net

  • $\begingroup$ -1 This looks more like spam than an answer. Besides that, let me quote the NoSLL website, first line of the first paragraph: “NoSSL is not a replacement for SSL certificates and other means to protect your website against intrusion.” (emphasis theirs, not mine) Also, on that same page near the end of the page, section “Man-in-the-middle attack”, they state: “…it has to be mentioned again that NoSSL is not a replacement for SSL…” In short, that renders your somewhat spammy, low-quality answer practically useless. $\endgroup$ – e-sushi Sep 23 '14 at 22:27
  • 1
    $\begingroup$ @e-sushi This doesn't look like spam because it's arguably on-topic and the OP does not appear to be affiliated with nossl. This looks like someone misread the question, or nossl's website. The rest of your comment is quite helpful though. $\endgroup$ – rath Sep 28 '14 at 13:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.