2014-04-17 3 views
2

У меня есть два приложения: сервер и клиент, один из которых выполняется с одного компьютера, а другой - со второго компьютера, сервер передает данные с помощью соединения WebSocket, данные зашифровываются раньше отправленные клиенту, данные вносят его в клиентское приложение, но я пытаюсь его расшифровать с использованием того же защищенного метода и секретного ключа, но я не буду работать, он только расшифровывает его, когда оба приложения запускаются из такой же компьютер. Кто-нибудь знает, почему это работает, когда они запускаются с одного и того же компьютера, но не при запуске их с отдельных машин?Невозможно расшифровать данные на втором компьютере

Оба сервера и клиентского приложения используют этот же защищенный метод.

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); 

Опять же, все это прекрасно работает ТОЛЬКО когда я использую серверные и клиентские приложения с одного и того же компьютера, но я пытаюсь использовать их отдельно, сервер на одной машине , а Клиент по другому не расшифровывает данные, даже если клиент успешно получает зашифрованные данные.

Пожалуйста, помогите!

Спасибо.

+0

Вы уверены, что сообщение получено в неповрежденном состоянии на другом конце? – spender

+0

просто догадка. <значения machineKey в файле web.config разные. если у вас нет машинного ключа, тогда сервер может генерировать его автоматически. Поэтому, если клиент и сервер одинаковы, он использует тот же машинный ключ, но на разных машинах он может использовать разные машинные клавиши ... попробуйте установить постоянный машинный ключ .. см. Http://aspnetresources.com/tools/machineKey – robert

ответ

5

Вы используете System.Security.Cryptography.ProtectedData класс, который использует Data Protection API (DPAPI) под капотом. Клавиши шифрования DPAPI всегда уникальны на каждом компьютере, поэтому, когда вы шифруете данные на компьютере A, вы используете ключ A, и когда вы пытаетесь расшифровать данные на компьютере B, вы используете ключ B. DPAPI предоставляет интерфейс для symmetric cipher только так, чтобы чтобы дешифровать данные успешно, вам нужно использовать точно такой же ключ для шифрования и дешифрования.

Я считаю, что вы должны изменить свой код, чтобы использовать другой алгоритм шифрования, то есть AES (реализованный классом System.Security.Cryptography.AesManaged), который позволит вам разделить ключ между двумя разными машинами.

+0

Спасибо @jariq I Я попробую это – AJ152

+0

Это помогло, спасибо – AJ152

2

В Protect и Unprotect методы are only making calls to the DPAPI, который работает только на разных компьютерах, если вы включили перемещаемые профили, и только потом under certain circumstances.

Вместо этого используйте алгоритм с ключом сеанса, который вы управляете самостоятельно (AES, others...), или еще лучше: использовать TLS в качестве WebSocket (wss://) или торцевым транспорта (SslStream). Прокручивание собственного криптограммы просто требует неприятностей.

Смежные вопросы