Authen-SCRAM

 view release on metacpan or  search on metacpan

lib/Authen/SCRAM/Client.pm  view on Meta::CPAN

has minimum_iteration_count => (
    is      => 'ro',
    isa     => Num,
    default => 4096,
);

# The derived PBKDF2 password can be reused if the salt and iteration count
# is the same as a previous authentication conversation.
has _cached_credentials => (
    is      => 'rw',
    default => sub { [ "", 0, "" ] }, # salt, iterations, derived password
);

#--------------------------------------------------------------------------#
# provided by Authen::SCRAM::Role::Common
#--------------------------------------------------------------------------#

with 'Authen::SCRAM::Role::Common';

#pod =attr digest
#pod

lib/Authen/SCRAM/Client.pm  view on Meta::CPAN

    $self->_set_session(
        _s1 => $s_first_msg,
        c   => $self->_base64( encode_utf8( $self->_gs2_header ) ),
    );
    $self->_set_session( '_c2wop' => $self->_join_reply(qw/c r/) );

    # assemble proof
    my $salt  = decode_base64( $self->_get_session("s") );
    my $iters = $self->_get_session("i");
    if ( $iters < $self->minimum_iteration_count ) {
        croak sprintf( "SCRAM server requested %d iterations, less than the minimum of %d",
            $iters, $self->minimum_iteration_count );
    }

    my ( $stored_key, $client_key, $server_key ) = $self->computed_keys( $salt, $iters );

    $self->_set_session(
        _stored_key => $stored_key,
        _server_key => $server_key,
    );

lib/Authen/SCRAM/Server.pm  view on Meta::CPAN

#pod =attr credential_cb (required)
#pod
#pod This attribute must contain a code reference that takes a username (as a
#pod character string normalized by SASLprep) and returns the four user-credential
#pod parameters required by SCRAM: C<salt>, C<StoredKey>, C<ServerKey>, and
#pod C<iteration count>.  The C<salt>, C<StoredKey> and C<ServerKey> must be
#pod provided as octets (i.e. B<NOT> base64 encoded).
#pod
#pod If the username is unknown, it should return an empty list.
#pod
#pod     ($salt, $stored_key, $server_key, $iterations) =
#pod         $server->credential_cb->( $username );
#pod
#pod See L<RFC 5802: SCRAM Algorithm Overview|http://tools.ietf.org/html/rfc5802#section-3>
#pod for details.
#pod
#pod =cut

has credential_cb => (
    is       => 'ro',
    isa      => CodeRef,

lib/Authen/SCRAM/Server.pm  view on Meta::CPAN

=head2 credential_cb (required)

This attribute must contain a code reference that takes a username (as a
character string normalized by SASLprep) and returns the four user-credential
parameters required by SCRAM: C<salt>, C<StoredKey>, C<ServerKey>, and
C<iteration count>.  The C<salt>, C<StoredKey> and C<ServerKey> must be
provided as octets (i.e. B<NOT> base64 encoded).

If the username is unknown, it should return an empty list.

    ($salt, $stored_key, $server_key, $iterations) =
        $server->credential_cb->( $username );

See L<RFC 5802: SCRAM Algorithm Overview|http://tools.ietf.org/html/rfc5802#section-3>
for details.

=head2 auth_proxy_cb

If provided, this attribute must contain a code reference that takes an
B<authentication> username and a B<authorization> username (both as character
strings), and return a true value if the authentication username is permitted

t/client.t  view on Meta::CPAN

    {
        # force client nonce to match RFC5802 example
        my $client = get_client( _nonce_generator => sub { "fyko+d2lbbFgONRv9qkxdawL" } );
        my $first = $client->first_msg();

        # RFC5802 example server-first-message, with too low iteration count
        my $server_first =
          "r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4095";
        like(
            exception { $client->final_msg($server_first) },
            qr/requested 4095 iterations, less than/,
            "Default iteration count"
        );
    }

    {
        # force client nonce to match RFC5802 example
        my $client = get_client(
            _nonce_generator        => sub { "fyko+d2lbbFgONRv9qkxdawL" },
            minimum_iteration_count => 8192
        );
        my $first = $client->first_msg();

        # RFC5802 example server-first-message, with too low iteration count
        my $server_first =
          "r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=8191";
        like(
            exception { $client->final_msg($server_first) },
            qr/requested 8191 iterations, less than/,
            "Custom iteration count"
        );
    }
};

done_testing;
#
# This file is part of Authen-SCRAM
#
# This software is Copyright (c) 2014 by David Golden.

t/lib/TestSCRAM.pm  view on Meta::CPAN


use Encode qw/encode_utf8/;
use MIME::Base64 qw/decode_base64/;
use PBKDF2::Tiny qw/derive digest_fcn hmac/;

use base 'Exporter';
our @EXPORT = qw/get_client get_server get_cred check_proxy/;

my ( $sha1, $sha1_block ) = digest_fcn('SHA-1');

# username => [ base64-salt, password, iterations ]
# entry 'user' matches example from RFC 5802
my %CRED_INPUTS = (
    user                => [ 'QSXCR+Q6sek8bf92', 'pencil',                 4096 ],
    johndoe             => [ 'saltSALTsaltSALT', 'passPASSpass',           4096 ],
    "johnd\N{U+110B}oe" => [ 'salt',             "pass\N{U+110B}PASSpass", 4096 ],
);

# username => [ salt, stored key, server key, iterations ];
my %CRED;

for my $user ( keys %CRED_INPUTS ) {
    my ( $salt, $pw, $i ) = @{ $CRED_INPUTS{$user} };
    $salt = decode_base64($salt);
    my $salted_password = derive( 'SHA-1', encode_utf8($pw), $salt, $i );
    my $client_key = _hmac( $salted_password, "Client Key" );
    my $stored_key = $sha1->($client_key);
    my $server_key = _hmac( $salted_password, "Server Key" );
    $CRED{$user} = [ $salt, $stored_key, $server_key, $i ];



( run in 1.277 second using v1.01-cache-2.11-cpan-96521ef73a4 )