=================================================================== RCS file: /cvs/palm/Palm-Keyring/lib/Palm/Keyring.pm,v retrieving revision 1.1 retrieving revision 1.4 diff -u -r1.1 -r1.4 --- palm/Palm-Keyring/lib/Palm/Keyring.pm 2006/01/26 20:54:19 1.1 +++ palm/Palm-Keyring/lib/Palm/Keyring.pm 2006/11/10 04:21:17 1.4 @@ -8,8 +8,8 @@ # # This started as Memo.pm, I just made it work for Keyring. # -# $Id: Keyring.pm,v 1.1 2006/01/26 20:54:19 andrew Exp $ -# $RedRiver$ +# $Id: Keyring.pm,v 1.4 2006/11/10 04:21:17 andrew Exp $ +# $RedRiver: Keyring.pm,v 1.3 2006/02/02 00:59:08 andrew Exp $ use strict; package Palm::Keyring; @@ -18,7 +18,7 @@ use vars qw( $VERSION @ISA ); use Digest::MD5 qw(md5); -use Crypt::TripleDES; +use Crypt::DES; use constant ENCRYPT => 1; use constant DECRYPT => 0; @@ -27,7 +27,7 @@ # One liner, to allow MakeMaker to work. -$VERSION = do { my @r = (q$Revision: 1.1 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; +$VERSION = do { my @r = (q$Revision: 1.4 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; @ISA = qw( Palm::StdAppInfo Palm::Raw ); @@ -113,6 +113,26 @@ ); } +sub Load +{ + my $self = shift; + $self->SUPER::Load(@_); + + # Skip the first 2 records because they are special + # and don't have any plaintext + my $skip = 0; + foreach my $record (@{ $self->{records} }) { + if ($skip < 2) { + $skip++; + next; + } + my ($name, $encrypted) = split /\000/, $record->{data}, 2; + $record->{plaintext}->{name} = $name; + $record->{encrypted} = $encrypted; + } + 1; +} + sub Encrypt { my $self = shift; @@ -142,11 +162,11 @@ my $description = defined $record->{plaintext}->{description} ? $record->{plaintext}->{description} : ''; my $extra = ''; - my $plaintext = join("\0", $account, $password, $description, $extra); + my $plaintext = join("\000", $account, $password, $description, $extra); - my $encrypted = $self->_crypt($plaintext, ENCRYPT); + my $encrypted = $self->_crypt3des($plaintext, ENCRYPT); - $record->{data} = join("\0", $name, $encrypted); + $record->{data} = join("\000", $name, $encrypted); } return 1; @@ -171,17 +191,25 @@ next unless defined $record->{data}; - my ($name, $encrypted) = split /\0/, $record->{data}; + my ($name, $encrypted) = split /\000/, $record->{data}, 2; $record->{plaintext}->{name} = $name; - my $decrypted = $self->_crypt($encrypted, DECRYPT); + my $decrypted = $self->_crypt3des($encrypted, DECRYPT); my ($account, $password, $description, $extra) - = split /\0/, $decrypted, 4; + = split /\000/, $decrypted, 4; $record->{plaintext}->{account} = defined $account ? $account : ''; $record->{plaintext}->{password} = defined $password ? $password : ''; $record->{plaintext}->{description} = defined $description ? $description : ''; + #print "Name: '$name'\n"; + #print "Encrypted: '$encrypted' - Length: " . length($encrypted) . "\n"; + #print "Hex: '" . unpack("H*", $encrypted) . "'\n"; + #print "Binary: '" . unpack("b*", $encrypted) . "'\n"; + #print "Decrypted: '$decrypted' - Length: " . length($decrypted) . "\n"; + #print "Hex: '" . unpack("H*", $decrypted) . "'\n"; + #print "Binary: '" . unpack("b*", $decrypted) . "'\n"; + #print "\n"; #print "Extra: $extra\n"; #-------------------------------------------------- # print "Account: $account\n"; @@ -194,24 +222,6 @@ return 1; } -sub _crypt -{ - my $self = shift; - my $original = shift; - my $flag = shift; - - my $digest = $self->{digest} || $self->_calc_keys(); - #print "DIGEST: $digest\n"; - - my $des = new Crypt::TripleDES; - - if ($flag == ENCRYPT) { - return $des->encrypt3($original, $digest); - } else { - return $des->decrypt3($original, $digest); - } -} - sub _calc_keys { my $self = shift; @@ -242,7 +252,7 @@ my $self = shift; my $pass = shift; - die "No password specified!" unless defined $pass; + die "No password specified!" unless $pass; $self->{password} = $pass; # AFAIK the thing we use to test the password is @@ -282,7 +292,7 @@ my $self = shift; my $pass = shift; - die "No password specified!" unless defined $pass; + die "No password specified!" unless $pass; # if the database already has a password in it if ($self->{records}->[0]->{data}) { @@ -313,6 +323,50 @@ return 1; } + +# XXX Have to make this encrypt as well as decrypting, but w00 h00! +# do null padding on the end of a cleartext if we are going to encrypt it +sub _crypt3des { + my ( $self, $plaintext, $flag ) = @_; + + my $passphrase = $self->{digest} || $self->_calc_keys(); + $passphrase .= ' ' x (16*3); + my $cyphertext = ""; + + + my $size = length ( $plaintext ); + #print "STRING: '$plaintext' - Length: " . length($plaintext) . "\n"; + + # This check should see if it is plaintext first, if it is, + # pad it with \000 + # if not, then die + die "record not 8 byte padded" if (length($plaintext) % 8) && ! $flag; + + my %C; + for ( 0..2 ) { + $C{$_} = new Crypt::DES( pack( "H*", substr($passphrase, 16*$_, 16 ))); + } + + for ( 0 .. (($size)/8) - 1) { + my $pt = substr( $plaintext, $_*8, 8 ); + #print "PT: '$pt' - Length: " . length($pt) . "\n"; + if (length($pt) < 8) { + my $len = 8 - length($pt); + print "LENGTH: $len\n"; + print "Binary: '" . unpack("b*", $pt) . "'\n"; + $pt .= (chr(0) x $len);# . $pt; + print "Binary: '" . unpack("b*", $pt) . "'\n"; + #print "PT: '$pt' - Length: " . length($pt) . "\n"; + } + $pt = $C{0}->decrypt( $pt ); + $pt = $C{1}->encrypt( $pt ); + $pt = $C{2}->decrypt( $pt ); + #print "PT: '$pt' - Length: " . length($pt) . "\n"; + $cyphertext .= $pt; + } + + return substr ( $cyphertext, 0, $size ); +} 1; __END__