Search code examples
perlutf-8ansiblowfish

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


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 );

Solution

  • 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));