summaryrefslogtreecommitdiff
path: root/lib/App/Raps2/Password.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/App/Raps2/Password.pm')
-rw-r--r--lib/App/Raps2/Password.pm227
1 files changed, 111 insertions, 116 deletions
diff --git a/lib/App/Raps2/Password.pm b/lib/App/Raps2/Password.pm
index 1e33f58..1a3ab63 100644
--- a/lib/App/Raps2/Password.pm
+++ b/lib/App/Raps2/Password.pm
@@ -11,6 +11,103 @@ use Crypt::Eksblowfish::Bcrypt qw(bcrypt_hash en_base64 de_base64);
our $VERSION = '0.3';
+sub new {
+ my ( $obj, %conf ) = @_;
+
+ $conf{cost} //= 12;
+
+ if ( not defined $conf{salt} ) {
+ $conf{salt} = create_salt();
+ }
+
+ if ( length( $conf{salt} ) != 16 ) {
+ confess('incorrect salt length');
+ }
+
+ if ( not( defined $conf{passphrase} and length $conf{passphrase} ) ) {
+ confess('no passphrase given');
+ }
+
+ my $ref = \%conf;
+
+ return bless( $ref, $obj );
+}
+
+sub create_salt {
+ my ($self) = @_;
+ my $salt = q{};
+
+ for ( 1 .. 16 ) {
+ $salt .= chr( 0x21 + int( rand(90) ) );
+ }
+
+ return $salt;
+}
+
+sub salt {
+ my ( $self, $salt ) = @_;
+
+ if ( defined $salt ) {
+ if ( length($salt) != 16 ) {
+ confess('incorrect salt length');
+ }
+
+ $self->{salt} = $salt;
+ }
+
+ return $self->{salt};
+}
+
+sub encrypt {
+ my ( $self, $in ) = @_;
+
+ my $eksblowfish = Crypt::Eksblowfish->new( $self->{cost}, $self->{salt},
+ $self->{passphrase}, );
+ my $cbc = Crypt::CBC->new( -cipher => $eksblowfish );
+
+ return $cbc->encrypt_hex($in);
+}
+
+sub decrypt {
+ my ( $self, $in ) = @_;
+
+ my $eksblowfish = Crypt::Eksblowfish->new( $self->{cost}, $self->{salt},
+ $self->{passphrase}, );
+ my $cbc = Crypt::CBC->new( -cipher => $eksblowfish );
+
+ return $cbc->decrypt_hex($in);
+}
+
+sub bcrypt {
+ my ($self) = @_;
+
+ return en_base64(
+ bcrypt_hash(
+ {
+ key_nul => 1,
+ cost => $self->{cost},
+ salt => $self->{salt},
+ },
+ $self->{passphrase},
+ )
+ );
+}
+
+sub verify {
+ my ( $self, $testhash ) = @_;
+
+ my $myhash = $self->bcrypt();
+
+ if ( $testhash eq $myhash ) {
+ return 1;
+ }
+ confess('Passwords did not match');
+}
+
+1;
+
+__END__
+
=head1 NAME
App::Raps2::Password - Password class for App::Raps2
@@ -23,7 +120,7 @@ App::Raps2::Password - Password class for App::Raps2
passphrase => 'secret',
);
- my $oneway_hash = $raps2->crypt();
+ my $oneway_hash = $raps2->bcrypt();
$raps2->verify($oneway_hash);
my $twoway_hash = $raps2->encrypt('data');
@@ -34,6 +131,10 @@ App::Raps2::Password - Password class for App::Raps2
This manual documents B<App::Raps2::Password> version 0.3
+=head1 DESCRIPTION
+
+App::Raps2::Pasword is a wrapper around Crypt::Eksblowfish.
+
=head1 METHODS
=over
@@ -60,153 +161,47 @@ generates its own.
=back
-=cut
-
-sub new {
- my ($obj, %conf) = @_;
-
- $conf{cost} //= 12;
-
- if (not defined $conf{salt}) {
- $conf{salt} = create_salt();
- }
-
- if (length($conf{salt}) != 16) {
- confess('incorrect salt length');
- }
-
- if (not (defined $conf{passphrase} and length $conf{passphrase})) {
- confess('no passphrase given');
- }
-
- my $ref = \%conf;
-
- return bless($ref, $obj);
-}
-
=item $pass->create_salt()
Returns a new 16-byte salt. Contains only printable characters.
-=cut
-
-sub create_salt {
- my ($self) = @_;
- my $salt = q{};
-
- for (1 .. 16) {
- $salt .= chr(0x21 + int(rand(90)));
- }
-
- return $salt;
-}
-
=item $pass->salt([I<salt>])
Returns the currently used salt and optionally changes it to I<salt>.
-=cut
-
-sub salt {
- my ($self, $salt) = @_;
-
- if (defined $salt) {
- if (length($salt) != 16) {
- confess('incorrect salt length');
- }
-
- $self->{salt} = $salt;
- }
-
- return $self->{salt};
-}
-
=item $pass->encrypt(I<data>)
Encrypts I<data> with the passphrase saved in the object, returns the
corresponding hexadecimal hash (as string).
-=cut
-
-sub encrypt {
- my ($self, $in) = @_;
-
- my $eksblowfish = Crypt::Eksblowfish->new(
- $self->{cost},
- $self->{salt},
- $self->{passphrase},
- );
- my $cbc = Crypt::CBC->new(-cipher => $eksblowfish);
-
- return $cbc->encrypt_hex($in);
-}
-
=item $pass->decrypt(I<hexstr>)
Decrypts I<hexstr> (as created by B<encrypt>), returns its original content.
-=cut
-
-sub decrypt {
- my ($self, $in) = @_;
-
- my $eksblowfish = Crypt::Eksblowfish->new(
- $self->{cost},
- $self->{salt},
- $self->{passphrase},
- );
- my $cbc = Crypt::CBC->new(-cipher => $eksblowfish);
-
- return $cbc->decrypt_hex($in);
-}
-
-=item $pass->crypt()
+=item $pass->bcrypt()
Return a base64 bcrypt hash of the password, salted with the salt.
-=cut
-
-sub crypt {
- my ($self) = @_;
-
- return en_base64(
- bcrypt_hash({
- key_nul => 1,
- cost => $self->{cost},
- salt => $self->{salt},
- },
- $self->{passphrase},
- ));
-}
-
=item $pass->verify(I<hash>)
Verify a hash as returned by B<crypt>.
Returns true if it matches, dies if it doesn't.
-=cut
-
-sub verify {
- my ($self, $testhash) = @_;
-
- my $myhash = $self->crypt();
+=back
- if ($testhash eq $myhash) {
- return 1;
- }
- confess('Passwords did not match');
-}
+=head1 DIAGNOSTICS
-1;
+When anything goes wrong, App::Raps2::Password will use Carp(3pm)'s B<confess>
+method to die with a backtrace.
-__END__
+=head1 DEPENDENCIES
-=back
+Crypt::CBC(3pm), Crypt::Eksblowfish(3pm).
-=head1 DEPENDENCIES
+=head1 BUGS AND LIMITATIONS
-B<Crypt::CBC>, B<Crypt::Eksblowfish>.
+Unknown.
=head1 SEE ALSO