[BACK]Return to Keyring.pm CVS log [TXT][DIR] Up to [local] / palm / Palm-Keyring / lib / Palm

Diff for /palm/Palm-Keyring/lib/Palm/Keyring.pm between version 1.8 and 1.12

version 1.8, 2006/11/10 17:31:38 version 1.12, 2007/01/28 00:18:46
Line 8 
Line 8 
 #  #
 #   This started as Memo.pm, I just made it work for Keyring.  #   This started as Memo.pm, I just made it work for Keyring.
 #  #
 # $Id$  # $RedRiver: Keyring.pm,v 1.11 2007/01/27 23:59:29 andrew Exp $
 # $RedRiver: Keyring.pm,v 1.7 2006/11/10 16:45:42 andrew Exp $  
   
 use strict;  use strict;
 package Palm::Keyring;  package Palm::Keyring;
Line 37 
Line 36 
   
 =head1 SYNOPSIS  =head1 SYNOPSIS
   
     use Palm::Keyring;          use Palm::PDB;
         $pdb->Decrypt('mypassword');          use Palm::Keyring;
           my $pdb = new Palm::PDB;
           $pdb->Load($file);
           foreach my $record (@{ $pdb->{'records'} }) {
                   print "$record->{'plaintext'}->{'name'}\n";
           }
           $pdb->Decrypt($password);
           # do something with the decrypted parts
   
 =head1 DESCRIPTION  =head1 DESCRIPTION
   
 The Keyring PDB handler is a helper class for the Palm::PDB package. It  The Keyring PDB handler is a helper class for the Palm::PDB package. It
 parses Keyring databases.  See  parses Keyring for Palm OS databases.  See
 L<http://gnukeyring.sourceforge.net/>.  L<http://gnukeyring.sourceforge.net/>.
   
 It is just the standard Palm::Raw with 2 additional public methods.  Decrypt and Encrypt.  It has the standard Palm::PDB methods with 2 additional public methods.
   Decrypt and Encrypt.
   
   It currently supports the v4 Keyring databases.  The v5 databases from the pre-release keyring-2.0 are not supported.
   
 =cut  =cut
   
 =head2 new  =head2 new
   
   $pdb = new Palm::Keyring ('password');          $pdb = new Palm::Keyring([$password]);
   
 Create a new PDB, initialized with the various Palm::Keyring fields  Create a new PDB, initialized with the various Palm::Keyring fields
 and an empty record list.  and an empty record list.
   
 Use this method if you're creating a Keyring PDB from scratch.  Use this method if you're creating a Keyring PDB from scratch otherwise you
   can just use Palm::PDB::new().
   
 =cut  =cut
 #'  
 sub new  sub new
 {  {
         my $classname   = shift;          my $classname   = shift;
Line 86 
Line 97 
         $self->{version} = 4;          $self->{version} = 4;
   
         # Give the PDB the first record that will hold the encrypted password          # Give the PDB the first record that will hold the encrypted password
         $self->{records} = [ {          $self->{records} = [ $self->new_Record ];
                 'category'   => 0,  
                 'attributes' => {  
                         'private' => 1,  
                         'Secret'  => 1,  
                         'Dirty'   => 1,  
                         'dirty'   => 1,  
                 },  
         }, ];  
   
         if ($pass) {          if (defined $pass) {
                 $self->Encrypt($pass);                  $self->Encrypt($pass);
         }          }
   
Line 110 
Line 113 
                 );                  );
 }  }
   
   =pod
   
   =head2 Load
   
           $pdb->Load($filename[, $password]);
   
   Overrides the standard Palm::Raw Load() to add
   $record->{'plaintext'}->{'name'} and
   $record->{'encrypted'} fields.
   $record->{'plaintext'}->{'name'} holds the name of the record,
   $record->{'encrypted'} is the encrypted information in the PDB.
   
   It also takes an additional optional parameter, which is the password to use to
   decrypt the database.
   
   See Decrypt() for the additional fields that are available after decryption.
   
   =cut
   
 sub Load  sub Load
 {  {
         my $self = shift;          my $self     = shift;
         $self->SUPER::Load(@_);          my $filename = shift;
           my $password = shift;
   
           $self->{'appinfo'} = {};
           $self->{'records'} = [];
           $self->SUPER::Load($filename);
   
         foreach my $record (@{ $self->{records} }) {          foreach my $record (@{ $self->{records} }) {
                 next unless exists $record->{data};                  next unless exists $record->{data};
                 my ($name, $encrypted) = split /\000/, $record->{data}, 2;                  my ($name, $encrypted) = split /\000/, $record->{data}, 2;
Line 122 
Line 149 
                 $record->{plaintext}->{name} = $name;                  $record->{plaintext}->{name} = $name;
         $record->{encrypted} = $encrypted;          $record->{encrypted} = $encrypted;
         }          }
   
           return $self->Decrypt($password) if defined $password;
   
         1;          1;
 }  }
   
   =pod
   
   =head2 Write
   
           $pdb->Write($filename[, $password]);
   
   Just like the Palm::Raw::Write() but encrypts everything before saving.
   
   Also takes an optional password to encrypt with a new password, not needed
   unless you are changing the password.
   
   =cut
   
 sub Write  sub Write
 {  {
         my $self = shift;          my $self = shift;
         $self->Encrypt() || return undef;          my $filename = shift;
         return $self->SUPER::Load(@_);          my $password = shift;
   
           $self->Encrypt($password) || return undef;
           return $self->SUPER::Write($filename);
 }  }
   
   =pod
   
   =head2 Encrypt
   
           $pdb->Encrypt([$password]);
   
   Encrypts the PDB, either with the password used to decrypt or create it, or
   optionally with a password that is passed.
   
   See Decrypt() for an what plaintext fields are available to be encrypted.
   
   =cut
   
 sub Encrypt  sub Encrypt
 {  {
         my $self = shift;          my $self = shift;
         my $pass = shift;          my $pass = shift;
   
   
         if ($pass) {          if ($pass) {
                 unless ($self->_keyring_verify($pass) ) {                  unless (exists $self->{'records'}->[0]->{'data'} &&
                       $self->_keyring_verify($pass) ) {
                         # This would encrypt with a new password.                          # This would encrypt with a new password.
                         # First decrypting everything with the old password of course.                          # First decrypting everything with the old password of course.
                         $self->_keyring_update($pass) || return undef;                          $self->_keyring_update($pass) || return undef;
Line 169 
Line 228 
                 $record->{data} = join("\000", $name, $encrypted);                  $record->{data} = join("\000", $name, $encrypted);
         }          }
   
         return 1;          1;
 }  }
   
   =head2 Decrypt
   
           $pdb->Decrypt([$password]);
   
   Decrypts the PDB and fills out the rest of the fields available in
   $record->{'plaintext'}.
   
   The plaintext should now be this, before encryption or after decryption:
   
           $record->{'plaintext'} = {
                   name        => $name,
                   account     => $account,
                   password    => $account_password,
                   description => $description,
           };
   
   =cut
   
 sub Decrypt  sub Decrypt
 {  {
         my $self = shift;          my $self = shift;
Line 220 
Line 297 
   
         }          }
   
         return 1;          1;
 }  }
   
 sub _calc_keys  sub _calc_keys
