3

i have a C# program which makes HTTP PUTs from one server, to another Server which runs (XS)JS. The content type which i am sending is JSON. This is already working fine.

Now i need to work on the security, but i have no idea where to start here. Can someone point in the right direction?

What do i need to use sending over the internet? AES256, Rijndael, i dont even know in which direction to look. Also the JS needs to be able to decrypt it afterwards.

Thanks in advance!

Kulu
  • 111
  • 10
  • 4
    What is wrong with HTTPS? I think you should be more concerned with transport encryption than content encryption. – DaSourcerer May 13 '16 at 17:47
  • Hello, i dont know anything about encryption. The examples i gave were just what i know about. What do i have to do to use HTTPS? Are there special libraries or is it built in C#? – Kulu May 13 '16 at 21:13
  • 1
    Are you using `HttpWebRequest`? It speaks SSL/HTTPS natively. – DaSourcerer May 13 '16 at 21:18
  • Yes i am using HttpWebRequest. So maybe i am already using HTTPS. So should i worry about content encryption at all or is transport encryption fine enought when i control both the sending and the receiving servers? @DaSourcerer – Kulu May 14 '16 at 19:36
  • Preparing a full answer. A bit of a warning: It's complex and really depends on what you need and what you are willing to learn. – DaSourcerer May 14 '16 at 20:35
  • Sorry it took so long. But as I said: it's a complex topic and I had quite a lot to type :/ – DaSourcerer May 15 '16 at 16:11
  • @DaSourcerer Thank you really much for this detailed answer. It will take some time for me to read and understand everything. I will keep you update on what happened :) – Kulu May 15 '16 at 16:29
  • Feel free to ask new questions on SO and security.stackexchange.com anytime! I think I'll have to go over my answer tomorrow one more time to eliminate any typos :D – DaSourcerer May 15 '16 at 16:32

2 Answers2

1

Let's start with a quote:

Bad crypto is worse than no crypto, because it gives the user the mistaken impression that their data is secure.
    Jimm Gillogly, April 19th 2000 on cryptography@senator-bedfellow.mit.edu

That is not to discourage you; rather a reminder to tread lightly: Applying proper cryptography is quite a challenge and men smarter than you and I together have shot themselves in the foot unknowingly in the most spectacular ways.

From what I could gather, I am really under the impression you are indeed in need of transport rather then content encryption. But one step after the other:

Content Encryption

If you employ content encryption, you are aiming at keeping the content of your communication a secrete while still allowing the metadata (who spoke with whom at which time about what?) to be sniffed.

In doing so, you will need to establish

  1. a common encryption scheme on your client and you server, and
  2. a common secret on client and server used to encrypt your messages

The last point is a weak point as you need to exchange the key securely. This requires a secure communication channel, which used to be a chicken-and-egg-problem until the rise of the Diffie-Hellman Key Exchange method, which allowed for the secure exchange of a shared secret oder an insecure channel. You will see this method being mentioned often, so memorize it.

The nature of the encapsulated request/response communication here is asking for the application of a so-called block cipher. Block ciphers - in contrast to stream ciphers - can be decrypted with the same secret again and again. The obvious disadvantage is that should your secret be compromised, all intercepted messages will no longer be a secret. Unless you have been negotiating a new secret for each round of communications, that is.

Rijndael/AES (AES is a standard while Rijndael is a family of ciphers used by said standard) can be used in ECB- or CBC-mode which is providing just that. CBC is to be preferred as it is safe against replay attacks. If replay attacks are none of your concern, choose CBC regardless: You will fance the extra security that comes with little overhead.

AES ist actually a good fit for another reason: Many modern CPUs have hardware AES-support built-in, which used to be something that went into separate hardware crypto accelerator cards. On a practical note, if you choose to implement this via JavaScript (or a js library), you are not going to take advantage of this.

Another concern is the bitlength of the chosen secret. You may have stumbled upon AES-128 or AES-256: That number is referring to the keysize in bits. There is an ongoing discussion about the relation between keysize and protection level. In recent years, there have been a number of theoretical attacks that battered the effective keylength of AES-256 below that of AES-128. In practice, this has little effect as AES is still incredibly strong. Regardless of the chosen keylength, at the current technological level you will rather see the sun extinguish than having AES cracked. A 128bit key may see better hardware- and software support, though. So AES-128-CBC, AES-192-CBC, or AES-256-CBC are your choices here. Ask on security.SE for advice if you like to see it go up in flames :)

