Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用AES的C#文件加密,使用phpseclib解密_C#_Php_Encryption_Phpseclib - Fatal编程技术网

使用AES的C#文件加密,使用phpseclib解密

使用AES的C#文件加密,使用phpseclib解密,c#,php,encryption,phpseclib,C#,Php,Encryption,Phpseclib,我正在从事一个安全文件传输项目,该项目在客户端使用c#client对文件进行加密。我需要使用php或者phpseclib对服务器端的文件进行解密。这里的代码是我从一个msdn示例复制的。但是我不能在php中计算出解密函数 public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes) { byte[] encryptedBytes = null;

我正在从事一个安全文件传输项目,该项目在客户端使用c#client对文件进行加密。我需要使用php或者phpseclib对服务器端的文件进行解密。这里的代码是我从一个msdn示例复制的。但是我不能在php中计算出解密函数

public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
        {
            byte[] encryptedBytes = null;
            byte[] saltBytes = passwordBytes;

            using (MemoryStream ms = new MemoryStream())
            {
                using (RijndaelManaged AES = new RijndaelManaged())
                {
                    var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);

                    AES.KeySize = 256;
                    AES.BlockSize = 256;
                    AES.Mode = CipherMode.CBC;
                    AES.Padding = PaddingMode.Zeros;
                    AES.Key = key.GetBytes(AES.KeySize / 8);
                    AES.IV = key.GetBytes(AES.BlockSize / 8);                    

                    using (CryptoStream cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                        cs.Close();
                    }
                    encryptedBytes = ms.ToArray();
                }
            }

            return encryptedBytes;
        }
这是无法工作的php代码:

        $pw = "this_is_my_pw";
        $aes = new Crypt_AES(CRYPT_AES_MODE_CBC);
        $aes->setKey($pw);
        $aes->setKeyLength(256);
        $aes->disablePadding();

        $file = "enc.txt";

        $fh = fopen($file, "r");
        $contents = trim(fread($fh, filesize($file)));
        fclose($fh);

        //echo "Encoded: \n\n" . $contents;

        $contents = $aes->decrypt($contents);
        #$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
        #$padding = $block - (strlen($clear) % $block);

        #$dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $pw, base64_decode($contents), MCRYPT_MODE_CBC, $pw);

        echo "Decoded: \n\n" . $contents;

有人能帮我解决这个问题或者给我一个提示我做错了什么吗?

在我看到的Java代码中
AES.BlockSize=256。从技术上讲,AES具有128位的固定块大小。Rijndael支持可变块大小,但AES不支持。如果您想在PHP和phpseclib中使用可变块大小,您需要执行以下操作:

    $pw = "this_is_my_pw";
    $aes = new Crypt_Rijndael(CRYPT_RIJNDAEL_MODE_CBC);
    $aes->setKey($pw);
    $aes->setKeyLength(256);
    $aes->setBlockLength(256);
    $aes->disablePadding();
此外,您的密钥长度为13字节。AES密钥需要16字节(128位)长、24字节(192位)长或32字节(256位)长。idk您正在使用的js库,但phpseclib 1.0/2.0 null会在键不够长时填充键。phpseclib的最新版本(目前正在开发中)引发异常


或者,您的意思是使用基于密码的密钥派生函数?phpseclib提供了两种可通过
setPassword()
使用的方法,但如果是这种情况,您需要知道js库使用的方法和参数。

如果您试图使用AES,请将块大小设置为128位,这是唯一受支持的块大小。使用不同的块大小意味着您使用的是Rijndael加密,这在跨平台上没有得到很好的支持

AES支持128、192和256位的多种密钥大小。有时在使用Rijndael实现使用AES加密时会出现混乱

  • 解密时不使用初始化向量。您需要将初始化向量(IV)与数据一起发送-您的PHP代码从未从phpseclib调用
    $aes->setIV
    ,因此它将永远无法解密文本,因为phpseclib在未设置的情况下使用全零的IV。我个人建议使用C#生成一个安全的随机IV,但显然从PBKDF2密钥派生IV是可以接受的。PBKDF2(在RFC 2898中指定)是关键拉伸算法
    Rfc2898DeriveBytes
    实现。无论如何,您需要在PHP端重新生成IV,无论这意味着使用加密数据传输IV(这是完全正确的),还是在PHP端重新派生IV

  • 使用密码作为salt是一个非常糟糕的主意。salt必须具有足够的长度,并以加密方式随机生成。使用密码作为salt完全违背了拥有salt的意义。这说明了如何结合使用
    Rfc2898DeriveBytes
    生成加密随机salt,但重要的是:

  • byte[]saltBytes=新字节[8];
    使用(RNGCryptoServiceProvider rngCsp=new RNGCryptoServiceProvider())
    {
    //用随机值填充数组。
    rngCsp.GetBytes(salt1);
    }
    
  • salt必须与加密数据一起传输。您需要发送PBKDF2 salt字节以及IV字节和加密数据。phpseclib将需要所有这些来正确初始化自身和解密数据。您可能需要使用phpseclib来实现这一点,如下所示:
  • $salt=…;//以某种方式将盐添加到PHP代码中
    $iv=…;//获取PHP代码的IV
    $pw=“这是我的”;
    $aes=新加密aes(加密aes模式CBC);
    $aes->setPassword($pw,'pbkdf2'/*密钥扩展算法*/,,
    'sha1'/*散列算法*/,$salt/*从C#*/*生成的salt,
    1000/*迭代次数,必须与C#代码*/,
    256/8/*密钥大小(字节),256位密钥/8位/字节*/
    );
    $aes->setIV($iv);
    
  • 记住关于blocksize的其他答案。128位是标准的AES blocksize,因此请确保C#和phpseclib都能在较大的blocksize下正常工作,或者只使用AES标准

  • 使用不完全支持长度的加密密钥取决于非标准密钥填充,这不是一个好主意,可能会导致互操作性困难。使用文本作为密钥也会降低安全性。在本例中,密码表示少于86位的密钥材料。@zaph-关于密钥大小的好发现-我实际上没有看到它。我刚刚注意到了块大小的一点,有点跳到了上面。答案是Rijndael(
    setBlockLength(256)
    )不是AES,Rijndael允许密钥和块大小分别为128、160、192、224或256位。@zaph-正确。但是,OP使用的是
    RijndaelManaged AES=new RijndaelManaged()
    AES.BlockSize=256