version 1.8, 2006/11/10 17:31:38 |
version 1.10, 2006/12/06 18:45:42 |
|
|
# 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.7 2006/11/10 16:45:42 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; |
|
|
$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); |
|
|
sub Load |
sub Load |
{ |
{ |
my $self = shift; |
my $self = shift; |
|
$self->{'appinfo'} = {}; |
|
$self->{'records'} = []; |
$self->SUPER::Load(@_); |
$self->SUPER::Load(@_); |
|
|
foreach my $record (@{ $self->{records} }) { |
foreach my $record (@{ $self->{records} }) { |
|
|
{ |
{ |
my $self = shift; |
my $self = shift; |
$self->Encrypt() || return undef; |
$self->Encrypt() || return undef; |
return $self->SUPER::Load(@_); |
return $self->SUPER::Write(@_); |
} |
} |
|
|
sub Encrypt |
sub Encrypt |
|
|
|
|
# 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; |
|
|
|
|
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; |
} |
} |
|
|
|
|
# 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}); |
|
|
# XXX It looks like they are using des_ecb2_encrypt so I dunno if that is different |
# 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 = ""; |
|
|
$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; |
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; |