4

I have two applications, Server and the Client, one running from one machine, and the other from a second machine, the server is passing data using a WebSocket connection, the data is encrypted before is sent to the Client, the data makes it to the Client application correctly but I'm trying to Decrypt it using the same secure method, and Secret Key, but I won't work, it only decrypts it when both apps are run from the same computer. Does any one have any idea why it works when they are run from the same machine, but not when running them from separate machines?

Both Server and Client application use this same Secure Method.

using System.Security.Cryptography;

// ENCRYPT

static byte[] entropy = System.Text.Encoding.Unicode.GetBytes("MY SECRET KEY HERE");

public static string EncryptString(System.Security.SecureString input)
{
    byte[] encryptedData = System.Security.Cryptography.ProtectedData.Protect(
        System.Text.Encoding.Unicode.GetBytes(ToInsecureString(input)),
        entropy,
        System.Security.Cryptography.DataProtectionScope.CurrentUser);
    return Convert.ToBase64String(encryptedData);
}

public static SecureString DecryptString(string encryptedData)
{
    try
    {
        byte[] decryptedData = System.Security.Cryptography.ProtectedData.Unprotect(
            Convert.FromBase64String(encryptedData),
            entropy,
            System.Security.Cryptography.DataProtectionScope.CurrentUser);
        return ToSecureString(System.Text.Encoding.Unicode.GetString(decryptedData));
    }
    catch
    {
        return new SecureString();
    }
}

public static SecureString ToSecureString(string input)
{
    SecureString secure = new SecureString();
    foreach (char c in input)
    {
        secure.AppendChar(c);
    }
    secure.MakeReadOnly();
    return secure;
}

public static string ToInsecureString(SecureString input)
{
    string returnValue = string.Empty;
    IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
    try
    {
        returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
    }
    finally
    {
        System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
    }
    return returnValue;
}

// ENCRYPT ENDS

To Encrypt data on the Server I use:

string encryptedMessage = EncryptString(ToSecureString("Data to Encrypt Here"));

To Decrypt data on the Client I use:

SecureString data1 = DecryptString(dataEncryptedReceived);
IntPtr stringPointerData1 = Marshal.SecureStringToBSTR(data1);
string normalStringData1 = Marshal.PtrToStringBSTR(stringPointerData1);
Marshal.ZeroFreeBSTR(stringPointerData1);

Again, this all works fine ONLY when I use both Server and Client applications from the same computer, but I try to use them separate, Server on one machine, and Client on another it won't Decrypt the data, even though the Client receives the encrypted data successfully.

Please help!

Thanks.

AJ152
  • 671
  • 2
  • 12
  • 28

2 Answers2

8

You are using System.Security.Cryptography.ProtectedData class that uses Data Protection API (DPAPI) under the hood. DPAPI encryption keys are always unique on each computer therefore when you encrypt data on computer A you are using key A and when you try to decrypt the data on the computer B you are using the key B. DPAPI provides interface to symmetric cipher only so in order to decrypt the data successfully you need to use exactly the same key for both encryption and decryption.

I believe you should change your code to use different encryption algorithm i.e. AES (implemented by System.Security.Cryptography.AesManaged class) that will allow you to share the key between two different machines.

jariq
  • 11,681
  • 3
  • 33
  • 52
2

The Protect and Unprotect methods are only making calls to the DPAPI, which only works across computers if you have roaming profiles enabled, and only then under certain circumstances.

Instead, use a algorithm with a session key which you manage yourself (AES, others...), or better yet: use TLS as your WebSocket (wss://) or Socket transport (SslStream). Rolling your own crypto is just asking for trouble.

Mitch
  • 21,223
  • 6
  • 63
  • 86