15

I have an app which is designed in C#. In simple terms the app sends data and image to my web server which takes all the $_POST data and processes it. I will confess i do not understand how the security end of things work. I will employ someone with relevant experience to do that however i wouldn't even know what to ask them at this point as in what are some accepted techniques.

I assume its not as simple as just base64 encode/decode the data and it needs a higher level of encryption. The webserver will have HTTPS SSL(OV) certification over the next few weeks but my limited understanding is that i still need some sort of protection/encryption when transferring the data from the users PC to my web server so someone is not listening in on the data transfer or something like that.

In simple terms if i want to keep the data secure between users and my webserver what are some of the most common or accepted methods for C# to PHP?

The data goes directly from the app on the users PC to my server, i control source code for both but i myself and not the developer hence my lack of technical knowledge on the issue.

One C# developer i talked with suggested symmetric/asymmetric algorithm but he is not a PHP developer so he doesn't know if php can take that data and decrypt it.

user1547410
  • 863
  • 7
  • 27
  • 58
  • If you're worried that someone will listen while the data is being transferred, HTTPS (SSL/TLS) will take care of the encryption during the transport of the data. If you care about someone intercepts the data before/after it is transferred, asymmetric encryption is the way to go. In this case, you might be interested in this post : http://stackoverflow.com/questions/4484246/encrypt-and-decrypt-text-with-rsa-in-php – Irwene Apr 29 '15 at 16:25
  • 2
    As a general rule, if you are wondering whether to implement your own crypto, then the answer is most likely "no". Your best bet is probably TLS. – wallenborn Apr 29 '15 at 16:28
  • 2
    Thanks for the feedback guys, Wallenborn, you say TLS is probably my best bet, it sounds like from what i read TLS/SSL are the same thing just different terms so sounds like both suggestions are for SSL. What i dont understand due to my limited knowledge is how SSL works in this context, my understanding goes as far as to implement SSL you have to install a certificate on your server but what i dont understand is if you want to send it from the desktop app do i need to install the same certificate within the desktop app also. What i dont understand – user1547410 Apr 29 '15 at 18:14
  • Also is it true to say that if i want high protection and peace of mind for my users i should also do asymmetric encryption or does SSL also cover this? – user1547410 Apr 29 '15 at 18:16
  • this is what https is for. if you are extra paranoid, you can encrypt the data with a shared secret between your app and the web server. –  May 02 '15 at 14:29
  • so sad the OP gets a downvote :( – Ceeee May 07 '15 at 09:16

2 Answers2

11

It seems you are concerned with the security of the data while being transferred from the client app to the server, and vice versa. As has been mentioned in the comments, an HTTPS connection will be sufficient in this regard. It automatically performs encryption/decryption for you.

To get an HTTPS connection working, you would purchase an SSL certificate (Namecheap is one website where you can buy one) and install it on your web server. The certificate is automatically installed on a user's local machine the first time he/she connects to the server, and each subsequent connection performs a check for a valid certificate. So basically, you just install the certificate on the server and don't have to worry about it until you have to renew your certificate. Just make sure that your client app attempts to connect to an HTTPS address instead of an HTTP.

If you were to implement symmetric/asymmetric encryption, it would help with encryption and decryption before and after the data is transferred. If you encrypt the data in your client app, you will have to decrypt it on the server side when you receive it, and vice versa. This would provide you with even stronger security; however, depending on the nature of your app, an HTTPS connection may be enough.

One of my personal projects is a client C# app that connects to a Ruby web server, which I also wrote. I installed an SSL certificate on my Ruby web server so that data is encrypted while in transit. In my case, the data being transferred does not contain any user data or PII (Personally Identifiable Information) and therefore does not pose a security risk if an external party gains access to this information. As such, I felt using encryption before and after transit was not worthwhile nor would provide any benefit to the end user. Again, this depends on the nature of your app and your users' expectations.

EDIT:

As mine mentioned in the comments, StartSSL offers free SSL certificates.

Community
  • 1
  • 1
Alexander
  • 3,959
  • 2
  • 31
  • 58
  • 1
    You might also take a look at http://www.startssl.com/ , they're offering SSL certificates for free. – michaeln May 02 '15 at 14:44
  • @mine Awesome, thanks for mentioning that website! I didn't know about it. – Alexander May 02 '15 at 18:10
  • 1
    You're welcome. There's also the initiative https://letsencrypt.org/ , which aims at encrypting everything, but I think this is not related to this topic anymore. – michaeln May 02 '15 at 20:22
4

To answer your further questions, when a server is issued and properly configured with a good cert, you shouldn't need to do anything more.

Using HTTPS

HTTPS works by verifying SSL certifications with a Certificate Authority (CA) during an initial handshake. Certificate Authorities, which is essentially a list of signatures that are used to verify said certs, usually come preloaded by an OS vendor.

Assuming your server has a CA issued certificate, all you will be required to do is change from using HTTP to HTTPS when making the connection. The library you're using should have a method of verifying the servers SSL cert, if it doesn't automatically do this for you.

There is no technical reason that you should have to encrypt anything that will being sent over HTTPS, so long as the certificate is strongly encrypted.

Also, if you would like to dig deeper into the nitty-gritty details of how HTTPS works, there's this very good post over on Information Security that sheds a little light on the inner workings of the protocol.

To answer your original question

For the sake of completeness.

PHP has the cryptography extension mcrypt which supports various algorithms and cipher operation modes. I've put together a simple example using AES 256 / PBKDF-SHA1 key decryption (along with the C# code to perform the encryption).

EDIT: I'd like to point out that hash_pbkdf2 is only available in PHP 5.5 and up. Support down to 5.3 can be added with this nifty trick.

PHP

function decode_aes($data, $key) // Decrypt custom format data string
{
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $salt_size = 16;

    $iv = substr($data, 0, $iv_size); // Init vector
    $salt = substr($data, $iv_size, $salt_size); // The salt
    $extact = substr($data, $iv_size + $salt_size); // This is the encrypted data

    $key = hash_pbkdf2("sha1", $key, $salt, 1000, 32, true); // Sets to use PBKDF-SHA1

    return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $extact, MCRYPT_MODE_CBC, $iv); // Perform the decryption with the extracted sections
}

