Apache2-API
view release on metacpan or search on metacpan
lib/Apache2/API/Password.pod view on Meta::CPAN
=encoding utf8
=head1 NAME
Apache2::API::Password - Create and verify HTTP Basic Auth password hashes (APR1/bcrypt/SHA-crypt)
=head1 SYNOPSIS
use Apache2::API::Password;
# Create a new hash from a cleartext password (random salt)
# MD5-crypt (APR1, "$apr1$") - default
my $ht = Apache2::API::Password->new( 'secret', create => 1 );
my $hash = $ht->hash; # "$apr1$abcd1234$...."
# Create APR1 with a provided salt (max 8 chars; [./0-9A-Za-z])
my $ht2 = Apache2::API::Password->new( 'secret', create => 1, salt => 'hfT7jp2q' );
say $ht2->hash;
# Wrap an existing APR1 ($apr1$) hash and verify user input
my $ht3 = Apache2::API::Password->new( '$apr1$hfT7jp2q$DcU1Hf5w2Q/9G8yqv1hbl.' );
my $ok = $ht3->matches( 'secret' );
# Bcrypt ($2y$), choose a cost (04..31); defaults to 12
my $b = Apache2::API::Password->new('s3cret', create => 1, algo => 'bcrypt', bcrypt_cost => 12);
say $b->hash; # "$2y$12$..."
# SHA-crypt ($5$ = SHA-256, $6$ = SHA-512), optionally set rounds
my $s6 = Apache2::API::Password->new('s3cret', create => 1, algo => 'sha512', sha_rounds => 150000);
say $s6->hash; # "$6$rounds=150000$..."
# Accessors
my $hash_password = $ht->hash;
# parsed from the hash
my $salt = $ht3->salt;
=head1 VERSION
v0.1.1
=head1 DESCRIPTION
C<Apache2::API::Password> creates and verifies password hashes used by Apache HTTP Basic Authentication. It supports:
=over 4
=item * APR1 / MD5-crypt (C<$apr1$>) - same as C<htpasswd -m>
This implements the full APR1 algorithm (password + magic + salt, alternate sum, bit-mixing, 1000 rounds, and the crypt-style 64-symbol encoding) and is fully compatible with Apacheâs C<htpasswd -m> and L<Crypt::PasswdMD5/ apache_md5_crypt>.
=item * bcrypt (C<$2y$>) - same as C<htpasswd -B>
Generated via the system C<crypt(3)> when available; otherwise falls back to C<Authen::Passphrase::BlowfishCrypt>, C<Crypt::Bcrypt>, or
C<Crypt::Eksblowfish::Bcrypt>.
=item * SHA-crypt (C<$5$ = SHA-256, $6$ = SHA-512>) - same as C<htpasswd -2> / C<-5>
Generated via the system C<crypt(3)> when available; otherwise falls back to C<Crypt::Passwd::XS>.
=back
This class handles existing Apache password or create new ones, and makes it possible to retrieve the encoded password, or to test if a user-provided clear password matches.
When constructing from an existing hash, the scheme is auto-detected by prefix (C<$apr1$>, C<$2y$>, C<$5$>, C<$6$>) and C<matches> uses the appropriate verifier.
=head2 CONSTRUCTOR
=head2 new
my $ht = Apache2::API::Password->new( $clear, create => 1 );
my $ht = Apache2::API::Password->new( $clear, create => 1, salt => $salt );
my $ht = Apache2::API::Password->new( $apr1_hash );
# Multi-algorithm creation:
my $b = Apache2::API::Password->new( $clear, create => 1, algo => 'bcrypt', bcrypt_cost => 12 );
my $s5 = Apache2::API::Password->new( $clear, create => 1, algo => 'sha256', sha_rounds => 6000 );
my $s6 = Apache2::API::Password->new( $clear, create => 1, algo => 'sha512', sha_rounds => 150000 );
This creates an instance either from:
=over 4
=item * a cleartext password (C<$clear>) with C<create =E<gt> 1>
Generates a new hash. If C<salt> is provided:
=over 8
=item * APR1: clamped to C<[./0-9A-Za-z]>, truncated to 8 chars.
lib/Apache2/API/Password.pod view on Meta::CPAN
$ht->salt( 'abcd1234' );
Gets or sets the salt (1â8 chars in C<[./0-9A-Za-z]> for C<MD5>, 22 chars for C<bcrypt>, 1â16 chars for C<SHA-256/512>, alphabet C<[./0-9A-Za-z]>).
If an hash is provided upon object construction, its C<salt> will be derived, and stored.
=head2 sha_rounds
$ht->sha_rounds(150000);
my $r = $ht->sha_rounds;
Sets or gets the number of rounds for C<SHA-256/512> (1000â999999999). Default is 5000.
=head2 make
my $hash = $ht->make( $clear_password );
my $hash = $ht->make( $clear_password, $salt );
Generates a hash using the selected L<algorithm|/algo>. If C<$salt> is omitted, the value stored in L</salt> is used or a random C<salt> is generated. The C<salt> is clamped to the valid alphabet and truncated to the appropriate number of characters ...
Returns the generated hash on success, or, upon error, C<undef> in scalar context, or an empty list in list context.
=head2 make_md5
my $hash = $ht->make_md5( $clear_password, $salt );
Generates an APR1 MD5 hash (C<$apr1$<salt>$<hash>). Salt is 1â8 chars, default random.
=head2 make_bcrypt
my $hash = $ht->make_bcrypt( $clear_password, $salt );
Generates a bcrypt hash (C<$2y$<cost>$<salt-and-hash>). Salt is 22 chars, default random. Uses C<bcrypt_cost>.
=head2 make_sha256
my $hash = $ht->make_sha256( $clear_password, $salt );
Generates a SHA-256 crypt hash (C<$5$[rounds=<n>$]<salt>$<hash>). Salt is 1â16 chars, default random. Uses C<sha_rounds>.
=head2 make_sha512
my $hash = $ht->make_sha512( $clear_password, $salt );
Generates a SHA-512 crypt hash (C<$6$[rounds=<n>$]<salt>$<hash>). Salt is 1â16 chars, default random. Uses C<sha_rounds>.
=head2 matches
my $ok = $ht->matches( $user_input_password );
Compute a fresh hash using the instance salt and compare with the stored L<hash|/hash>.
Returns true if the cleartext password matches.
=head1 EXAMPLES
=head2 Creating a C<.htpasswd> line
my $user = 'john';
my $ht = Apache2::API::Password->new( 's3cret', create => 1 );
say join( ':', $user, $ht->hash );
=head2 Verifying a login
my $stored = '$apr1$hfT7jp2q$DcU1Hf5w2Q/9G8yqv1hbl.';
my $ht = Apache2::API::Password->new( $stored );
if( $ht->matches( $input_password ) )
{
# ok
}
=head1 THREAD SAFETY
This module keeps per-object state only (C<algo>, C<salt>, C<bcrypt_cost>, C<sha_rounds>, C<hash>) and uses no mutable global variables except precompiled regex constants. As such, it is I<re-entrant> and safe to use from multiple Perl L<ithreads|per...
For bcrypt/SHA-crypt, verification/generation prefers the system C<crypt(3)>; on modern libcs this is thread-safe. When the system lacks support, fallbacks are used:
=over 4
=item * L<Authen::Passphrase::BlowfishCrypt>, L<Crypt::Bcrypt>, L<Crypt::Eksblowfish::Bcrypt> (bcrypt)
=item * L<Crypt::Passwd::XS> (bcrypt and SHA-crypt)
=back
These libraries are widely used and do not expose shared mutable globals for the operations performed here; there are no known thread-safety issues in typical Perl ithread usage. If your deployment uses C<fork> rather than ithreads, objects are indep...
=head1 COMPATIBILITY
=over 4
=item * APR1 output is identical to C<htpasswd -m> and L<Crypt::PasswdMD5/apache_md5_crypt>.
=item * bcrypt output is compatible with C<htpasswd -B> (C<$2y$...>).
=item * SHA-crypt output is compatible with C<htpasswd -2> (C<$5$>) and C<-5> (C<$6$>).
=back
All 64 encoding symbols (including trailing C<.> or C</>) are valid.
=head1 SECURITY NOTES
=over 4
=item * Empty passwords
All algorithms accept empty strings. An empty password will verify successfully if you store its hash. Avoid this in production.
=item * Legacy algorithm
APR1/MD5-crypt is legacy and weak by modern standards. Prefer C<bcrypt> (with a cost appropriate to your CPU budget) or C<sha512> (SHA-crypt) where bcrypt is not available; retain C<APR1> only for Apache compatibility. For bcrypt, remember the 72-byt...
=item * Salt generation
Salt generation requires either L<Crypt::URandom> or L<Bytes::Random::Secure> to be installed. If neither is available, C<make>, C<make_md5>, C<make_bcrypt>, C<make_sha256>, and C<make_sha512> will return an error. The use of the non-cryptographic C<...
=back
=head1 AUTHOR
( run in 0.336 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )