Encryption between desktop app and server - C# to PHP
Asked Answered
L

2

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.

Lepidopterous answered 29/4, 2015 at 16:21 Comment(6)
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 : #4484746Haworth
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.Allometry
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 understandLepidopterous
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?Lepidopterous
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.Luce
so sad the OP gets a downvote :(Borodin
M
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();
                }
            }
        }
    }
}
Moorehead answered 7/5, 2015 at 19:15 Comment(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.Classless
W
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.

Waligore answered 1/5, 2015 at 18:15 Comment(3)
You might also take a look at startssl.com , they're offering SSL certificates for free.Albright
@mine Awesome, thanks for mentioning that website! I didn't know about it.Waligore
You're welcome. There's also the initiative letsencrypt.org , which aims at encrypting everything, but I think this is not related to this topic anymore.Albright
M
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();
                }
            }
        }
    }
}
Moorehead answered 7/5, 2015 at 19:15 Comment(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.Classless

© 2022 - 2024 — McMap. All rights reserved.