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

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

问题描述

我目前具有解密通过PHP的mcrypt加密的消息有点问题。
PHP的code是如下:

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 code到urlde code)的问题。在code,我在ASP.NET的计算如下(IV和密钥是相同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 EN codeD字符串,所以我可以urlde code吧。然后,我将结果到那里我转换的字符串返回到字节[]和运行它通过解密过程的功能。但是,我不能得到期望的结果...任何想法?

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,你不需要urlen code密文。

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_en code有助于你看

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

base64_en code 恩codeS给定的使用Base64数据。这种编码是
  旨在使二进制数据生存运输

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

还有一件事 - 在.NET中的信息去codeD具有正确的长度,你有填充字符来手动添加它。为RijndaelManaged的默认填充模式是PKCS7,让'坚持下去。你必须扩展您的源字符串到连块与字符code等于填充字节数。

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 第一次转换为字节[] 只。请记住,Base64是抱着cyphered文本是二进制数据,不串。
同时请注意,RijndaelManaged的是IDisposable的,所以我用()构造包裹它。调用close()是必要的,但还不够在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#以下code将返回初始的字符串:

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天全站免登陆