Algorithm-IRCSRP2

 view release on metacpan or  search on metacpan

lib/Algorithm/IRCSRP2.pm  view on Meta::CPAN

use Digest::SHA;
use MIME::Base64;
use Math::BigInt only => 'GMP,Pari';

# CPAN
use Crypt::OpenSSL::AES;

# local
use Algorithm::IRCSRP2::Utils qw(:all);

has 'error' => (
    'isa' => 'Str',
    'is'  => 'rw',
);

has 'nickname' => (
    'isa'     => 'Str',
    'is'      => 'rw',
    'default' => 'unknown'
);

lib/Algorithm/IRCSRP2.pm  view on Meta::CPAN

=head2 Optional Attributes

=over

=item * B<am_i_dave> (ro, Bool) - Child class will set this.

=item * B<cbc_blocksize> (ro, Int) - CBC blocksize. Defaults to '16'.

=item * B<debug_cb> (rw, CodeRef) - Debug callback. Defaults to C<print()>

=item * B<error> (rw, Str) - If set, there was an error.

=item * B<nickname> (rw, Str) - Child class will set this. Defaults to 'unknown'.

=back

=head1 PUBLIC API METHODS

=over

=item * B<init()> - Setup object for key exchange.

=item * B<encrypt_message($msg, $who)> - Returns encrypted message with
plaintext C<$msg> from nickname C<$who>.

=item * B<decrypt_message($msg)> - Returns decrypted text from encrypted
C<$msg>. C<die()>s on errors.

=back

=head1 SEE ALSO

=over

=item * L<http://www.bjrn.se/ircsrp/>

=item * See L<https://gitorious.org/ircsrp/ircsrp> for a working version used in

lib/Algorithm/IRCSRP2/Alice.pm  view on Meta::CPAN

# CPAN
use Crypt::OpenSSL::AES;
use Moose::Util::TypeConstraints qw(enum);

# local
use Algorithm::IRCSRP2::Utils qw(:all);

has '+am_i_dave' => ('default' => 0, 'is' => 'ro');

has 'state' => (
    'isa'     => enum([qw(null error init srpa0 srpa1 srpa2 srpa3 authenticated)]),
    'is'      => 'rw',
    'default' => 'null',
    'trigger' => sub {
        my ($self, $new, $old) = @_;

        $self->debug_cb->("State change $old -> $new");

        if ($new eq 'error') {
            $self->debug_cb->('Fatal error: ', $self->error);
        }
    }
);

sub srpa0 {
    my ($self) = @_;

    $self->state('srpa0');

    return '+srpa0 ' . $self->I();

lib/Algorithm/IRCSRP2/Alice.pm  view on Meta::CPAN

    $self->s($s);

    my $B = $self->B(bytes2int($decoded));

    if ($B->copy->bmod(N()) != 0) {
        $self->state('srpa1');

        return $self->srpa2();
    }
    else {
        $self->error('srpa1');
        $self->state('error');
        return 0;
    }
}

sub srpa2 {
    my ($self) = @_;

    # a = random integer with 1 < a < N.
    my $a = Math::BigInt->new(gen_a());
    $self->a($a);

lib/Algorithm/IRCSRP2/Alice.pm  view on Meta::CPAN

sub verify_srpa3 {
    my ($self, $msg) = @_;

    $msg =~ s/^\+srpa3 //;

    my $cipher = MIME::Base64::decode_base64($msg);

    my $cmac = substr($cipher, 0, 16);

    if (hmac_sha256_128($self->K2(), substr($cipher, 16)) ne $cmac) {
        $self->error('incorrect mac');
        $self->state('error');
    }

    $self->state('srpa3');

    $self->cipher(Crypt::OpenSSL::AES->new($self->K1()));

    my $plain = $self->cbc_decrypt(substr($cipher, 16));

    my $sessionkey = substr($plain, 0,  32);
    my $mackey     = substr($plain, 32, 32);

lib/Algorithm/IRCSRP2/Alice.pm  view on Meta::CPAN


    $self->debug_cb->('sessionkey ' . bytes2int($sessionkey));
    $self->debug_cb->('mackey ' . bytes2int($mackey));

    my $M2ver = H(join('', int2bytes($self->A), $self->M1, int2bytes($self->S)));

    $self->debug_cb->('M2 ' . bytes2int($M2));
    $self->debug_cb->('M2ver ' . bytes2int($M2ver));

    if ($M2 ne $M2ver) {
        $self->error('M2 != M2ver');
        $self->state('error');
    }

    $self->session_key($sessionkey);
    $self->cipher(Crypt::OpenSSL::AES->new($sessionkey));
    $self->mac_key($mackey);

    $self->state('authenticated');

    return 1;
}



( run in 0.293 second using v1.01-cache-2.11-cpan-65fba6d93b7 )