Ignore:
Timestamp:
04/08/09 04:07:58 (15 years ago)
Author:
nanardon
Message:
  • start user interface for encypted polls
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/Vote/DB/Poll.pm

    r173 r175  
    88use Mail::Mailer; 
    99use Crypt::RSA; 
     10use Crypt::RSA::Key::Public::SSH; 
     11use Crypt::RSA::Key::Private::SSH; 
    1012use Crypt::CBC; 
    1113use XML::Simple; 
     
    3739 
    3840sub voteid { $_[0]->{voteid} } 
     41 
     42sub setup { 
     43    my ($self) = @_; 
     44    $self->param( 
     45        free_choice => 0, 
     46        choice_count => 1, 
     47    ); 
     48} 
    3949 
    4050sub param { 
     
    294304    my ($self, $choice, $fchoice) = @_; 
    295305 
     306    my $uid = ($self->is_crypted 
     307        ? $self->_register_ballot_crypted($choice, $fchoice) 
     308        : $self->_register_ballot_clear($choice, $fchoice)) 
     309        or do { 
     310            self->db->rollback; 
     311            return; 
     312        }; 
     313 
     314    $uid 
     315} 
     316 
     317sub _register_ballot_clear { 
     318    my ($self, $choice, $fchoice, $uid) = @_; 
     319 
    296320    my $addb = $self->db->prepare_cached( 
    297321        q{ 
     
    299323        } 
    300324    ); 
    301     my $uid = Vote::DB::common::gen_uid(); 
     325    $uid ||= Vote::DB::common::gen_uid(); 
    302326    $addb->execute($uid, $self->voteid, scalar(@{$fchoice || []}) ? undef : 'f') or do { 
    303327        self->db->rollback; 
     
    336360 
    337361    $uid; 
     362} 
     363 
     364sub _register_ballot_crypted { 
     365    my ($self, $choice, $fchoice) = @_; 
     366    my $xml = XML::Simple->new(ForceArray => 1, RootName => 'ballot'); 
     367    my $symkey = map{ chr(rand(256)) } (1 .. (256 / 8)); 
     368    my $cipher = new Crypt::CBC($symkey, 'DES'); 
     369    my $ballotuid = Vote::DB::common::gen_uid(); 
     370    my $encryptedballot = $cipher->encrypt_hex( 
     371        $xml->XMLout({ 
     372            id => $ballotuid, 
     373            sbal => $choice, 
     374            fsbal => $fchoice 
     375        }) 
     376    ); 
     377    my $encsymkey = $self->rsa->encrypt ( 
     378        Message    => $symkey, 
     379        Key        => $self->public_key, 
     380        Armour     => 1, 
     381    ) || die $self->rsa->errstr(); 
     382 
     383    my $addenc = $self->db->prepare_cached( 
     384        q{insert into ballot_enc (id, data, enckey, poll) values (?,?,?,?)} 
     385    ); 
     386 
     387    my $uid = Vote::DB::common::gen_uid(); 
     388    $addenc->execute($uid, $encryptedballot, $encsymkey, $self->voteid); 
     389    $ballotuid; 
     390} 
     391 
     392sub _decrypted_ballot { 
     393    my ($self, $ballotid, $privkey) = @_; 
     394    my $sth = $self->db->prepare_cached( 
     395        q{select * from ballot_enc where id = ? for update} 
     396    ); 
     397    $sth->execute($ballotid); 
     398    my $ballot = $sth->fetchrow_hashref; 
     399    $sth->finish; 
     400    my $encsymkey = $ballot->{enckey}; 
     401    my $data = $ballot->{data}; 
     402    my $symkey = $self->rsa->decrypt ( 
     403        Cyphertext => $encsymkey, 
     404        Key        => $privkey, 
     405        Armour     => 1, 
     406    ) || die $self->rsa->errstr(); 
     407    my $cipher = new Crypt::CBC($symkey, 'DES'); 
     408    my $xmldata = XMLin($cipher->decrypt_hex($data), ForceArray => 1); 
     409    $self->_register_ballot_clear($xmldata->{sbal}, $xmldata->{fsbal}, $xmldata->{id}); 
     410    my $upd = $self->db->prepare_cached(q{update ballot_enc set decrypted = true where id = ?}); 
     411    if ($upd->execute($ballotid)) { 
     412        $self->db->commit; 
     413        return; 
     414    } else { 
     415        $self->db->rollback; 
     416        return 1; 
     417    } 
     418}     
     419 
     420sub decrypted_ballots { 
     421    my ($self, $password) = @_; 
     422    my $privkey = $self->private_key($password); 
     423    foreach ($self->list_ballot_need_dec) { 
     424        $self->_decrypted_ballot($_, $privkey); 
     425    } 
    338426} 
    339427 
     
    422510} 
    423511 
     512sub is_crypted { 
     513    my ($self) = @_; 
     514    return $self->info->{public_key} ? 1 : 0; 
     515} 
     516 
    424517sub ballot_count { 
    425518    my ($self) = @_; 
    426  
    427     my $sth = $self->db->prepare_cached( 
    428         q{ 
    429         select count(*) from ballot where poll = ? 
    430         } 
     519    return $self->is_crypted 
     520        ? $self->ballot_count_crypt 
     521        : $self->ballot_count_clear; 
     522} 
     523 
     524sub ballot_count_clear { 
     525    my ($self) = @_; 
     526 
     527    my $sth = $self->db->prepare_cached( 
     528        q{select count(*) from ballot where poll = ?} 
     529    ); 
     530 
     531    $sth->execute($self->voteid); 
     532    my $res = $sth->fetchrow_hashref; 
     533    $sth->finish; 
     534    $res->{count} 
     535} 
     536 
     537sub ballot_count_crypt { 
     538    my ($self) = @_; 
     539 
     540    my $sth = $self->db->prepare_cached( 
     541        q{select count(*) from ballot_enc where poll = ?} 
    431542    ); 
    432543 
     
    565676        q{ 
    566677        select id from ballot where poll = ? 
     678        order by id 
     679        } 
     680    ); 
     681    $sth->execute($self->voteid); 
     682    my @ids; 
     683    while (my $res = $sth->fetchrow_hashref) { 
     684        push(@ids, $res->{id}); 
     685    } 
     686    @ids 
     687} 
     688 
     689sub list_ballot_enc { 
     690    my ($self) = @_; 
     691 
     692    my $sth = $self->db->prepare_cached( 
     693        q{ 
     694        select id from ballot_enc where poll = ? 
     695        order by id 
     696        } 
     697    ); 
     698    $sth->execute($self->voteid); 
     699    my @ids; 
     700    while (my $res = $sth->fetchrow_hashref) { 
     701        push(@ids, $res->{id}); 
     702    } 
     703    @ids 
     704} 
     705 
     706sub list_ballot_need_dec { 
     707    my ($self) = @_; 
     708 
     709    my $sth = $self->db->prepare_cached( 
     710        q{ 
     711        select id from ballot_enc where poll = ? and decrypted = 'false' 
    567712        order by id 
    568713        } 
     
    715860 
    716861sub gen_poll_keys { 
    717     my ($self) = @_; 
     862    my ($self, $password) = @_; 
    718863    my ($public, $private) = $self->rsa->keygen ( 
    719864        Identity  => 'Epoll Vote ' . $self->voteid, 
    720865        Size      => 768, 
    721         Password  => undef, 
     866        Password  => $password, 
    722867        Verbosity => 0, 
    723868        KF=>'SSH', 
     
    732877    my ($self) = @_; 
    733878    my $serialize = $self->info->{public_key} or return; 
    734     my $pubkey = Crypt::RSA::Key::Public->new; 
    735     $pubkey->deserialize($serialize); 
    736  
     879    my $pubkey = Crypt::RSA::Key::Public::SSH->new; 
     880    $pubkey->deserialize(String => [ $serialize ]); 
    737881    $pubkey 
    738882} 
    739883 
     884sub private_key { 
     885    my ($self, $password) = @_; 
     886    my $serialize = $self->info->{private_key} or return; 
     887    my $privkey = Crypt::RSA::Key::Private::SSH->new; 
     888    $privkey->deserialize(String => [ decode_base64($serialize) ], Passphrase => $password); 
     889    $privkey 
     890} 
    740891=head1 AUTHOR 
    741892 
Note: See TracChangeset for help on using the changeset viewer.