http://www.perlmonks.org?node_id=844289

Update: replaced Crypt::Lite with the more secure Crypt::CBC thank to ikegami.

Hello everyone. After my ToDo Manager, I also want to share with you a simple script that I use to manage my passwords.

It provides a simple encryption using the Crypt::Lite module (I know it is not one of the most secure encryption module, but is is quite easy to use and install, if you want to add more secure encryption, you are completely free to do so) and simple 'add' and 'list' methods.

More info are available in the POD section.

Hope you'll find it useful.

#!/usr/bin/perl # Simple command-line password manager. # # Copyright 2010 Alessandro Ghedini <al3xbio@gmail.com> # -------------------------------------------------------------- # "THE BEER-WARE LICENSE" (Revision 42): # Alessandro Ghedini wrote this file. As long as you retain this # notice you can do whatever you want with this stuff. If we # meet some day, and you think this stuff is worth it, you can # buy me a beer in return. # -------------------------------------------------------------- # # Portions written by ikegami are public domain. use strict; use warnings; use Crypt::CBC; use constant SIG => "SUCCESS"; die "For info type 'perldoc $0'\n" unless $#ARGV >= 0; my $default_pwd; if ($^O eq 'MSWin32') { $default_pwd = $ENV{USERPROFILE}."\\passwd.txt"; } else { $default_pwd = $ENV{HOME}."/.passwd"; } my $pwdfile = $ENV{PWD_FILE} ? $ENV{PWD_FILE} : $default_pwd; print("Password: "); system('stty','-echo') if $^O eq 'linux'; chop(my $passphrase = <STDIN>); system('stty','echo') if $^O eq 'linux'; print "\n"; my $cipher = Crypt::CBC->new( -cipher => 'Blowfish', -key => $passphrase, ); my $action = $ARGV[0]; if ($action eq 'add') { my $data = read_file($cipher, $pwdfile); print "Account Name: "; chop(my $account = <STDIN>); print "Account Login: "; chop(my $login = <STDIN>); print "Account Password: "; chop(my $password = <STDIN>); my $new_string = "$account - $password ($login)\n"; $data .= $new_string; write_file($cipher, $pwdfile, $data); } elsif ($action eq 'ls') { my $grep = $ARGV[1] ? $ARGV[1] : "(.*?)"; my $data = read_file($cipher, $pwdfile); my @pwds = sort split("\n", $data); foreach (@pwds) { next unless $_ =~ m/$grep/; $_ =~ m/(.*?) - (.*?) \((.*?)\)/; my $title = $1; my $user = $3; my $pwd = $2; print $title."\nUser: ".$user."\nPassword: ".$pwd."\n"; } } elsif ($action eq 'rm') { my $grep = $ARGV[1] ne "" ? $ARGV[1] : ""; my $data = read_file($cipher, $pwdfile); my @pwds = split "\n", $data; my $i = -1; foreach (@pwds) { $i++; next unless $_ =~ m/$grep/; $_ =~ m/(.*?) - (.*?) \((.*?)\)/; print "Delete '$1'? [y/n] "; chop(my $command = <STDIN>); next unless $command eq 'y'; splice(@pwds, $i, 1); } $data = (join "\n", @pwds)."\n"; write_file($cipher, $pwdfile, $data); } else { print "ERROR: Invalid action '$action'.\n"; print "Type 'perldoc $0' for manual\n"; } sub read_file { my ($cipher, $qfn) = @_; open(my $fh, '<:bytes', $qfn) or die("Cannot open $qfn: $!\n"); my $file; { local $/; $file = <$fh>; } return if $file eq ""; $file = $cipher->decrypt($file); die("Wrong password\n") if substr($file, 0, length(SIG), '') ne SI +G; return $file; } sub write_file { my ($cipher, $qfn, $file) = @_; open(my $fh, '>:bytes', $qfn) or die("Cannot create file $qfn: $!\n"); print($fh $cipher->encrypt(SIG . $file)); } __END__ =head1 NAME Password - A simple command-line password manager. =head1 USAGE B<Password> I<ACTION> I<ARGS> =head1 ACTIONS =over =item B<add> Add a new account in the password file. The user will be asked interac +tively for all the information (account name, login and password) needed. =item B<rm ACCOUNT> Remove the ACCOUNT account. =item B<ls TERM> Show accounts that contain TERM. If no TERM specified, the entire list is showed. =back =head1 CONFIGURATION Set PWD_FILE environment variable, to your password file location. Default ~/.passwd. =head1 ENCRYPTION Blowfish encryption is used, with proper salting and chaining. =cut
Alex's Log - http://alexlog.co.cc

