跨平台(PHP到C#.NET)encryption/解密与Rijndael

我目前有解密php密码encryption消息的一些问题。 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/>"; ?> 

encryption的消息然后被发送到ASP.NET平台(C#)。 但是,我有保留解密顺序(base64解码到urldecode)的问题。 我在ASP.NET中的代码如下(iv和key与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的encryption信息后,我把它转换成byte [],然后转换回UTF8编码的string,所以我可以urldecode它。 然后将结果input到函数中,将string转换回byte []并通过解密过程运行。 但是,我无法得到理想的结果…任何想法?

提前致谢。

在这里,我可以看到双方的问题。

请记住,编码时得到的不是string,而是一个字节数组。 所以在PHP中,你不需要urlencode密码。

base64编码就是你所需要的。 当你打开base64_encode帮助你看到

base64_encode使用base64编码给定的数据。 这种编码旨在使二进制数据在传输过程中存活

还有一件事 – 以.net正确的长度解码你的信息,你必须手动追加填充字符。 RijndaelManaged的默认填充模式是PKCS7,让我们坚持下去。 您必须将源string扩展到字符编码等于填充字节数的块。

 <?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转换byte []来将string转换byte [] 。 你只需要做第一次从base64byte []的转换。 请记住,base64持有encryption的文本是二进制数据,而不是string。 另外请注意RijndaelManaged是IDisposable,所以我用()构造包装它。 调用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#中的以下代码将返回初始string:

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