Зашифровать файл в Perl и расшифровать в С#

Я пытаюсь зашифровать текстовый файл с помощью Perl, а затем расшифровать его с помощью другого приложения, написанного на С#. Вот мой код 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";

И мой код С# для расшифровки:

    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 и изменить код С# для использования

PaddingMode.Zeros

но я все еще получаю то же исключение. Помогите, пожалуйста...


person Eldad    schedule 14.11.2011    source источник
comment
C# требует, чтобы данные были дополнены до определенной длины. Вы не можете использовать отступы, если размер данных не соответствует алгоритму   -  person sehe    schedule 14.11.2011
comment
@sehe: Как указал munissor, «заполнение» Perl => «null» означает, что блоки заполнены нулями.   -  person Eldad    schedule 14.11.2011


Ответы (2)


Если вы проверите документацию CPAN для Crypt::CBC, там сказано, что "нулевой " padding заполняет блоки нулями. Поэтому я думаю, что вы должны использовать PaddingMode.Zeros на стороне С#.

person munissor    schedule 14.11.2011
comment
Спасибо за ответ. Я попытался заменить на PaddingMode.Zeros, но результат тот же: CryptographicException: длина данных для расшифровки недействительна. - person Eldad; 14.11.2011

Решение найдено!!!

В Perl мне пришлось добавить после открытия выходного файла:

бинмод $оф;

Предложение заполнения было полезным, но в конце концов я пропустил директиву заполнения и использовал значение по умолчанию, которое равно PKCS7 в Perl и C#.

Мой окончательный код 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";

и часть С#:

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();
person Eldad    schedule 15.11.2011