2016-02-17 3 views
1

Мое положение: Я переписываю сервер в C#, который был написан на C++ для учебных целей. В какой-то момент клиент отправит пароль на сервер, который зашифрован. Они использовали шифрование Rijndael для пароля. Вы можете найти исходный класс шифрования здесь:Rijndael: шифрование на C++, дешифрование C#

Rijndael.h: https://github.com/astorks/FlyFF/blob/master/Source/_Common/Rijndael.h

Rijndael.cpp: https://github.com/astorks/FlyFF/blob/master/Source/_Common/Rijndael.cpp#L926

Как вы можете видеть в .cpp-файле, они используют этот ключ и IV:

char const* CRijndael::sm_chain0 = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 

char szDefaultKey[32] = "dldhsvmflvm"; 

Вот часть, где они на самом деле расшифровать пароль в исходном сервере (https://github.com/astorks/FlyFF/blob/master/Source/CERTIFIER/DPCertifier.cpp#L256)

// MAX_PASSWORD is actually 42. So 16*42 = 672 byte 
char szEnc[ 16 * MAX_PASSWORD ] = {0, }; 
char szDec[ 16 * MAX_PASSWORD ] = {0, }; 

ar.Read(szEnc, 16 * MAX_PASSWORD); 

g_xRijndael->ResetChain(); 
g_xRijndael->Decrypt(szEnc, szDec, 16 * MAX_PASSWORD, CRijndael::CBC); 

Теперь я нахожусь в той части, где я правильно получаю пакет от клиента и где мне нужно расшифровать пароль. Мой текущий код C# не расшифровывает данные правильно, и я не могу понять, почему. Это мой код:

public static class Rijndael 
    { 
     private static ICryptoTransform decryptor { get; set; } 
     private static RijndaelManaged rijndael { get; set; } 

     public static void Init() 
     { 
      byte[] decryptKey = Encoding.ASCII.GetBytes("dldhsvmflvm").Concat(Enumerable.Repeat((byte)0, 21).ToArray()).ToArray(); 
      byte[] decryptIV = Enumerable.Repeat((byte)0, 16).ToArray(); 
      // I've tried BlockSize 128 and 256. It actually should be 128 since it's 16 on the original server (16 * 8 = 128) 
      rijndael = new RijndaelManaged() { Padding = PaddingMode.Zeros, Mode = CipherMode.CBC, KeySize = 256, BlockSize = 128, Key = decryptKey, IV = decryptIV }; 
      decryptor = rijndael.CreateDecryptor(decryptKey, decryptIV); 
     } 


     public static string decrypt(byte[] data) 
     { 
      string password = null; 
      using (MemoryStream ms = new MemoryStream(data)) 
       using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) 
        using (StreamReader sr = new StreamReader(cs)) 
         password = sr.ReadToEnd(); 
      return password; 
     } 
    } 

Они выбрали 32 байт на ServerSide, но заполняется только их 11 символов: dldhsvmflvm. Вот почему я заполняю остальные 21 байты 0. 32 * 8 = 256 бит = KeySize

Я получаю сообщение об ошибке, когда я буду использовать IV как байт [32] и залейте его 0. Это сказало smth, как IV не соответствует размеру блока. Вот почему он имеет 16 байтов и заполнен 0. Может ли это быть проблемой, и если да, то как я могу это исправить?

Кроме того, я понятия не имею, что может пойти не так. Надеюсь, вы сможете сэкономить мой день, Stackoverflow. :)

+0

Можете ли вы проверить, действительно ли значения IV и Key идентичны как в C++, так и в коде C#? –

+2

Блокировка по умолчанию CRijndael составляет 128 бит, поэтому 16 байт, поэтому IV должен иметь длину 16 байтов. (см. 'void MakeKey (char const * key, char const * chain, int keylength = DEFAULT_BLOCK_SIZE, int blockSize = DEFAULT_BLOCK_SIZE)', где 'enum {DEFAULT_BLOCK_SIZE = 16}', а 'MakeKey' вызывается' CRijndael: : CRijndael() 'с' MakeKey (szDefaultKey, CRijndael :: sm_chain0); ', поэтому с параметрами по умолчанию.) – xanatos

+2

Обратите внимание, что даже длина ключа должна быть 16.' CRijndael' не использует 'sizeof (char [ 32]) или аналогичные. Он знает длину ключа из параметра 'MakeKey', поэтому попробуйте' Enumerable.Repeat ((byte) 0, 5) ' – xanatos

ответ

1

Как xanatos сказал, что я добавил вместо 5 вместо 5 нулей, потому что они должны быть только 16 байт вместо 32 байтов. Теперь он работает без проблем. Спасибо всем!

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