3

我正在尝试使用 Perl 加密文本文件,然后使用用 C# 编写的不同应用程序对其进行解密。这是我的 Perl 代码:

use strict;
use Crypt::CBC;

my $ifh;
my $ofh;
my $line;

my $cipher = Crypt::CBC->new(
    {
        'key'         => 'length16length16',
        'cipher'      => 'Rijndael',
        'iv'          => 'length16length16',
        'literal_key' => 1,
        'header'      => 'none',
    'padding'     => 'null',
        'keysize'     => 128 / 8
    }
);

open($ifh,'<', $infile)
            or die "Can't open $infile for encryption input: $!\n";
open($ofh, '>', $outfile)
        or die "Can't open $outfile for encryption output: $!\n";

$cipher->start('encrypting');

for $line (<$ifh>) {
    print $ofh $cipher->crypt($line);
  }

print $ofh $cipher->finish;

close($ifh)
    or die "Error closing input file: $!\n";

close($ofh)
    or die "Error closing output file: $!\n";

还有我的 C# 解密代码:

    RijndaelManaged myRijndael = new System.Security.Cryptography.RijndaelManaged();
    myRijndael.Key = System.Text.Encoding.UTF8.GetBytes("length16length16");
    myRijndael.IV = System.Text.Encoding.UTF8->GetBytes("length16length16");
    myRijndael.Mode = CipherMode.CBC;
    myRijndael.Padding = PaddingMode.None;

    // Create a decryptor to perform the stream transform.
    ICryptoTransform decryptor = myRijndael.CreateDecryptor(myRijndael.Key, myRijndael.IV);

    //Create the streams used for decryption.
    FileStream file = File.OpenRead(strInFile);
    CryptoStream csDecrypt = new CryptoStream(file, decryptor, CryptoStreamMode.Read);
    StreamReader srDecrypt = new StreamReader(csDecrypt);

    // Read the decrypted bytes from the decrypting stream
    string decryptedText = srDecrypt.ReadToEnd();

我不断得到

System.Security.Cryptography.CryptographicException:要解密的数据长度无效

当我尝试一次读取几个字节的数据时,我注意到前 100 个左右的字节被正确解密,但其余的只是垃圾。

顺便说一句,我可以使用 Perl 解密加密文件:

$cipher->start('decrypting');

那么我在 C# 和 Perl 上做错了什么?

编辑:我尝试遵循@munissor 的建议并更改要使用的 C# 代码

PaddingMode.Zeros

但我仍然得到同样的例外。请帮忙...

4

2 回答 2

3

如果您检查Crypt::CBC 的 CPAN 文档,它会说“空”填充用零填充块。所以我认为你应该PaddingMode.Zeros在 C# 端使用。

于 2011-11-14T11:29:51.267 回答
2

找到了解决办法!!!

在 Perl 中,我必须在打开输出文件后添加:

二进制模式 $ofh;

填充建议很有帮助,但最后我省略了填充指令并使用了默认值,即 Perl 和 C# 中的 PKCS7。

我的最终 Perl 代码如下所示:

use strict;
use Crypt::CBC;

my $ifh;
my $ofh;

my $cipher = Crypt::CBC->new(
    {
      'key'         => 'length16length16',
      'cipher'      => 'Rijndael',
      'iv'          => 'length16length16',
      'literal_key' => 1,
      'header'      => 'none',
      'keysize'     => 128 / 8
    }
);

#open input and output file
open($ifh,'<', $infile)
        or die "Can't open $infile for encryption input: $!\n";
open($ofh, '>', $outfile)
    or die "Can't open $outfile for encryption output: $!\n";
binmode &ofh;

$cipher->start('encrypting');

#write encrypted data to output file
while (read($ifh,my $buffer,1024)) 
{
    print $ofh $cipher->crypt($buffer);
} 

print $ofh $cipher->finish;

#close file handles
close($ifh)
    or die "Error closing input file: $!\n";
close($ofh)
    or die "Error closing output file: $!\n";

和 C# 部分:

RijndaelManaged myRijndael = new System.Security.Cryptography.RijndaelManaged();
myRijndael.Key = System.Text.Encoding.UTF8.GetBytes("length16length16");
myRijndael.IV = System.Text.Encoding.UTF8->GetBytes("length16length16");
myRijndael.Mode = CipherMode.CBC;

// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = myRijndael.CreateDecryptor(myRijndael.Key, myRijndael.IV);

//Create the streams used for decryption.
FileStream file = File.OpenRead(strInFile);
CryptoStream csDecrypt = new CryptoStream(file, decryptor, CryptoStreamMode.Read);
StreamReader srDecrypt = new StreamReader(csDecrypt);

// Read the decrypted bytes from the decrypting stream
string decryptedText = srDecrypt.ReadToEnd();
于 2011-11-15T15:18:38.163 回答