App-PasswordManager
view release on metacpan or search on metacpan
lib/App/PasswordManager.pm view on Meta::CPAN
package App::PasswordManager;
use strict;
use warnings;
use Crypt::PBKDF2;
use File::HomeDir;
use File::Spec;
use JSON;
our $VERSION = '1.0.0';
sub new {
my ( $class, %args ) = @_;
my $home_dir = File::HomeDir->my_home;
my $file = File::Spec->catfile( $home_dir, '.password_manager.json' );
my $self = {
pbkdf2 => Crypt::PBKDF2->new(
hash_class => 'HMACSHA1',
iterations => 10000,
salt_len => 10,
),
data_file => $args{file} || $file,
salt => 42,
passwords => {},
};
bless $self, $class;
$self->_load_passwords();
return $self;
}
sub add_password {
my ( $self, $login, $password ) = @_;
die "Login '$login' already exists!\n" if exists $self->{passwords}{$login};
my $hashed_password = $self->{pbkdf2}->generate( $password, $self->{salt} );
$self->{passwords}{$login} = {
password => $hashed_password,
salt => $self->{salt},
};
$self->_save_passwords();
return scalar keys %{ $self->{passwords} };
}
sub list_passwords {
my ($self) = @_;
return [ keys %{ $self->{passwords} } ];
}
sub remove_password {
my ( $self, $login ) = @_;
die "Login '$login' not found!\n" unless exists $self->{passwords}{$login};
delete $self->{passwords}{$login};
$self->_save_passwords();
return 1;
}
sub edit_password {
my ( $self, $login, $new_password ) = @_;
die "Login '$login' not found!\n" unless exists $self->{passwords}{$login};
my $hashed_password = $self->{pbkdf2}->generate( $new_password, $self->{salt} );
$self->{passwords}{$login}{password} = $hashed_password;
$self->{passwords}{$login}{salt} = $self->{salt};
$self->_save_passwords();
return 1;
}
sub copy_to_clipboard {
my ( $self, $login ) = @_;
die "Login '$login' not found!\n" unless exists $self->{passwords}{$login};
my $password = $self->{passwords}{$login}{password};
open my $clip, '|-', 'xclip -selection clipboard'
or die "Could not copy: $!";
print $clip $password;
close $clip;
return 1;
}
( run in 1.392 second using v1.01-cache-2.11-cpan-96521ef73a4 )