Crypt-HashCash

 view release on metacpan or  search on metacpan

lib/Crypt/HashCash/Client.pm  view on Meta::CPAN

# -*-cperl-*-
#
# Crypt::HashCash::Client - Client for HashCash Digital Cash
# Copyright (c) 2001-2017 Ashish Gulhati <crypt-hashcash at hash.neo.tc>
#
# $Id: lib/Crypt/HashCash/Client.pm v1.130 Sat Dec 22 18:42:25 PST 2018 $

package Crypt::HashCash::Client;

use warnings;
use strict;

use Crypt::Random qw(makerandom);
use Bytes::Random::Secure;
use Crypt::RSA::Blind;
use Crypt::ECDSA::Blind;
use Crypt::HashCash::Coin;
use Crypt::HashCash::CoinRequest;
use Crypt::CBC;
use Persistence::Object::Simple;
use Crypt::EECDH;
use Crypt::HashCash qw (_dec _hex);
use Compress::Zlib;
use vars qw( $VERSION $AUTOLOAD );

our ( $VERSION ) = '$Revision: 1.130 $' =~ /\s+([\d\.]+)/;

sub new {
  my $class = shift;
  my %arg = @_;
  bless { RSAB           =>   new Crypt::RSA::Blind,
	  ECDSAB         =>   new Crypt::ECDSA::Blind,
	  SIGSCHEME      =>   'ECDSA',
	  VERSION        =>   "Crypt::HashCash::Client v$VERSION",
	  VAULTCONF      =>   $arg{VaultConfig} || '/tmp/vault.cfg',
	  DEBUG          =>   $arg{Debug} || 0,
	  XSIZE          =>   128
	}, $class;
}

sub loadkeys {
  my $self = shift;
  my %pkey;
  my $keydb = new Persistence::Object::Simple ('__Fn' => $self->vaultconf);
  $self->keydb($keydb); $self->sigscheme($keydb->{sigscheme});
  $self->denoms([sort { $a <=> $b } keys %{$self->keydb->{pub}}]);
  my $sigmod = 'Crypt::' . $self->sigscheme . '::Blind';
  no strict 'refs';
  for (@{$self->denoms}) {
    $pkey{$_} = &{$sigmod.'::PubKey::from_hex'}($self->keydb->{pub}->{$_});
  }
  $self->vaultkey(pack ('H*',$self->keydb->{vaultpub}));
  $self->mintkeys(\%pkey);
}

sub request_coin {
  my $self = shift; my %arg = @_;
  $self->_diag("CLIENT: request_coin()\n");
  return unless my $mintkey = $self->mintkeys->{$arg{Denomination}};
  my $x = makerandom( Size => $self->xsize, Strength => 1 );
  $self->_diag("x: $x\n");
  my $signer = $self->sigscheme eq 'RSA' ? $self->rsab : $self->ecdsab;
  my $req = $signer->request(Key => $mintkey, Message => $x, Init => $arg{Init});
  $self->_diag("req: $req\n");
  $self->_request($arg{Init} => $x);
  return ( bless { R => $req, D => $arg{Denomination}, Init => $arg{Init} }, 'Crypt::HashCash::CoinRequest' );
}

sub unblind_coin {
  my $self = shift;
  $self->_diag("CLIENT: unblind_coin()\n");
  my $bcoin = shift;
  return unless my $mintkey = $self->mintkeys->{$bcoin->{D}};
  my $signer = $self->sigscheme eq 'RSA' ? $self->rsab : $self->ecdsab;
  my $coin = $signer->unblind(Signature => $bcoin->{C}, Key => $mintkey, Init => $bcoin->{Init});
  $self->_diag("coin (bc / b): $coin\n");
  my $x = $self->_request($bcoin->{Init});
  return ( bless { X => $x, D => $bcoin->{D}, Z => $coin }, 'Crypt::HashCash::Coin' );
}



( run in 0.986 second using v1.01-cache-2.11-cpan-e1769b4cff6 )