Кросс-платформенный (php-C # .NET) шифрование / дешифрование с помощью Rijndael

В настоящее время у меня проблема с расшифровкой сообщения, зашифрованного php mcrypt. Код php выглядит следующим образом:

<?php //$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); $iv = "45287112549354892144548565456541"; $key = "anjueolkdiwpoida"; $text = "This is my encrypted message"; $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv); $crypttext = urlencode($crypttext); $crypttext64=base64_encode($crypttext); print($crypttext64) . "\n<br/>"; ?> 

Зашифрованное сообщение затем отправляется на платформу ASP.NET (C #). Тем не менее, у меня проблема с сохранением порядка дешифрования (base64 decode to urldecode). Код, который я имел в ASP.NET, выглядит следующим образом (iv и ключ такой же, как и в php):

 public string Decode(string str) { byte[] decbuff = Convert.FromBase64String(str); return System.Text.Encoding.UTF8.GetString(decbuff); } static public String DecryptRJ256(string cypher, string KeyString, string IVString) { string sRet = ""; RijndaelManaged rj = new RijndaelManaged(); UTF8Encoding encoding = new UTF8Encoding(); try { //byte[] message = Convert.FromBase64String(cypher); byte[] message = encoding.GetBytes(cypher); byte[] Key = encoding.GetBytes(KeyString); byte[] IV = encoding.GetBytes(IVString); rj.Padding = PaddingMode.Zeros; rj.Mode = CipherMode.CBC; rj.KeySize = 256; rj.BlockSize = 256; rj.Key = Key; rj.IV = IV; MemoryStream ms = new MemoryStream(message); using (CryptoStream cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Read)) { using (StreamReader sr = new StreamReader(cs)) { sRet = sr.ReadToEnd(); } } } finally { rj.Clear(); } return sRet; } string temp = DecryptRJ256(Server.UrlDecode(Decode(cypher)), keyString, ivString); 

Проблема, с которой я столкнулась, заключается в том, что после того, как я получил зашифрованное сообщение от php, я преобразовал его в байт [], а затем преобразовал обратно в кодированную строку UTF8, чтобы я мог urldecode. то я передаю результат в функцию, где я преобразовал строку обратно в байт [] и запускал ее через процесс дешифрования. Однако я не могу получить желаемый результат … любые идеи?

Заранее спасибо.

Solutions Collecting From Web of "Кросс-платформенный (php-C # .NET) шифрование / дешифрование с помощью Rijndael"

Здесь я вижу проблемы с обеих сторон.

Имейте в виду, что то, что вы получаете, когда кодирование не является строкой, а скорее массивом байтов. Поэтому в PHP вам не нужно указывать urlencode cyphertext.

кодировка base64 – это все, что вам нужно. Когда вы открываете справку base64_encode, вы видите

base64_encode Кодирует данные с базой64. Эта кодировка предназначена для того, чтобы бинарные данные выдерживали транспорт

Еще одно: чтобы ваше сообщение было декодировано в .net с правильной длиной, вам нужно вручную добавить его с помощью дополняющих символов. Режим заполнения по умолчанию для RijndaelManaged – PKCS7, позволяет «придерживаться». Вы должны расширить свою исходную строку до четных блоков с кодом символов, равным количеству байтов заполнения.

 <?php $iv = "45287112549354892144548565456541"; $key = "anjueolkdiwpoida"; $text = "This is my encrypted message"; // to append string with trailing characters as for PKCS7 padding scheme $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); $padding = $block - (strlen($text) % $block); $text .= str_repeat(chr($padding), $padding); $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv); // this is not needed here //$crypttext = urlencode($crypttext); $crypttext64=base64_encode($crypttext); print($crypttext64) . "\n<br/>"; ?> 

На стороне C # вы выполняете кастинг от base64 до байта [] до строки в байт [] . Вы должны выполнить первое преобразование из base64 в байт [] . Помните, что base64 хранит зашифрованный текст, который является двоичными данными, а не строкой. Также обратите внимание, что RijndaelManaged является IDisposable, поэтому я завернул его в конструкцию using (). Вызов Close () необходим, но недостаточно, как указано в MSDN.

 public byte[] Decode(string str) { var decbuff = Convert.FromBase64String(str); return decbuff; } static public String DecryptRJ256(byte[] cypher, string KeyString, string IVString) { var sRet = ""; var encoding = new UTF8Encoding(); var Key = encoding.GetBytes(KeyString); var IV = encoding.GetBytes(IVString); using (var rj = new RijndaelManaged()) { try { rj.Padding = PaddingMode.PKCS7; rj.Mode = CipherMode.CBC; rj.KeySize = 256; rj.BlockSize = 256; rj.Key = Key; rj.IV = IV; var ms = new MemoryStream(cypher); using (var cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Read)) { using (var sr = new StreamReader(cs)) { sRet = sr.ReadLine(); } } } finally { rj.Clear(); } } return sRet; } 

В результате следующий код в C # вернет вам исходную строку:

 var iv = "45287112549354892144548565456541"; var key = "anjueolkdiwpoida"; var cypher = "u+rIlHB/2rrT/u/qFInnlEkg2unhizsNzGVb9O54sP8="; var temp = DecryptRJ256(Decode(cypher), key, iv);