Frage

How to handle over non-ANSI characters to Crypt::Blowfish in Perl?

The following script was written in charset UTF-8 and fails only on § or ö.

#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use utf8;
use Crypt::Blowfish;
my $cipher = Crypt::Blowfish->new( pack 'H16', '12345678' );
my @chars = ( 'a', '§', 'ö', '9' );
printf( "%s: %s",
    $_, ( eval { $cipher->encrypt( $_ x 8 ) } ) ? "ok\n" : "fail: $@" )
    for ( @chars );
War es hilfreich?

Lösung

Ciphers work on streams or blocks of bytes, but you aren't providing it with bytes. You are providing it with Unicode cope points.

You need to serialise any text you want to encrypt into bytes before you can encrypt it, which is to say, you need to encode your text.

use Encode qw( encode_utf8 );
my $bytes = encode_utf8($char x 8);

Furthermore, you shouldn't use Crypt::Blowfish directly. That will produce weak encryption. You want to access it through Crypt::CBC. This provides salting, chaining and padding.

use Crypt::CBC qw( );
use Encode     qw( encode_utf8 decode_utf8 );

my $cipher = Crypt::CBC->new(
   -key    => '... key phrase ...',
   -cipher => 'Blowfish',
);

my $cipher_bytes = $cipher->encrypt(encode_utf8($plain_text));
my $plain_text = decode_utf8($cipher->decrypt($cipher_bytes));

Andere Tipps

Many of the Crypt::* modules are block encryption algorithms. So, they can work only with blocks with fixed length. Since '§' is a UTF8 character, it actually contain more than 1 byte, thats why your code is failing. Another issue is that you using use utf8 pragma, which means utf8 constant strings will be created with "utf8 flag". This can lead to big changes in binary algorithms, like encryption.

I'd suggest you to use Crypt::CBC module(check it on the CPAN); and, remove utf8 flag before encryption: utf8::encode($_);

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top