Line 251 
Line 328 
         my $pass = shift;          my $pass = shift;
   
         die "No password specified!" unless $pass;          die "No password specified!" unless $pass;
         $self->{password} = $pass;  
   
         # AFAIK the thing we use to test the password is          # AFAIK the thing we use to test the password is
         #     always in the first entry          #     always in the first entry
         my $data = $self->{records}->[1]->{data};          my $data = $self->{records}->[0]->{data};
         #die "No encrypted password in file!" unless defined $data;          #die "No encrypted password in file!" unless defined $data;
         return undef unless defined $data;          return undef unless defined $data;
   
Line 271 
Line 347 
   
         if ($data eq $salt . $digest) {          if ($data eq $salt . $digest) {
                 # May as well generate the keys we need now, since we know the password is right                  # May as well generate the keys we need now, since we know the password is right
                 $self->{digest} = _calc_keys($self->{password});                  $self->{digest} = _calc_keys($pass);
                 if ($self->{digest}) {                  if ($self->{digest}) {
                           $self->{password} = $pass;
                         return 1;                          return 1;
                 } else {                  } else {
                         return undef;                          return undef;
Line 294 
Line 371 
         die "No password specified!" unless $pass;          die "No password specified!" unless $pass;
   
         # if the database already has a password in it          # if the database already has a password in it
         if ($self->{records}->[1]->{data}) {          if ($self->{records}->[0]->{data}) {
                 # Make sure everything is decrypted before we update the keyring                  # Make sure everything is decrypted before we update the keyring
                 $self->Decrypt() || return undef;                  $self->Decrypt() || return undef;
         }          }
Line 314 
Line 391 
   
         # AFAIK the thing we use to test the password is          # AFAIK the thing we use to test the password is
         #     always in the first entry          #     always in the first entry
         $self->{records}->[1]->{data} = $data;          $self->{records}->[0]->{data} = $data;
   
         $self->{password} = $pass;          $self->{password} = $pass;
         $self->{digest}   = _calc_keys($self->{password});          $self->{digest}   = _calc_keys($self->{password});
Line 322 
Line 399 
         return 1;          return 1;
 }  }
   
   
 # XXX It looks like they are using des_ecb2_encrypt so I dunno if that is different  
 sub _crypt3des {  sub _crypt3des {
         my ( $plaintext, $passphrase, $flag ) = @_;          my ( $plaintext, $passphrase, $flag ) = @_;
           my $NULL = chr(0);
   
         $passphrase .= ' ' x (16*3);          $passphrase .= ' ' x (16*3);
         my $cyphertext = "";          my $cyphertext = "";
Line 338 
Line 414 
                 $C[$_] = new Crypt::DES( pack( "H*", substr($passphrase, 16*$_, 16 )));                  $C[$_] = new Crypt::DES( pack( "H*", substr($passphrase, 16*$_, 16 )));
         }          }
   
         for ( 0 .. (($size)/8) - 1) {          for ( 0 .. (($size)/8)) {
                 my $pt = substr( $plaintext, $_*8, 8 );                  my $pt = substr( $plaintext, $_*8, 8 );
                 #print "PT: '$pt' - Length: " . length($pt) . "\n";                  #print "PT: '$pt' - Length: " . length($pt) . "\n";
                   next unless length($pt);
                 if (length($pt) < 8) {                  if (length($pt) < 8) {
                         die "record not 8 byte padded" if  $flag == DECRYPT;                          die "record not 8 byte padded" if  $flag == DECRYPT;
                         my $len = 8 - length($pt);                          my $len = 8 - length($pt);
                         #print "LENGTH: $len\n";                          #print "LENGTH: $len\n";
                         #print "Binary:    '" . unpack("b*", $pt) . "'\n";                          #print "Binary:    '" . unpack("b*", $pt) . "'\n";
                         $pt .= (chr(0) x $len);# . $pt;                          $pt .= ($NULL x $len);
                         #print "Binary:    '" . unpack("b*", $pt) . "'\n";  
                         #print "PT: '$pt' - Length: " . length($pt) . "\n";                          #print "PT: '$pt' - Length: " . length($pt) . "\n";
                           #print "Binary:    '" . unpack("b*", $pt) . "'\n";
                 }                  }
                 $pt = $C[0]->decrypt( $pt );                  if ($flag == ENCRYPT) {
                 $pt = $C[1]->encrypt( $pt );                          $pt = $C[0]->encrypt( $pt );
                 $pt = $C[2]->decrypt( $pt );                          $pt = $C[1]->decrypt( $pt );
                           $pt = $C[2]->encrypt( $pt );
                   } else {
                           $pt = $C[0]->decrypt( $pt );
                           $pt = $C[1]->encrypt( $pt );
                           $pt = $C[2]->decrypt( $pt );
                   }
                 #print "PT: '$pt' - Length: " . length($pt) . "\n";                  #print "PT: '$pt' - Length: " . length($pt) . "\n";
                 $cyphertext .= $pt;                  $cyphertext .= $pt;
         }          }
   
         return substr ( $cyphertext, 0, $size );          $cyphertext =~ s/$NULL+$//;
           #print "CT: '$cyphertext' - Length: " . length($cyphertext) . "\n";
   
           return $cyphertext;
 }  }
   
 1;  1;
Line 365 
Line 451 
   
 =head1 AUTHOR  =head1 AUTHOR
   
 Andrew Fresh E<lt>andrew@mad-techies.org<gt>  Andrew Fresh E<lt>andrew@mad-techies.orgE<gt>
   
 =head1 SEE ALSO  =head1 SEE ALSO
   
 Palm::PDB(3)  Palm::PDB(3)
   
 Palm::StdAppInfo(3)  Palm::StdAppInfo(3)
   
   The Keyring for Palm OS website:
   L<http://gnukeyring.sourceforge.net/>
   
 =cut  =cut

Legend:
Removed from v.1.8  
changed lines
  Added in v.1.12

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>