Skip to content

Instantly share code, notes, and snippets.

@TBSliver
Last active October 7, 2022 08:39
Show Gist options
  • Save TBSliver/f77ffd7931734fea31518886f1f2561f to your computer and use it in GitHub Desktop.
Save TBSliver/f77ffd7931734fea31518886f1f2561f to your computer and use it in GitHub Desktop.
Custom Authen::Passphrase Algorithm
package Authen::Passphrase::MyCustomAlg;
=head1 DESCRIPTION
Override for a custom passphrase type
=cut
use strict;
use warnings;
use Authen::Passphrase;
use Carp qw(croak carp);
use MIME::Base64 qw/ encode_base64 decode_base64 /;
use String::Random;
our $VERSION = "0.001";
use parent "Authen::Passphrase";
my $algtag = "mycustomalg";
sub new {
my $class = shift;
my %args = @_;
if ($args{salt_random}) {
if (! defined $args{salt}) {
my $rand = String::Random->new;
$args{salt} = $rand->randpattern('s' x 12);
}
}
my $self = bless({
salt => $args{salt},
}, $class);
if ( defined $args{passphrase} ) {
# Only hash it if it wasnt already a hash
$self->{hash} = $args{from_hash}
? $args{passphrase}
: $self->_as_hash( $args{passphrase} );
} else {
croak 'No passphrase to hash';
}
return $self;
}
sub from_rfc2307 {
my ( $class, $userpassword ) = @_;
if ( $userpassword =~ /\A\{(?i:$algtag)\}/ ) {
$userpassword =~ /\A\{.*?\}(.*)\$(.*)\z/
or croak sprintf( "malformed {%s} data", uc $algtag );
my $b64_salt = $1;
my $text = $2;
my $salt = decode_base64($b64_salt);
return $class->new( salt => $salt, passphrase => $text, from_hash => 1 );
}
return $class->SUPER::from_rfc2307($userpassword);
}
sub _as_hash {
my $self = shift;
my $to_hash = shift;
my $salt = $self->{salt} or croak "No salt set";
# Change this to yuor actual algorithm
return $salt . ":" . $to_hash;
}
sub match {
my ( $self, $passphrase ) = @_;
return $self->{hash} eq $self->_as_hash( $passphrase );
}
sub as_rfc2307 {
my $self = shift;
my $b64_salt = encode_base64($self->{salt}, '');
return sprintf( "{%s}%s$%s", uc $algtag, $b64_salt, $self->{hash} );
}
1;
use strict;
use warnings;
use Test::More;
use MIME::Base64 qw/ encode_base64 /;
use Authen::Passphrase;
use PadWalker qw(closed_over);
closed_over(Authen::Passphrase->can('from_rfc2307'))
->{'%rfc2307_scheme_handler'}
->{'MYCUSTOMALG'} = [ 'Authen::Passphrase::MyCustomAlg', 0 ];
my $passphrase = 's3cr3t';
my $salt = 'beef';
my $hash = $salt . ':' . $passphrase;
my $b64_salt = encode_base64($salt, '');
my $authen = Authen::Passphrase->from_rfc2307( "{MYCUSTOMALG}$b64_salt\$$hash" );
isa_ok $authen, 'Authen::Passphrase::MyCustomAlg';
is $authen->{hash}, $hash, 'Hash is found correctly';
ok $authen->match( $passphrase ), 'Matched correctly';
ok !$authen->match( 'no match' ), 'Failed match correctly';
is $authen->as_rfc2307, "{MYCUSTOMALG}$b64_salt\$$hash", 'rfc2307 built correctly';
done_testing;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment