[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.4 and 1.10

version 1.4, 2006/11/10 04:21:17 version 1.10, 2006/12/06 18:45:42
Line 9 
Line 9 
 #   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$  # $Id$
 # $RedRiver: Keyring.pm,v 1.3 2006/02/02 00:59:08 andrew Exp $  # $RedRiver: Keyring.pm,v 1.9 2006/11/10 17:49:51 andrew Exp $
   
 use strict;  use strict;
 package Palm::Keyring;  package Palm::Keyring;
Line 65 
Line 65 
         my $classname   = shift;          my $classname   = shift;
         my $pass = shift;          my $pass = shift;
   
           # Create a generic PDB. No need to rebless it, though.
         my $self        = $classname->SUPER::new(@_);          my $self        = $classname->SUPER::new(@_);
                         # Create a generic PDB. No need to rebless it,  
                         # though.  
   
         $self->{name} = "Keys-Gtkr";    # Default          $self->{name} = "Keys-Gtkr";    # Default
         $self->{creator} = "Gtkr";          $self->{creator} = "Gtkr";
         $self->{type} = "Gkyr";          $self->{type} = "Gkyr";
           # The PDB is not a resource database by
           # default, but it's worth emphasizing,
           # since MemoDB is explicitly not a PRC.
         $self->{attributes}{resource} = 0;          $self->{attributes}{resource} = 0;
                                 # The PDB is not a resource database by  
                                 # default, but it's worth emphasizing,  
                                 # since MemoDB is explicitly not a PRC.  
   
         # Initialize the AppInfo block          # Initialize the AppInfo block
         $self->{appinfo} = {};          $self->{appinfo} = {};
Line 87 
Line 86 
         $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 ($pass) {
                 $self->Encrypt($pass);                  $self->Encrypt($pass);
Line 116 
Line 105 
 sub Load  sub Load
 {  {
         my $self = shift;          my $self = shift;
           $self->{'appinfo'} = {};
           $self->{'records'} = [];
         $self->SUPER::Load(@_);          $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} }) {          foreach my $record (@{ $self->{records} }) {
                 if ($skip < 2) {                  next unless exists $record->{data};
                         $skip++;  
                         next;  
                 }  
                 my ($name, $encrypted) = split /\000/, $record->{data}, 2;                  my ($name, $encrypted) = split /\000/, $record->{data}, 2;
                   next unless $encrypted;
                 $record->{plaintext}->{name} = $name;                  $record->{plaintext}->{name} = $name;
         $record->{encrypted} = $encrypted;          $record->{encrypted} = $encrypted;
         }          }
         1;          1;
 }  }
   
   sub Write
   {
           my $self = shift;
           $self->Encrypt() || return undef;
           return $self->SUPER::Write(@_);
   }
   
 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 ($self->_keyring_verify($pass) ) {
                         # This would encrypt with a new password.                          # This would encrypt with a new password.
Line 147 
Line 141 
                 }                  }
         }          }
   
         my $seen_enc_pass = 0;          $self->{digest} ||= _calc_keys($self->{password});
         foreach my $record (@{ $self->{records} }) {  
                 unless ($seen_enc_pass) {  
                         $seen_enc_pass = 1;  
                         next;  
                 }  
   
           foreach my $record (@{ $self->{records} }) {
                 next unless defined $record->{plaintext};                  next unless defined $record->{plaintext};
   
                 my $name        = defined $record->{plaintext}->{name}        ? $record->{plaintext}->{name}        : '';                  my $name        = defined $record->{plaintext}->{name}        ?
                 my $account     = defined $record->{plaintext}->{account}     ? $record->{plaintext}->{account}     : '';                          $record->{plaintext}->{name}        : '';
                 my $password    = defined $record->{plaintext}->{password}    ? $record->{plaintext}->{password}    : '';                  my $account     = defined $record->{plaintext}->{account}     ?
                 my $description = defined $record->{plaintext}->{description} ? $record->{plaintext}->{description} : '';                          $record->{plaintext}->{account}     : '';
                   my $password    = defined $record->{plaintext}->{password}    ?
                           $record->{plaintext}->{password}    : '';
                   my $description = defined $record->{plaintext}->{description} ?
                           $record->{plaintext}->{description} : '';
                 my $extra       = '';                  my $extra       = '';
   
                 my $plaintext = join("\000", $account, $password, $description, $extra);                  my $plaintext = join("\000", $account, $password, $description, $extra);
   
                 my $encrypted = $self->_crypt3des($plaintext, ENCRYPT);                  my $encrypted = _crypt3des($plaintext, $self->{digest}, ENCRYPT);
   
                 $record->{data} = join("\000", $name, $encrypted);                  $record->{data} = join("\000", $name, $encrypted);
         }          }
Line 181 
Line 175 
                 $self->_keyring_verify($pass) || return undef;                  $self->_keyring_verify($pass) || return undef;
         }          }
   
         my $seen_enc_pass = 0;          $self->{digest} ||= _calc_keys($self->{password});
         foreach my $record (@{ $self->{records} }) {  
                 unless ($seen_enc_pass) {  
                         # need to skip the first record because it is the encrypted password  
                         $seen_enc_pass = 1;  
                         next;  
                 }  
   
           foreach my $record (@{ $self->{records} }) {
                 next unless defined $record->{data};                  next unless defined $record->{data};
   
                 my ($name, $encrypted) = split /\000/, $record->{data}, 2;                  my ($name, $encrypted) = split /\000/, $record->{data}, 2;
                   next unless $encrypted;
   
                 $record->{plaintext}->{name} = $name;                  $record->{plaintext}->{name} = $name;
   
                 my $decrypted = $self->_crypt3des($encrypted, DECRYPT);                  my $decrypted = _crypt3des($encrypted, $self->{digest}, DECRYPT);
                 my ($account, $password, $description, $extra)                  my ($account, $password, $description, $extra)
                       = split /\000/, $decrypted, 4;                        = split /\000/, $decrypted, 4;
   
                 $record->{plaintext}->{account}     = defined $account     ? $account     : '';                  $record->{plaintext}->{account}     = defined $account     ?
                 $record->{plaintext}->{password}    = defined $password    ? $password    : '';                          $account     : '';
                 $record->{plaintext}->{description} = defined $description ? $description : '';                  $record->{plaintext}->{password}    = defined $password    ?
                           $password    : '';
                   $record->{plaintext}->{description} = defined $description ?
                           $description : '';
   
         #print "Name:      '$name'\n";                  #print "Name:      '$name'\n";
         #print "Encrypted: '$encrypted' - Length: " . length($encrypted) . "\n";                  #print "Encrypted: '$encrypted' - Length: " . length($encrypted) . "\n";
         #print "Hex:       '" . unpack("H*", $encrypted) . "'\n";                  #print "    Hex:   '" . unpack("H*", $encrypted) . "'\n";
         #print "Binary:    '" . unpack("b*", $encrypted) . "'\n";                  #print "    Binary:'" . unpack("b*", $encrypted) . "'\n";
         #print "Decrypted: '$decrypted' - Length: " . length($decrypted) . "\n";                  #print "Decrypted: '$decrypted' - Length: " . length($decrypted) . "\n";
         #print "Hex:       '" . unpack("H*", $decrypted) . "'\n";                  #print "    Hex:   '" . unpack("H*", $decrypted) . "'\n";
         #print "Binary:    '" . unpack("b*", $decrypted) . "'\n";                  #print "    Binary:'" . unpack("b*", $decrypted) . "'\n";
         #print "\n";                  #print "\n";
                 #print "Extra: $extra\n";                  #print "Extra: $extra\n";
                   #exit;
                 #--------------------------------------------------                  #--------------------------------------------------
                 # print "Account:     $account\n";                  # print "Account:     $account\n";
                 # print "Password:    $password\n";                  # print "Password:    $password\n";
Line 224 
Line 219 
   
 sub _calc_keys  sub _calc_keys
 {  {
         my $self = shift;          my $pass = shift;
   
         my $pass = $self->{'password'};  
         die "No password defined!" unless defined $pass;          die "No password defined!" unless defined $pass;
   
         my $digest = md5($pass);          my $digest = md5($pass);
Line 243 
Line 236 
         # print length $digest, "\n";          # print length $digest, "\n";
         #--------------------------------------------------          #--------------------------------------------------
   
         $self->{digest} = $digest;  
         return $digest;          return $digest;
 }  }
   
Line 273 
Line 265 
   
         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
                 if ($self->_calc_keys()) {                  $self->{digest} = _calc_keys($self->{password});
                   if ($self->{digest}) {
                         return 1;                          return 1;
                 } else {                  } else {
                         return undef;                          return undef;
Line 318 
Line 311 
         $self->{records}->[0]->{data} = $data;          $self->{records}->[0]->{data} = $data;
   
         $self->{password} = $pass;          $self->{password} = $pass;
         $self->_calc_keys();          $self->{digest}   = _calc_keys($self->{password});
   
         return 1;          return 1;
 }  }
   
   
 # XXX Have to make this encrypt as well as decrypting, but w00 h00!  # XXX It looks like they are using des_ecb2_encrypt so I dunno if that is different
 # do null padding on the end of a cleartext if we are going to encrypt it  
 sub _crypt3des {  sub _crypt3des {
         my ( $self, $plaintext, $flag ) = @_;          my ( $plaintext, $passphrase, $flag ) = @_;
           my $NULL = chr(0);
   
         my $passphrase = $self->{digest} || $self->_calc_keys();  
         $passphrase .= ' ' x (16*3);          $passphrase .= ' ' x (16*3);
         my $cyphertext = "";          my $cyphertext = "";
   
   
         my $size = length ( $plaintext );          my $size = length ( $plaintext );
         #print "STRING: '$plaintext' - Length: " . length($plaintext) . "\n";          #print "STRING: '$plaintext' - Length: " . length($plaintext) . "\n";
   
         # This check should see if it is plaintext first, if it is,          my @C;
         #   pad it with \000  
         # if not, then die  
         die "record not 8 byte padded" if (length($plaintext) % 8) && ! $flag;  
   
         my %C;  
         for ( 0..2 ) {          for ( 0..2 ) {
                 $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) {  
   # XXX From Crypt::TripleDES
   # http://search.cpan.org/src/VIPUL/Crypt-TripleDES-0.24/lib/Crypt/TripleDES.pm
   #
   #    for ( 0 .. (($size)/8) -1 ) {
   #     my $pt = substr( $plaintext, $_*8, 8 );
   #        $pt = Crypt::PPDES::des_ecb_encrypt( $flag ? $keyvecs{0} : $keyvecs{2}, $flag, $pt );
   #        $pt = Crypt::PPDES::des_ecb_encrypt( $keyvecs{1}, (not $flag), $pt );
   #        $pt = Crypt::PPDES::des_ecb_encrypt( $flag ? $keyvecs{2} : $keyvecs{0}, $flag, $pt );
   #        $cyphertext .= $pt;
   #    }
   
           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;
                         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;

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.10

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