If you feel AES isn't right for you, have a look at Twofish which missed inclusion into AES. It is seeing actual use in OpenPGP, yet lacks library support.

So in conclusion we have here:

  • AES is actually a solid choice
    • the lib mentioned by Michael has support for it
    • Choose CBC-mode over ECB
  • No protection of metadata
  • Extra roundtrip for key exchange
  • No hardware acceleration

None of this is a k.o.-criterium but should be kept in the back of your head.

Transport Encryption

Going a step further, we end up with encrypting not the message content but the way the message is exchanged: by encrypting the communication channel itself. In the past, this has been implemented through SSL, the Secure Socket Layer. It has been superseded now by Transport Layer Security while still being occasionally referred to as SSL (don't allow that to confuse you!).

TLS works by letting the peers negotiate a common cipher followed by a key exchange (often akin to the Diffie-Hellman method mentioned earlier). This is done in cleartext, which should not really concern you. All the application protocol data is going to be encrypted. And while we're at it: AES is among the negotiable ciphers. It is more likely to be in a stream cipher mode, though.

As far as confidentiality goes, attackers will still be able to pick up who communicated when with which host. There weill be little to no indications on what has been communicated as the full URL is already in the encrypted part.

As you may have noticed by now, HTTP over SSL/TLS (commonly known as HTTPS) is an established standard with remakably little interoperability issues. In fact, you are visiting this very site over it :)

As you are using .NET's WebRequest, you are in luck as it already features HTTPS support:

If the scheme for the Uniform Resource Identifier (URI) is http:// or https://, Create returns an HttpWebRequest object.

As far as the HANA XS Engine goes, I know it supports SSL but it seems to be tied to proprietary crypto libs. It seems to me as if it were less troublesome (and safer) to configure as a reverse proxy to handle the SSL/TLS-part.

Having said that, here's an issue with this worth mentioning: HTTP is working hop-by-hop, which means you cannot tell if you are speaking HTTP to an originating server or just an intermediary. HTTPS helps to a point as you can pinpoint the end of the SSL/TLS tunnel:

An important aspect of SSL/TLS is that each peer is keeping a set of keys: One public and one private. They play a vital part in the key exchange, but the public keys can also be used to identify a peer (or at least the hostname-pubkey pairing). This allows to identify man-in-the-middle attacks as early as in the negotiation phase, so no confidential informations is leaked.

Having said that, you have not mentioned whether your endpoint is public or not. If so, you may not want to use a self-signed certificate (i.e. a pair of public and private keys you issued for yourself with no other party involved). Browservendors tend to ship lists of trusted certificate issuers who go to some length to ensure a certificate is not issued for just some domain, but for a domain under the control of whoever wishes to issue a certificate for said domain.

If your certificate has not been sanctioned ("signed") by any of the listed issuers, you will face interoperability issues as browsers tend to spew out warnings and fully automated clients may very will quit service alltogether for security reasons. You can get free certificates through the following services:

The general approach is to generate a private key, create a certificate signing request (CSR) to it, submit this CSR to an issuer of your choice and receive a signed public key. Let's Encrypt has this somewhat automated, so you may find that easier to use. The OpenSSL library has extensive documentation but may be difficult to read for someone new to the topic.

If you are sufficiently advanced, you can try to tackle more advanced techniques such as OCSP stapling, Strict HTTP Transport Security, and HTTP Public Key Certificate Pinning. All of which will help you tightening the security of your TLS/SSL setup. Though for the start, see to it you have a reasonable list of ciphers set up for negotiation and test your setup for obvious errors.

To summarize:

  • Established and well-tested solution
  • Very likely hardware acceleration
  • little to no interoperability issues if (when) you open your API to the public
  • Metadata is kept largely a secret
  • Establishing end-to-end message confidentiality is a challenge to enforce

As I said earlier, I really feel transport encryption is the way to go for you. After all, it is faster and (in comparison) easier to set up and maintain. You may be tempted to combine the two methods: that may not necessarily be a good idea. Recall the quote from the beginning.

Community
  • 1
  • 1
DaSourcerer
  • 6,288
  • 5
  • 32
  • 55
-1

There are loads of js libraries that deal with encryption/decryption. The encryption algorithms are vast for a reason and each of them serves a different purpose. You need to decide how important the information is to protect vs how long it takes to encrypt/decrypt the data. I have only used the Google library Crypto-js and it works like a charm. https://code.google.com/archive/p/crypto-js/ I would also advise to use transport encryption (https) as well as it will be harder to crack than something you write yourself. You can create a self-signed certificate for that too.