无法解密第二台计算机上的数据

时间:2014-04-17 03:17:51

标签: c# encryption cryptography

我有两个应用程序,Server和Client,一个从一台机器运行,另一个从第二台机器运行,服务器使用WebSocket连接传递数据,数据在发送到Client之前加密,数据正确地将它发送到客户端应用程序,但我尝试使用相同的安全方法和密钥来解密它,但我不会工作,它只会在两个应用程序从同一台计算机运行时解密它。有没有人知道为什么它们在同一台机器上运行时有效,而不是从不同的机器上运行时呢?

服务器和客户端应用程序都使用相同的安全方法。

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

要加密我使用的服务器上的数据:

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

解密客户端上的数据我使用

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

同样,当我同时使用来自同一台计算机的服务器和客户端应用程序时,这一切都可以正常工作,但我尝试将它们分开使用,一台机器上的服务器,另一台机器上的客户端不能解密数据,即使客户端成功收到加密数据。

请帮忙!

感谢。

2 个答案:

答案 0 :(得分:5)

您正在使用System.Security.Cryptography.ProtectedData类,其中使用了Data Protection API (DPAPI)。 DPAPI加密密钥在每台计算机上始终是唯一的,因此当您加密计算机A上的数据时,您使用密钥A,当您尝试解密计算机B上的数据时,您使用密钥B. DPAPI提供symmetric cipher的接口只有这样才能成功解密数据,您需要使用完全相同的密钥进行加密和解密。

我相信你应该改变你的代码以使用不同的加密算法,即AES(由System.Security.Cryptography.AesManaged类实现),这将允许你在两台不同的机器之间共享密钥。

答案 1 :(得分:2)

ProtectUnprotect方法are only making calls to the DPAPI,只有在启用了漫游配置文件的情况下才能在计算机上运行,​​并且只有under certain circumstances

相反,使用具有您自己管理的会话密钥的算法(AESothers...),或者更好:使用TLS作为您的WebSocket(wss://)或套接字传输( SslStream)。滚动你自己的加密只是在惹麻烦。