Replies are listed 'Best First'.
Re: Password Manager
by ikegami (Patriarch) on Jun 11, 2010 at 20:20 UTC

    I know it is not one of the most secure encryption module, but is is quite easy to use and install, if you want to add more secure encryption, you are completely free to do so

    The lack of the word "salt" in the source worries me. In combination with the fact that it can tell whether the decrypt was successful, I suspect very weak encoding.

    It's just as easy to use something better:

    use Crypt::CBC; my $cipher = Crypt::CBC->new( -key => $passphrase, -cipher => 'Blowfish', ); my $cipher_text = $cipher->encrypt($plain_text);

    Adapted:

    #!/usr/bin/perl # Simple command-line password manager. # # Copyright 2010 Alessandro Ghedini <al3xbio@gmail.com> # -------------------------------------------------------------- # "THE BEER-WARE LICENSE" (Revision 42): # Alessandro Ghedini wrote this file. As long as you retain this # notice you can do whatever you want with this stuff. If we # meet some day, and you think this stuff is worth it, you can # buy me a beer in return. # -------------------------------------------------------------- # # Portions written by ikegami are public domain. use strict; use warnings; use Crypt::CBC; use constant SIG => "SUCCESS"; die "For info type 'perldoc $0'\n" unless $#ARGV >= 0; my $default_pwd; if ($^O eq 'MSWin32') { $default_pwd = $ENV{USERPROFILE}."\\passwd.txt"; } else { $default_pwd = $ENV{HOME}."/.passwd"; } my $pwdfile = $ENV{PWD_FILE} ne "" ? $ENV{PWD_FILE} : $default_pwd; print("Password: "); system('stty','-echo') if $^O eq 'linux'; chop(my $passphrase = <STDIN>); system('stty','echo') if $^O eq 'linux'; print "\n"; my $cipher = Crypt::CBC->new( -cipher => 'Blowfish' -key => $passphrase, ); my $action = $ARGV[0]; if ($action eq 'add') { my $data = read_file($crypt, $pwdfile); print "Account Name: "; chop(my $account = <STDIN>); print "Account Login: "; chop(my $login = <STDIN>); print "Account Password: "; chop(my $password = <STDIN>); my $new_string = "$account - $password ($login)\n"; $data .= $new_string; write_file($crypt, $pwdfile, $data); } elsif ($action eq 'ls') { my $grep = $ARGV[1] ne "" ? $ARGV[1] : "(.*?)"; my $data = read_file($crypt, $pwdfile); my @pwds = sort split("\n", $data); foreach (@pwds) { next unless $_ =~ m/$grep/; $_ =~ m/(.*?) - (.*?) \((.*?)\)/; my $title = $1; my $user = $3; my $pwd = $2; print $title."\nUser: ".$user."\nPassword: ".$pwd."\n"; } } elsif ($action eq 'rm') { my $grep = $ARGV[1] ne "" ? $ARGV[1] : ""; my $data = read_file($crypt, $pwdfile); my @pwds = split "\n", $data; my $i = -1; foreach (@pwds) { $i++; next unless $_ =~ m/$grep/; $_ =~ m/(.*?) - (.*?) \((.*?)\)/; print "Delete '$1'? [y/n] "; chop(my $command = <STDIN>); next unless $command eq 'y'; splice(@pwds, $i, 1); } $data = (join "\n", @pwds)."\n"; write_file($crypt, $pwdfile, $data); } else { print "ERROR: Invalid action '$action'.\n"; print "Type 'perldoc $0' for manual\n"; } sub read_file { my ($cipher, $qfn) = @_; open(my $fh, '<:bytes', $qfn") or die("Cannot open $qfn: $!\n"); my $file; { local $/; $file = <$fh>; } $file = $cipher->decrypt($file); die("Wrong password\n") if substr($file, 0, length(SIG), '') ne SI +G; return $file; } sub write_file { my ($cipher, $qfn, $file) = @_; open(my $fh, '>:bytes', $qfn") or die("Cannot create file $qfn: $!\n"); print($fh $cipher->encrypt(SIG . $file)); } __END__ =head1 NAME Password - A simple command-line password manager. =head1 USAGE B<Password> I<ACTION> I<ARGS> =head1 ACTIONS =over =item B<add> Add a new account in the password file. The user will be asked interac +tively for all the information (account name, login and password) needed. =item B<rm ACCOUNT> Remove the ACCOUNT account. =item B<ls TERM> Show accounts that contain TERM. If no TERM specified, the entire list + is showed. =back =head1 CONFIGURATION Set PWD_FILE environment variable, to your password file location. Default ~/.passwd. =head1 ENCRYPTION Blowfish encryption is used, with proper salting and chaining. =cut

    Untested.

      Thank you very much for the help. I've fixed some issues with your code, and updated the main node.

      Tomorrow I'll do more test, now it's time for bed.

      Alex's Log - http://alexlog.co.cc
Re: Password Manager
by jwkrahn (Abbot) on Jun 12, 2010 at 04:36 UTC
    foreach (@pwds) { $i++; next unless $_ =~ m/$grep/; $_ =~ m/(.*?) - (.*?) \((.*?)\)/; print "Delete '$1'? [y/n] "; chop(my $command = <STDIN>); next unless $command eq 'y'; splice(@pwds, $i, 1); }

    From the "Foreach Loops" section of perlsyn:

    If any part of LIST is an array, "foreach" will get very confused if you add or remove elements within the loop body, for example with "splice". So don't do that.