Authen-Passphrase

 view release on metacpan or  search on metacpan

lib/Authen/Passphrase/MD5Crypt.pm  view on Meta::CPAN

sub new {
	my $class = shift;
	my $self = bless({}, $class);
	my $passphrase;
	while(@_) {
		my $attr = shift;
		my $value = shift;
		if($attr eq "salt") {
			croak "salt specified redundantly"
				if exists $self->{salt};
			$value =~ m#\A[\x00-\xff]*\z#
				or croak "not a valid salt";
			$self->{salt} = "$value";
		} elsif($attr eq "salt_random") {
			croak "salt specified redundantly"
				if exists $self->{salt};
			$self->{salt} = encode_base64(random_bytes(6), '');
			$self->{salt} =~ tr{A-Za-z0-9+/=}{./0-9A-Za-z}d;
		} elsif($attr eq "hash_base64") {
			croak "hash specified redundantly"
				if exists($self->{hash_base64}) ||
					defined($passphrase);
			$value =~ m#\A[./0-9A-Za-z]{21}[./01]\z#
				or croak "\"$value\" is not a valid ".
						"MD5-based crypt() hash";
			$self->{hash_base64} = "$value";
		} elsif($attr eq "passphrase") {
			croak "passphrase specified redundantly"
				if exists($self->{hash_base64}) ||
					defined($passphrase);
			$passphrase = $value;
		} else {
			croak "unrecognised attribute `$attr'";
		}
	}
	croak "salt not specified" unless exists $self->{salt};
	$self->{hash_base64} = $self->_hash_base64_of($passphrase)
		if defined $passphrase;
	croak "hash not specified" unless exists $self->{hash_base64};
	return $self;
}

=item Authen::Passphrase::MD5Crypt->from_crypt(PASSWD)

Generates a new passphrase recogniser object using the MD5-based crypt()
algorithm, from a crypt string.  The crypt string must consist of
"B<$1$>", the salt, "B<$>", then 22 base 64 digits giving the hash.
The salt may be up to 8 characters long, and cannot contain "B<$>"
or any character that cannot appear in a crypt string.

=cut

sub from_crypt {
	my($class, $passwd) = @_;
	if($passwd =~ /\A\$1\$/) {
		$passwd =~ m:\A\$1\$([!-#%-9;-~]{0,8})\$([./0-9A-Za-z]{22})\z:
			or croak "malformed \$1\$ data";
		my($salt, $hash) = ($1, $2);
		return $class->new(salt => $salt, hash_base64 => $hash);
	}
	return $class->SUPER::from_crypt($passwd);
}

=item Authen::Passphrase::MD5Crypt->from_rfc2307(USERPASSWORD)

Generates a new passphrase recogniser object using the MD5-based
crypt() algorithm, from an RFC 2307 string.  The string must consist of
"B<{CRYPT}>" (case insensitive) followed by an acceptable crypt string.

=back

=head1 METHODS

=over

=item $ppr->salt

Returns the salt, in raw form.

=cut

sub salt {
	my($self) = @_;
	return $self->{salt};
}

=item $ppr->hash_base64

Returns the hash value, as a string of 22 base 64 digits.

=cut

sub hash_base64 {
	my($self) = @_;
	return $self->{hash_base64};
}

=item $ppr->match(PASSPHRASE)

=item $ppr->as_crypt

=item $ppr->as_rfc2307

These methods are part of the standard L<Authen::Passphrase> interface.
Not every passphrase recogniser of this type can be represented as a
crypt string: the crypt format only allows the salt to be up to eight
bytes, and it cannot contain any NUL or "B<$>" characters.

=cut

sub _hash_base64_of {
	my($self, $passphrase) = @_;
	die "can't use a crypt-incompatible salt yet ".
			"(need generalised Crypt::MD5Passwd)"
		if $self->{salt} =~ /[^\!-\#\%-9\;-\~]/ ||
			length($self->{salt}) > 8;
	my $hash = unix_md5_crypt($passphrase, $self->{salt});
	$hash =~ s/\A.*\$//;
	return $hash;
}



( run in 1.478 second using v1.01-cache-2.11-cpan-364913b4093 )