跨平台(php到C#.NET)加密/解密与Rijndael [英] Cross platform (php to C# .NET) encryption/decryption with Rijndael

查看:152
本文介绍了跨平台(php到C#.NET)加密/解密与Rijndael的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前在解密由php mcrypt加密的消息方面存在一些问题。
PHP代码如下:

I'm currently having a bit of problem with decrypting a message encrypted by php mcrypt. The php code is as following:

<?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解码为urldecode)。 ASP.NET中的代码如下(iv和key与php相同):

The the encrypted message is then sent to a ASP.NET platform (C#). However, I'm having problem retaining the order of decryption (base64 decode to urldecode). The code I had in ASP.NET is as the following (iv and key is the same as in 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它。然后我将结果输入到我将字符串转换回byte []的函数中,并通过解密过程运行它。但是,我无法得到所需的结果...任何想法?

The problem I'm having is that after I recieved the encrypted message from php, I converted it into byte[] and then converted back to UTF8 encoded string so I can urldecode it. then I feed the result into the function where I converted the string back to byte[] and ran it through the decryption process. However, I can't get the desired result...any ideas?

提前感谢

推荐答案

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

Here I can see problems on both sides.

请记住,当编码不是字符串时,你会得到什么,而是一个字节数组。
所以在PHP中你不需要urlencode cyphertext。

Please keep in mind that what you get when encoding is not string, but rather an array of bytes. So in PHP you don't need to urlencode cyphertext.

base64编码是你需要的。当您打开 base64_encode帮助时,您会看到

base64 encoding is all you need. When you open base64_encode help you see


base64_encode 使用base64对给定的数据进行编码。这个编码是
,旨在使二进制数据在运输中生存

base64_encode Encodes the given data with base64. This encoding is designed to make binary data survive transport

还有一件事 - 让你的消息在.net中解码一个正确的长度,你必须手动附加填充字符。 RijndaelManaged的默认填充模式是PKCS7,让我们坚持下去。您必须将源字符串扩展为字符代码等于填充字节数的偶数块。

One more thing - to have your message decoded in .net with a correct length, you have to manually append it with padding characters. Default padding mode for RijndaelManaged is PKCS7, lets' stick with it. You have to extend your source string to even blocks with characters code equal to number of padding bytes.

<?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 转换为 byte [] 。记住,base64正在保存二进制数据的加密文本,而不是字符串。
另请注意,RijndaelManaged是IDisposable,所以我已经使用()构造包装了它。调用关闭()是必需的,但不够,如MSDN中所述。

At C# side you have casting from base64 to byte[] to string to byte[]. You have to do the first conversion from base64 to byte[] only. Remember, base64 is holding the cyphered text that is binary data, not string. Also please note that RijndaelManaged is IDisposable, so I have wrapped it in using() construct. Calling Close() is necessary but not enough as stated in 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#中的以下代码将返回初始字符串: / p>

As a result, following code in C# will return you the initial string:

var iv = "45287112549354892144548565456541";
var key = "anjueolkdiwpoida";
var cypher = "u+rIlHB/2rrT/u/qFInnlEkg2unhizsNzGVb9O54sP8=";

var temp = DecryptRJ256(Decode(cypher), key, iv);

这篇关于跨平台(php到C#.NET)加密/解密与Rijndael的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