in reply to Salt issue

I can reproduce this error as follows:
use Modern::Perl; use Crypt::CBC; my $cipher1 = Crypt::CBC->new( -key => 'my secret key', -cipher => 'Crypt::DES', -header => 'randomiv', ); my $plaintext = 'In nova fert animus mutatas dicere formas corpora; di, coeptis (nam v +os mutastis et illas) adspirate meis primaque ab origine mundi ad mea + perpetuum deducite tempora carmen!'; my $ciphertext = $cipher1->encrypt_hex($plaintext); say $ciphertext; my $cipher2 = Crypt::CBC->new( -key => 'my secret key', -cipher => 'Crypt::DES', #-header => 'randomiv', ); $plaintext = $cipher2->decrypt_hex($ciphertext); say $plaintext;
The error shows up in
$plaintext = $cipher2->decrypt_hex($ciphertext);

The error goes away when commenting out -header => 'randomiv', in $cipher1 or uncommenting -header => 'randomiv', in $cipher2.

So it appears your ciphertext has been generated in a different way than the decription routine expects.

The docs for this module say:

The "salt" header is now the default as of Crypt::CBC version 2.17. In all earlier versions "randomiv" was the default.

It may very well be that your upgrading of the OS also caused an upgrade in the Crypt::CBC module which now uses a different default ('salt' instead of 'randomiv'). I used the latest version which is 2.33.

What version did you use before the upgrade and what version are you using now?

CountZero

A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

My blog: Imperial Deltronics

Replies are listed 'Best First'.
Re^2: Salt issue
by Anonymous Monk on Sep 23, 2013 at 14:39 UTC

    I have 2.33 installed. I am not sure what version was installed in the original 11.2 OS installation. Thank you for looking into this.

Re^2: Salt issue
by Anonymous Monk on Sep 23, 2013 at 15:17 UTC

    Looking at the version statement in the EncryptedHash.pm file, it looks like CBC v. 1.8 was the original. I am also appending the entire file for your perusal.

    #!/usr/bin/perl -s ## ## Tie::EncryptedHash - A tied hash with encrypted fields. ## ## Copyright (c) 2000, Vipul Ved Prakash. All rights reserved. ## This code is based on Damian Conway's Tie::SecureHash. ## ## $Id: EncryptedHash.pm,v 1.8 2000/09/02 19:23:00 vipul Exp vipul $ ## vi:expandtab=1;ts=4; package Tie::EncryptedHash; use strict; use vars qw($VERSION $strict); use Digest::MD5 qw(md5_base64); use Crypt::CBC; use Data::Dumper; use Carp; ( $VERSION ) = '$Revision: 1.8 $' =~ /\s(\d+\.\d+)\s/; my $DEBUG = 0; sub debug { return undef unless $DEBUG; my ($caller, undef) = caller; my (undef,undef,$line,$sub) = caller(1); $sub =~ s/.*://; $sub = sprintf "%10s()%4d",$sub,$line; print "$sub " . (shift) . "\n"; } # sub new { # my ($class,%args) = @_; # my %self = (); tie %self, $class; # my $self = bless \%self, $class; # $self->{__password} = $args{__password} if $args{__password}; # $self->{__cipher} = $args{__cipher} || qq{Blowfish}; # return $self; # } sub new { my ($class,%args) = @_; my $self = {}; tie %$self, $class; bless $self, $class; $self->{__password} = $args{__password} if $args{__password}; $self->{__cipher} = $args{__cipher} || qq{Blowfish}; return $self; } sub _access { my ($self, $key, $caller, $file, $value, $delete) = @_; my $class = ref $self || $self; # SPECIAL ATTRIBUTE if ( $key =~ /(__password|__hide|__scaffolding|__cipher)$/ ) { my $key = $1; unless($value||$delete) {return undef unless $caller eq $class +} if ($delete && ($key =~ /__password/)) { for (keys %{$$self{__scaffolding}}) { if ( ref $self->{$_} ) { $self->{$_} = encrypt($self->{$_}, $self->{__scaffolding +}{$_}, $self->{__cipher}); delete $self->{__scaffolding}{$_}; } } } delete $$self{$key} if $delete; return $self->{$key} = $value if $value; return $self->{$key}; # SECRET FIELD } elsif ( $key =~ m/^(_{1}[^_][^:]*)$/ ||$key =~ m/.*?::(_{1}[^_][ +^:]*)/ ) { my $ctext = $self->{$1}; if ( ref $ctext && !($value)) { # ENCRYPT REF AT FETCH my $pass = $self->{__scaffolding}{$1} || $self->{__password} +; return undef unless $pass; $self->{$1} = encrypt($ctext, $pass, $self->{__cipher}); return $self->FETCH ($1); } my $ptext = qq{}; my $isnot = !( exists $self->{$1} ); my $auth = verify($self,$1); return undef if !($auth) && ref $self->{$1}; return undef if !($auth) && $self->{__hide}; if ($auth && $auth ne "1") { $ptext = $auth } if ($value && $auth) { # STORE if ( ref $value ) { $self->{__scaffolding}{$1} = $self->{__password}; $cte +xt = $value; } else { my $key = $1; unless ($self->{__password}) { if ($value =~ m:^\S+\s\S{22}\s:) { return $self->{$key} = $value; } else { return undef } } $ctext = encrypt($value, $self->{__password}, $self->{__ +cipher}); } $self->{$1} = $ctext; return $value; } elsif ($auth && $delete) { # DELETE delete $$self{$1} } elsif ($isnot && (!($value))) { # DOESN'T EXIST return; } elsif ((!($auth)) && $ctext) { return $ctext; # FETCH return ciphertext } elsif ($auth && !($isnot)) { # FETCH return plaintext if (ref $ptext) { $self->{$1} = $ptext; $self->{__scaffolding}{$1} = $self->{__password}; # R +ef counting mechanism return $self->{$1}; } } return undef unless $auth; return $ptext; # PUBLIC FIELD } elsif ( $key =~ m/([^:]*)$/ || $key =~ m/.*?::([^:]*)/ ) { $self->{$1} = $value if $value; delete $$self{$1} if $delete; return $self->{$1} if $self->{$1}; return undef; } } sub encrypt { # ($plaintext, $password, $cipher) $_[0] = qq{REF }. Data::Dumper->new([$_[0]])->Indent(0)->Terse(0)- +>Purity(1)->Dumpxs if ref $_[0]; return qq{$_[2] } . md5_base64($_[0]) .qq{ } . Crypt::CBC->new($_[1],$_[2])->encrypt_hex($_[0]) } sub decrypt { # ($cipher $md5sum $ciphertext, $password) return undef unless $_[1]; my ($m, $d, $c) = split /\s/,$_[0]; my $ptext = Crypt::CBC->new($_[1],$m)->decrypt_hex($c); my $check = md5_base64($ptext); if ( $d eq $check ) { if ($ptext =~ /^REF (.*)/is) { my ($VAR1,$VAR2,$VAR3,$VAR4,$VAR5,$VAR6,$VAR7,$VAR8); return eval qq{$1}; } return $ptext; } } sub verify { # ($self, $key) my ($self, $key) = splice @_,0,2; # debug ("$self->{__scaffolding}{$key}, $self->{__password}, $self +->{$key}"); return 1 unless $key =~ m:^_:; return 1 unless exists $self->{$key}; return undef if ref $self->{$key} && ($self->{__scaffolding}{$key} + ne $self->{__password}); my $ptext = decrypt($self->{$key}, $self->{__password}); return $ptext if $ptext; } sub each { CORE::each %{$_[0]} } sub keys { CORE::keys %{$_[0]} } sub values { CORE::values %{$_[0]} } sub exists { CORE::exists $_[0]->{$_[1]} } sub TIEHASH # ($class, @args) { my $class = ref($_[0]) || $_[0]; my $self = bless {}, $class; $self->{__password} = $_[1] if $_[1]; $self->{__cipher} = $_[2] || qq{Blowfish}; return $self; } sub FETCH # ($self, $key) { my ($self, $key) = @_; my $entry = _access($self,$key,(caller)[0..1]); return $entry if $entry; } sub STORE # ($self, $key, $value) { my ($self, $key, $value) = @_; my $entry = _access($self,$key,(caller)[0..1],$value); return $entry if $entry; } sub DELETE # ($self, $key) { my ($self, $key) = @_; return _access($self,$key,(caller)[0..1],'',1); } sub CLEAR # ($self) { my ($self) = @_; return undef if grep { ! $self->verify($_) } grep { ! /__/ } CORE::keys %{$self}; %{$self} = (); } sub EXISTS # ($self, $key) { my ($self, $key) = @_; my @context = (caller)[0..1]; return _access($self,$key,@context) ? 1 : ''; } sub FIRSTKEY # ($self) { my ($self) = @_; CORE::keys %{$self}; goto &NEXTKEY; } sub NEXTKEY # ($self) { my $self = $_[0]; my $key; my @context = (caller)[0..1]; while (defined($key = CORE::each %{$self})) { last if eval { _access($self,$key,@context) } } return $key; } sub DESTROY # ($self) { } 1; __END__