// As an example, I've included this.
$encryped = "zgCp2sSDs32Y8SOn8MYFCEjOJDeM4E3Y8Wx52A+iTFRk/1TJwMzkqmrB06bFu8dK";
echo decode_aes(base64_decode($encryped), "password");

C#

using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace AESExample
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] toEncrypt = Encoding.UTF8.GetBytes("Encrypted Text");
            byte[] key = Encoding.UTF8.GetBytes("password");
            String encrypted = Convert.ToBase64String(EncryptAES(toEncrypt, key));
        }

        public static byte[] EncryptAES(byte[] data, byte[] key)
        {
            using(RijndaelManaged algo = new RijndaelManaged())
            {
                algo.GenerateIV();
                algo.Mode = CipherMode.CBC;
                algo.Padding = PaddingMode.Zeros;

                byte[] saltBuffer = new byte[16];
                RNGCryptoServiceProvider saltGenerator = new RNGCryptoServiceProvider();
                saltGenerator.GetBytes(saltBuffer);

                Rfc2898DeriveBytes PBKDF2 = new Rfc2898DeriveBytes(key, saltBuffer, 1000);
                key = PBKDF2.GetBytes(32);

                ICryptoTransform cipher = algo.CreateEncryptor(key, algo.IV);

                using(MemoryStream ms = new MemoryStream())
                {
                    ms.Write(algo.IV, 0, algo.IV.Length);
                    ms.Write(saltBuffer, 0, saltBuffer.Length);
                    using(CryptoStream cs = new CryptoStream(ms, cipher, CryptoStreamMode.Write))
                    {
                        using(StreamWriter sw = new StreamWriter(cs))
                        {
                            sw.Write(Encoding.UTF8.GetString(data).ToCharArray());
                        }
                    }
                    return ms.ToArray();
                }
            }
        }
    }
}
Community
  • 1
  • 1
Bryan Way
  • 1,903
  • 3
  • 17
  • 27
  • 1
    This is definitely the more complete answer. Yes, trying to write your own Crypto will usually make your app more insecure, but, HTTPS itself isn't enough security for some applications, and you certainly won't make the app more insecure by using crypto *in addition* to HTTPS. Client-side certificates can help make HTTPS alone a more viable option as well. – Will May 08 '15 at 06:59