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 )