跨平台(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 [] 。 你只需要做第一次从base64到byte []的转换。 请记住,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);